WebGL 绘制Line的bug(三)

简介: WebGL 绘制Line的bug(三)

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

```


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的同学一定清楚。

相关文章
【el-tree】树形结构拖拽,拖动修改分组
【el-tree】树形结构拖拽,拖动修改分组
1112 1
|
自然语言处理 监控 数据可视化
海拍客与瓴羊达成合作,通过智能客服系统提升员工内部服务体验
海拍客与瓴羊达成合作,通过智能客服系统提升员工内部服务体验
230 0
|
9月前
|
调度
MindIE对接vLLM框架开发指南
vLLM对接MindIE,使能快速迁移到昇腾设备上,当前MindIE 1.0.0发布版本已支持多种三方框架。
|
存储 Kubernetes 关系型数据库
阿里云ACK备份中心,K8s集群业务应用数据的一站式灾备方案
阿里云ACK备份中心,K8s集群业务应用数据的一站式灾备方案
|
监控 NoSQL 算法
【MongoDB】MongoDB的复制如何工作?
【4月更文挑战第1天】【MongoDB】MongoDB的复制如何工作?
|
C语言 C++
结构体\年月日
结构体\年月日
97 4
|
Android开发 容器 API
Android 扫码枪监听封装
一、参考 1、常用keycode 一、简述 1、设备:扫码枪其实相当于一个物理输入设备,如果软键盘打开的话能明显感觉到其内容在输入 2、问题: 2.1、不能扫出中文来(可能和扫码枪设备,配置有关系) 2.
2535 0
|
Cloud Native Java Go
Springboot 获取 /resources 目录资源文件的 9 种方法
Springboot 获取 /resources 目录资源文件的 9 种方法
3356 0
|
JavaScript 前端开发 API
带你读《现代Javascript高级教程》二十二、JS Shadow DOM:创建封装的组件和样式隔离(1)
带你读《现代Javascript高级教程》二十二、JS Shadow DOM:创建封装的组件和样式隔离(1)
203 0
|
云安全 人工智能 弹性计算
专访阿里云技术极客,守护网络世界安全的神秘人
网络与数据时代不断催生着新的命题,对现代人来讲,如何在技术蓬勃发展的信息爆炸中寻求一席之地,是我们应该不断探索的命题。我们带着这些问题,和各个领域的杰出技术人对话,一期一会,抵掌而谈,走进他们的“技术人生”,和他们一起去寻找答案。
1612 0
专访阿里云技术极客,守护网络世界安全的神秘人