之前铺垫了许多,今天可以来分享点纯干货了。

上一篇已经讲述了通过面模拟线条时候,每一个顶点的顶点数据包括:端点坐标、偏移量、前一个端点坐标、后一个端点坐标,当然如果我们通过索引的方式来绘制的话,还包括索引数组,下面的代码通过传递一组线条的端点数组来创建上述相关数据:

bk.Line3D = function (points,colors){this.points = points;this.colors = colors;
}bk.Line3D.prototype.computeData = function() {var len = this.points.length;var count = len * 3 * 2;    var position = new Float32Array(count);var positionPrev =  new Float32Array(count);var positionNext = new Float32Array(count);var color = new Float32Array(count);var offset = new Float32Array(len * 2);var indicesCount = 3 * 2 * (len - 1);var indices = new Uint16Array(indicesCount);var triangleOffset = 0,vertexOffset = 0;for(var i = 0; i < len; i ++){var i3 = i * 3 * 2;var point = this.points[i];position[i3 + 0] = point.x;position[i3 + 1] = point.y;position[i3 + 2] = point.z;position[i3 + 3] = point.x;position[i3 + 4] = point.y;position[i3 + 5] = point.z;var r = (i + 1) / len;var g = Math.random();var b = Math.random();g = r;b = 0;r =  1- r;color[i3 + 0] = r;color[i3 + 1] = g;color[i3 + 2] = b;color[i3 + 3] = r;color[i3 + 4] = g;color[i3 + 5] = b;if (i < count - 1) {var i3p = i3 + 6;positionNext[i3p + 0] = point.x;positionNext[i3p + 1] = point.y;positionNext[i3p + 2] = point.z;positionNext[i3p + 3] = point.x;positionNext[i3p + 4] = point.y;positionNext[i3p + 5] = point.z;}if (i > 0) {var i3n = i3 - 6;positionPrev[i3n + 0] = point.x;positionPrev[i3n + 1] = point.y;positionPrev[i3n + 2] = point.z;positionPrev[i3n + 3] = point.x;positionPrev[i3n + 4] = point.y;positionPrev[i3n + 5] = point.z;}var idx = 3 * i;var i2 = i * 2;offset[i2 + 0]  = 5;offset[i2 + 1]  = -5;}var end = count - 1;for(i = 0;i < 6 ;i ++){positionNext[i] = positionNext[i + 6];positionPrev[end - i] = positionPrev[end - i - 6];}for(i = 0;i < indicesCount ;i ++){if(i % 2 == 0){indices[triangleOffset ++] = i;indices[triangleOffset ++] = i + 1;indices[triangleOffset ++] = i + 2;}else{indices[triangleOffset ++] = i + 1;indices[triangleOffset ++] = i;indices[triangleOffset ++] = i + 2;}}this.position  = position;this.positionNext  = positionNext;this.positionPrev = positionPrev;this.color = color;this.offset = offset;this.indices = indices;
};

代码首先定义了一个类,该类构造函数可以传入端点数组;在该类上定义了一个方法 computeData,用来计算顶点数组,每个顶点包括上文所述的4个信息,另外增加了一个颜色信息。
读者,可以结合第二篇的思路和上面的代码来来理解,此处不再详述 代码的细节。

另外一个比较重要的代码是顶点着色器中,通过传入的这些顶点信息来计算最终的顶点坐标,代码如下:

var lineVS = `attribute vec3 aPosition;attribute vec3 aPositionPre;attribute vec3 aPositionNext;attribute float aOffset;attribute vec3 aColor;varying  vec3  vColor;uniform mat4 uWorldViewProjection;uniform vec4 uViewport;uniform float uNear;uniform mat4 uViewMatrix;uniform mat4 uProjectMatrix;vec4 clipNear(vec4 p1,vec4 p2){float n = (p1.w - uNear) / (p1.w - p2.w);return vec4(mix(p1.xy,p2.xy,n),-uNear,uNear);}void main(){vec4 prevProj = uWorldViewProjection * vec4(aPositionPre, 1.0);vec4 currProj = uWorldViewProjection * vec4(aPosition, 1.0);vec4 nextProj = uWorldViewProjection * vec4(aPositionNext, 1.0);if (currProj.w < 0.0) {if (prevProj.w < 0.0) {currProj = clipNear(currProj, nextProj);}else {currProj = clipNear(currProj, prevProj);}}vec2 prevScreen = (prevProj.xy / abs(prevProj.w) + 1.0) * 0.5 * uViewport.zw;vec2 currScreen = (currProj.xy / abs(currProj.w) + 1.0) * 0.5 * uViewport.zw;vec2 nextScreen = (nextProj.xy / abs(nextProj.w) + 1.0) * 0.5 * uViewport.zw;vec2 dir;float len = aOffset;if(aPosition == aPositionPre){dir = normalize(nextScreen - currScreen);}else if(aPosition == aPositionNext){dir = normalize(currScreen - prevScreen);}else {vec2 dirA = normalize(currScreen - prevScreen);vec2 dirB = normalize(nextScreen - currScreen);vec2 tanget = normalize(dirA + dirB);float miter = 1.0 / max(dot(tanget,dirA),0.5);len *= miter;dir = tanget;}dir = vec2(-dir.y,dir.x) * len;currScreen += dir;currProj.xy = (currScreen / uViewport.zw - 0.5) * 2.0 * abs(currProj.w);vec4 pos = uProjectMatrix * uViewMatrix *  vec4(aPosition,1.0);vColor = aColor;gl_Position = currProj;}
`; 

计算的原理,也可以参考第二篇的论述,此处需要注意的是,为了能够计算顶点在屏幕上的最终位置,需要把canvans的尺寸大小传递给着色器(uniform 变量 uViewport),同样为了计算裁剪,需要把镜头的near值传递给着色器(uniform 变量 uNear),而变量uWorldViewProjection表示模型视图透视变换的矩阵,熟悉WebGL的同学一定清楚。

如果你对WebGL 感兴趣,可以了解下我们用WebGL开发的3D机房项目:

无插件纯Web 3D机房,HTML5+WebGL倾力打造

关于这个话题就先分享到这里了,如果大家对其它方面与兴趣的,我们也可以一起来探讨。

转载于:https://www.cnblogs.com/twaver/p/7238364.html

WebGL 绘制Line的bug(三)相关推荐

  1. WebGL 绘制Line的bug(一)

    插播一则广告(长期有效) MONO哥需要在武汉招JavaScript工程师若干 要求:对前端技术(JavasScript.HTML.CSS),对可视化技术(Canvas.WebGL)有浓厚的兴趣 基础 ...

  2. 【视觉高级篇】20 # 如何用WebGL绘制3D物体?

    说明 [跟月影学可视化]学习笔记. 如何用 WebGL 绘制三维立方体 我们知道立方体有8个顶点,6个面,在 WebGL 中,需要用 12 个三角形来绘制它.把每个面的顶点分开,需要 24 个顶点. ...

  3. 用webgl绘制一个彩色旋转立方体

    #用webgl绘制一个旋转立方体 ** 学习交流欢迎加群:789723098,博主会将一些demo整理共享 ** 今天给大家分享一个用webgl写的简单的三维场景:转动的交互式彩色立方体,其六个面的颜 ...

  4. 【图形基础篇】04 # GPU与渲染管线:如何用WebGL绘制最简单的几何图形?

    说明 [跟月影学可视化]学习笔记. 图形系统是如何绘图的? 一个通用计算机图形系统主要包括 6 个部分,分别是: 输入设备 中央处理单元:首先,数据经过 CPU 处理,成为具有特定结构的几何信息. 图 ...

  5. WebGL绘制立方体-每个面一种颜色

    WebGL绘制立方体-每个面一种颜色 本文是WebGL电子书的1.8节内容 思路很简单,在线框模式的立方体源码基础上直接进行更改,添加varying变量,引入顶点数据颜色,立方体6个面,每个面可以分为 ...

  6. WebGL绘制带箭头贴图的线

    示例 在讲述本文内容之前,我希望读者先具备以下知识点: 了解WebGL的基本知识,懂得调用自定义的Shader程序: 基本的数学基础和空间几何知识: 明白GPU的渲染管线流程: 因为,本文内容主要讲述 ...

  7. 三线表是什么?R语言使用table1包绘制(生成)三线表、构建不分层的三线表

    三线表是什么?R语言使用table1包绘制(生成)三线表.构建不分层的三线表 目录

  8. R语言使用table1包绘制(生成)三线表、使用单变量分列构建三线表、编写自定义函数在三线表中添加p值

    R语言使用table1包绘制(生成)三线表.使用单变量分列构建三线表.编写自定义函数在三线表中添加p值 目录

  9. R语言使用table1包绘制(生成)三线表、使用单变量分列构建三线表、设置transpose参数转置三线表、变量作为列,子组(strata)作为行

    R语言使用table1包绘制(生成)三线表.使用单变量分列构建三线表.设置transpose参数转置三线表.变量作为列,子组(strata)作为行 目录

  10. R语言使用table1包绘制(生成)三线表、使用单变量分列构建三线表、自定义overall的标签名称

    R语言使用table1包绘制(生成)三线表.使用单变量分列构建三线表.自定义overall的标签名称 目录

最新文章

  1. SEO优化简要工作流程
  2. 白名单 权限认证方法
  3. boost::fusion::unfused_typed用法的测试程序
  4. sql视图语句_SQL视图:Replace View语句的示例语法
  5. pc wifi 软件 模拟串口_唐山现代新型物联网软件
  6. python中字符串:声明、编码、函数、格式化
  7. Linux查看进程是否占用,Linux 下查看哪个进程占用swap空间
  8. C# Thread.Sleep 导致内存溢出,在多线程里Sleep的真实情况 软件闪退 内存溢出
  9. equalizer android,全球最佳十大安卓均衡器
  10. 解压文件-提示:“必要的压缩卷不存在”
  11. 文档数据防泄密需求分析
  12. c语言 函数 引用调用,C 引用方式调用函数
  13. CReLU与PReLU的大体简介
  14. Linux实战教学笔记28:企业级LNMP环境应用实践
  15. 【docker问题】Client.Timeout exceeded while awaiting header
  16. 把飞书融入日常学习流程:一个人的飞书也挺好
  17. 五年后中国将进入高收入国家行列?
  18. php excel导入数组,利用PHPExcel导入xlsx/xls,将xlsx、xls转换为数组
  19. Chrome主题下载网站安装简单教程
  20. yylabel html富文本,YYLabel 自动布局 富文本文字点击事件

热门文章

  1. 46张PPT彻底弄懂JVM、GC算法和性能调优!
  2. 中国顶级程序员有多牛?一个弄哭韩国,一个堪称阿里“扫地僧”
  3. 微服务架构实战(二):使用API Gateway
  4. 基于netty实现socketio的聊天室
  5. 如果计算机是中国人发明的,那编程代码很可能就应该这样写!
  6. 解读龙哥的书:用户是什么?
  7. 中国的 GitHub 要来了?
  8. 移动端适配的理解——REM方案
  9. Deepin下安装搭建latex编写环境
  10. 开机启动项快捷方式所在的目录