WebGL画粗线

目录

前言 

基本思路

求左右端点

实现

组织数据

顶点着色器计算端点坐标 

效果


前言 

WebGL绘制模式有点、线、面三种;通过点的绘制可以实现粒子系统等,通过线可以绘制一些连线关系;面就强大了,通过面,我们可以绘制我们想绘制的所有的三维对象。然而,WebGL在绘制线条的时候,存在一个缺陷,那就是在一些机器的一些浏览器上面(大多数情况下)线宽只能设置为1,而不能设置成其他的值。

http://alteredqualia.com/tmp/webgl-linewidth-test/,可以测试自己的电脑是否可以绘制粗线

可以看出,我的Chrome有这个 问题

 

基本思路

既然画线实现不了加粗,那就使用面来模拟粗线。

如下,一条线 p0 p1 构成,可算出两个点的左右两个端点0 1 、 2 3,这四个端点组成两个三角形

求左右端点

  1. 二维向量(x, y)的法向量为(-y, x),为方便后续平移操作,将法向量标准化为单位向量;
  2. 通过平移变换将p0、p1沿上述得到法向量正向平移width/2得到点0、1,沿法向量反向平移width/2得到点2、3。
     

但是,这样简单粗暴的求法向量会有问题,如下图,多个线段间会有冗余分割线条

为了消除节点处的可见分割,有必要将相邻节段的相邻点组合起来,以保持相邻节段两个节段的厚度。要做到这一点,需要更进一步的求法向量

如下图,用last、current、next表示前、当前、后三个点,算出当前now点的切线方向(黄色),切线方向乘以复数i,逆时针旋转90就为法线方向,乘以复数-i,顺时针旋转90度为负法线方向,则有了Normal和-Normal(紫色)。Normal和-Normal分别乘以宽度的一半,即可求出每个点的左右端点

将端点坐标写入WebGL顶点坐标缓冲区,另外通过索引[0, 1, 3, 1, 2, 3]来表示两个三角形的顶点序号写入WebGL索引缓冲区,调用gl.drawElements绘制出带线宽的直线。 

实现

事实上,计算左右端点的操作应该发生在顶点着色器中的,而且也只能在着色器中计算,因为最终显示到屏幕上的顶点与镜头相关,上述只是简单的用了2维的情况模拟,如果在js端计算,将极大消耗性能。 

组织数据

组织要传给着色器的数据:position、prevPositions、nextPositions、side

比如,三个点 p0 p1 p2,要组织数据的形式:

position = [p0, p0, p1, p1, p2, p2]

prevPositions = [p0, p0, p0, p0, p1, p1]

nextPositions= [p1, p1, p2, p2, p2, p2]

side = [1, -1, 1, -1, 1, -1]

    let geometry = new THREE.BufferGeometry()let vertices = []let count = vertices.lengthlet prevPositions = new Float32Array(count * 3 * 2)let nextPositions = new Float32Array(count * 3 * 2)let side = new Float32Array(count * 2)let position = new Float32Array(count * 3 * 2)let indexes = new Uint16Array(6 * (count - 1))for (let j = 0; j < count * 2; j += 2) {// sideside[j] = 1side[j + 1] = -1// indexlet current = vertices[j / 2]let prev = vertices[(j === 0 ? j : j - 2) / 2]let next = vertices[(j === (count - 1) * 2 ? j : j + 2) / 2]// positionposition[j * 3] = current.xposition[j * 3 + 1] = current.yposition[j * 3 + 2] = current.zposition[j * 3 + 3] = current.xposition[j * 3 + 4] = current.yposition[j * 3 + 5] = current.z// prevprevPositions[j * 3] = prev.xprevPositions[j * 3 + 1] = prev.yprevPositions[j * 3 + 2] = prev.zprevPositions[j * 3 + 3] = prev.xprevPositions[j * 3 + 4] = prev.yprevPositions[j * 3 + 5] = prev.z// nextnextPositions[j * 3] = next.xnextPositions[j * 3 + 1] = next.ynextPositions[j * 3 + 2] = next.znextPositions[j * 3 + 3] = next.xnextPositions[j * 3 + 4] = next.ynextPositions[j * 3 + 5] = next.z}for (let i = 0; i < count * 2 - 2; i += 2) {indexes[6 * (i - i / 2)] = iindexes[6 * (i - i / 2) + 1] = i + 1indexes[6 * (i - i / 2) + 2] = i + 2indexes[6 * (i - i / 2) + 3] = i + 2indexes[6 * (i - i / 2) + 4] = i + 1indexes[6 * (i - i / 2) + 5] = i + 3}geometry.setAttribute('position', new THREE.BufferAttribute(position, 3))geometry.setAttribute('prevPositions', new THREE.BufferAttribute(prevPositions, 3))geometry.setAttribute('nextPositions', new THREE.BufferAttribute(nextPositions, 3))geometry.setAttribute('side', new THREE.BufferAttribute(side, 1))geometry.index = new THREE.BufferAttribute(indexes, 1)

 

顶点着色器计算端点坐标 

正如上述 计算左右端点方法  两个点为单位轮回;算出法向量乘以side,得到最终的正负法线方向

需要注意的是,为了能够计算顶点在屏幕上的最终位置,需要把canvans的尺寸大小传递给着色器

    <script id="vertexShader" type="x-shader/x-vertex">attribute float side;attribute vec3 prevPositions;attribute vec3 nextPositions;uniform float width;uniform vec2 resolution;void main(){float aspect = resolution.x / resolution.y;mat4 pvm = projectionMatrix * modelViewMatrix;vec4 currentV4 = pvm * vec4(position, 1.0);vec4 prevV4 = pvm * vec4(prevPositions, 1.0);vec4 nextV4 = pvm * vec4(nextPositions, 1.0);vec2 currentV2 = currentV4.xy / currentV4.w;vec2 prevV2 = prevV4.xy / prevV4.w;vec2 nextV2 = nextV4.xy / nextV4.w;vec2 dir1 = normalize(nextV2 - currentV2);vec2 dir2 = normalize(currentV2 - prevV2);vec2 dir = normalize(dir1 + dir2);vec2 normal = vec2( -dir.y, dir.x );normal.x /= aspect;normal *= width;normal /= resolution.y;currentV4.xy += (normal * side) * currentV4.w;gl_Position = currentV4;}</script>

效果

export default [  {x:  0.2980022405076852, y:  0.0007317477689525731, z:  1},{x:  1.1869354597466781, y:  0.0009180096778322877, z:  0},{x:  2.0758235116605874, y:  0.0012041573064607292, z:  1},{x:  2.9647108701853995, y:  0.0016485209298480186, z:  1},{x:  3.8535979009456014, y:  0.002361701064614863, z:  0},{x:  4.7424853104305384, y:  0.00351269568443513, z:  0},{x:  5.631373663413683, y:  0.005294665597602943, z:  1},{x:  6.520261987572894, y:  0.007922778765419025, z:  0},{x:  7.409147752210174, y:  0.01167311915872915, z:  2},{x:  8.298025451981857, y:  0.016846610763536773, z:  0},{x:  9.186886934688118, y:  0.023772568206652522, z:  -1},{x:  10.07571907490967, y:  0.0328001040410868, z:  0},{x:  10.964496398756296, y:  0.044288140005107834, z:  5},{x:  11.85319602294021, y:  0.05862768318564804, z:  10},{x:  12.741786244815671, y:  0.07613330348408454, z:  0},{x:  13.630226377381064, y:  0.09712025624207854, z:  20},{x:  14.518501144938796, y:  0.12186988355398398, z:  1},{x:  15.406618008779674, y:  0.15055661742513848, z:  0},{x:  16.294597333615457, y:  0.18321126049687564, z:  1},{x:  17.182483414117996, y:  0.21982671919579388, z:  0},{x:  18.07027996070667, y:  0.26025710620086784, z:  0},{x:  18.957985046609565, y:  0.3042638844103749, z:  2},{x:  19.845588805245143, y:  0.35157055005709026, z:  20},{x:  20.733061996025413, y:  0.40187981369570025, z:  12},{x:  21.620398578083382, y:  0.4548763144693453, z:  0},{x:  22.50759421058183, y:  0.510277754478011, z:  0},{x:  23.394649626125783, y:  0.5678463420269395, z: 10},{x:  24.28156938481652, y:  0.6273966818090457, z:  10},{x:  25.16835632444645, y:  0.6887999401383809, z:  0},{x:  26.055014124105355, y:  0.7520044141307949, z:  2},{x:  26.94154278405199, y:  0.8170242843056599, z:  0},{x:  27.827935344684192, y:  0.8839563938809647, z:  2},{x:  28.71418144341419, y:  0.9530044273309386, z:  4},{x:  29.60025448188958, y:  1.0244047577025412, z:  0},{x:  30.486116503444237, y:  1.0984849046006389, z: 50},{x:  31.371726404611536, y:  1.175603041504246, z:  6},{x:  32.25701896209273, y:  1.2562969882843618, z:  4},{x:  33.14193521146046, y:  1.3409977805800963, z:  10},{x:  34.0263999228323, y:  1.4302624318554535, z:  0},{x:  34.91033330314474, y:  1.5245805770430252, z:  0},{x:  35.79361266847275, y:  1.6247205249796934, z:  0},{x:  36.676130186271166, y:  1.7312884009689355, z:  0},{x:  37.557760528031736, y:  1.844910698533738, z:  2},{x:  38.43832338116283, y:  1.9663458748508447, z:  0},{x:  39.31764605054343, y:  2.0958906489368587, z:  0},{x:  40.19564230123137, y:  2.234175946683024, z:  0},{x:  41.07190059501124, y:  2.3830193460015607, z:  10},{x:  41.946324364051975, y:  2.5416768732814035, z:  -20},{x:  42.81851559265749, y:  2.712179223072269, z:  0},{x:  43.688235247276, y:  2.8943826198482725, z:  -10},{x:  44.55509274214762, y:  3.089389858893753, z:  -10},{x:  45.41866612330193, y:  3.298229478551491, z:  -20}]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/22751.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

视频监控汇聚平台LntonCVS国标GB28181协议实现语音对讲功能

在当今这个智能技术飞速发展的时代&#xff0c;人工智能已经成为了电子产品领域的一股不可忽视的热门趋势。随着科技的不断进步&#xff0c;越来越多的电子产品开始融入人工智能技术&#xff0c;从而为其开拓了全新的发展路径。在这个大背景下&#xff0c;安防摄像头无插件直播…

基于springboot实现智慧校园之家长子系统项目【项目源码】计算机毕业设计

基于springboot实现智慧校园之家长子系统演示 SpringBoot框架介绍 本课题程序开发使用到的框架技术&#xff0c;英文名称缩写是SpringBoot&#xff0c;在JavaWeb开发中使用的流行框架有SSH、SpringBoot、SpringMVC等&#xff0c;作为一个课题程序采用SSH框架也可以&#xff0c…

【学习】测试用例设计与执行的黄金法则

在软件测试领域&#xff0c;测试用例的设计与执行是确保产品质量的关键环节。一个优秀的测试用例能够揭示软件中的缺陷&#xff0c;而高效的执行则能保障测试覆盖的全面性。如同璀璨的星辰指引航船前行&#xff0c;以下黄金法则将引领测试用例设计与执行的过程&#xff0c;确保…

Go 群发邮件Redis 实现邮件群发

一、安装 go get github.com/go-redis/redis/v8 go get gopkg.in/gomail.v2 二、使用"gopkg.in/gomail.v2"群发 package mainimport (gomail "gopkg.in/gomail.v2" )func main() {// 邮件内容m : gomail.NewMessage()m.SetHeader("From", &qu…

【杂谈】AIGC之Stable Diffusion:AI绘画的魔法

Stable Diffusion&#xff1a;AI绘画的魔法 引言 在AI的世界里&#xff0c;Stable Diffusion就像一位魔法师&#xff0c;它能够将我们脑海中的幻想&#xff0c;用画笔一一描绘出来。今天&#xff0c;就让我们一探这位魔法师的奥秘&#xff0c;看看它是如何从无到有&#xff0…

安装MongoDB单副本说明

参考&#xff1a;https://blog.csdn.net/weixin_43464076/article/details/126509254 https://driverzhang.github.io/post/mongo%E5%BC%80%E5%90%AF%E4%BA%8B%E5%8A%A1%E4%B9%8B%E5%89%AF%E6%9C%AC%E9%9B%86%E9%87%87%E5%9D%91/ https://dev.to/alexalvess/getting-started-wi…

实习面试题(答案自敲)、

1、为什么要重写equals方法&#xff0c;为什么重写了equals方法后&#xff0c;就必须重写hashcode方法&#xff0c;为什么要有hashcode方法&#xff0c;你能介绍一下hashcode方法吗&#xff1f; equals方法默认是比较内存地址&#xff1b;为了实现内容比较&#xff0c;我们需要…

mysql表级锁(表锁/元数据锁/意向锁)

文章目录 表级锁的分类1、表锁(分类)1.表共享读锁&#xff08;read lock&#xff09;2.表独占写锁&#xff08;write lock&#xff09;3.语法&#xff1a; 2、元数据锁&#xff08;meta data lock &#xff09;3、意向锁1.意向共享锁&#xff08;IS&#xff09;&#xff1a;由语…

【wiki知识库】05.分类管理实现--前端Vue模块

&#x1f4dd;个人主页&#xff1a;哈__ 期待您的关注 目录 一、&#x1f525;今日目标 二、&#x1f30f;前端部分的改造 2.1 新增一个tool.ts 2.2 新增admin-categoty.vue 2.3 添加新的路由规则 2.4 添加the-welcome.vue 2.5 修改HomeView.vue 三、❗注意 一、&…

车来了冲刺上市:业绩波动明显,依赖广告业务,滴滴、阿里入股

近日&#xff0c;MetaLight Inc.&#xff08;下称“元光科技”或“车来了”&#xff09;向港交所递交招股说明书&#xff0c;中金公司为其独家保荐人。 据招股书介绍&#xff0c;元光科技专注于利用时序数据&#xff08;按时间顺序排列的数据点&#xff09;来发现及预测分析对…

docker 存储 网络 命令

文章目录 1 docker存储1.1 目录挂载2.1卷映射2.1.1卷映射和目录挂载的区别2.1.2卷映射的使用 2 docker网络2.1查看docker的默认网络2.2查看容器的IP2.3容器互通2.4自定义网络2.4.1 创建自定义网络2.4.2创建容器的时候加入到自定义的网络2.4.3使用域名进行容器之间的访问2.4.4re…

盛凌电子IPO终止:实控人蒋志坚曾和前妻黄新打官司,儿子已离职

保荐人撤销&#xff0c;致使公司IPO终止。 近日&#xff0c;深圳证券交易所披露的信息显示&#xff0c;深圳盛凌电子股份有限公司&#xff08;下称“盛凌电子”&#xff09;的保荐人申万宏源证券撤回上市申请文件。因此&#xff0c;深圳证券交易所决定终止对该公司首次公开发行…

Qt报错:libvlc开发的程序,出现Direct3D output全屏窗口

问题描述&#xff1a; 在qt中开发重播模块时&#xff0c;第一次在窗口正常播放&#xff0c;点击重播按钮后会弹出新的Direct3D output窗口播放视频 分析&#xff1a; 因为libvlc_media_player_set_hwnd 这个函数 设置了不存在的窗口句柄&#xff0c;导致vlc视频播放窗口没有嵌…

kubesz(一键安装k8s)

引言 Kubernetes&#xff08;K8s&#xff09;是一个开源的容器编排系统&#xff0c;用于自动化部署、扩展和管理容器化应用程序。kubeasz 是一个用于快速搭建 Kubernetes 高可用集群的项目&#xff0c;它基于 Ansible&#xff0c;通过提供一套简单、易用的配置&#xff0c;使得…

用易查分制作活动抽奖系统,支持随机分配中奖结果!

学校或企业在开展抽奖活动时&#xff0c;如何确保公平公正&#xff0c;随机挑选中奖人员呢&#xff1f; 易查分的预置数据分配功能就可以实现&#xff0c;并且支持提交信息后随机分配中奖结果&#xff0c;不受任何人为因素的影响。下面就来教大家如何制作吧。 &#x1f4cc;使用…

ArcGIS for Vue3

二维&#xff1a; 1、创建vue项目 npm create vitelatest 2、安装ArcGIS JS API依赖包 npm install arcgis/core 3、引入ArcGIS API for JavaScript模块 <script setup> import "arcgis/core/assets/esri/themes/light/main.css"; import Map from arcgis…

HTML5+CSS3+JS小实例:网格图库

实例:网格图库 技术栈:HTML+CSS+JS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0&…

EXCEL从图片链接获取图片

step1: 选中图片地址列 step2:开发工具→Visual Basic 文件→导入 导入我制作的脚本&#xff08;代码见文章末尾&#xff09; 点击excel的小图标回到表格界面。 点击【宏】 选中刚才导入的脚本&#xff0c;点执行&#xff0c;等待完成。 代码本体&#xff1a; Sub InsertPict…

端午档新片速递《谈判专家》领衔,每日影视作品推荐❗❗❗多部佳作待映

每日影视作品推荐一、新片速递《谈判专家》上映时间&#xff1a;2024年端午档预售情况&#xff1a;已开启预售&#xff0c;并有望成为该档期的票房冠军备注&#xff1a;据猫眼专业版数据&#xff0c;该片备受期待 《我才不要和你做朋友呢》上映时间&#xff1a;2024年端午档期预…

9. MySQL事务、字符集

文章目录 【 1. 事务 Transaction 】1.1 事务的基本原理1.2 MySQL 执行事务的语法和流程1.2.1 开始事务1.2.2 提交事务1.2.3 回滚&#xff08;撤销&#xff09;事务实例1&#xff1a;一致性实例2&#xff1a;原子性 【 2. 字符集 和 校对规则 】2.1 基本原理2.2 查看字符集查看…