当前位置: 首页 > Web前端 > HTML

关于WebGL的基本使用和概念(着色器、缓冲区、绘制方法、变换矩阵等)

时间:2023-03-28 19:11:38 HTML

关于WebGL的基本使用和概念(shaders,buffers,drawingmethods,transformationmatrices等)Drawing,这里的基本概念还是很有帮助的,或者说是必须的。在演示和讲解的时候,我们选择image3D.js作为依赖库,但是由于它的语法简单,和原生的WebGL几乎一样,我们觉得这个选择不失为一个不错的选择(如果直接使用native的话,代码会变得过于冗余,解释)。在以下说明中,您无需查阅其他文档。当然,如果你想了解更具体的信息,也可以直接访问image3D.js文档进行参考。一般最常见的绘制流程大致如下:准备着色器→将数据写入缓冲区并完成分配→调用绘制方法进行绘制。不知道你能不能看懂上面每一步是干什么的。丰富的实例讲解。您可以预览我们将要绘制的内容:这是二元函数的图形:y=x2+z2。您可以单击此处查看实际效果。着色器绘制的第一步是准备两个着色器:顶点着色器和片段着色器。前者用来描述绘制图形的点的位置,后者用来描述每个点的颜色。可能你看不懂,其实很简单:我们在绘图的时候,会一次性把所有的数据传给GPU,而传给GPU的数据在使用前需要“整理”一下,而着色器就是常驻这个“终结者”,留在GPU上。我们传递什么数据?不就是点的位置和点的颜色吗?因此,着色器分为顶点着色器和片段着色器(有时称为片段着色器),前者处理点,后者处理颜色。那么,我们先来看看这里vertexshader的具体代码:v_color=a_color;}内置变量gl_Position是最终接收的绘图Point数据,而我们定义的变量a_position就像一个管道,后面我们可以给这个变量赋值,间接给gl_Position赋值(即点的位置)。v_color是什么?你可以理解为在绘制的时候,主要是基于点,而每个点的颜色都需要借助于点的位置来设置,而v_color就是位置到颜色的桥梁。或者直接看片段着色器:precisionmediumpfloat;改变vec4v_color;voidmain(){gl_FragColor=v_color;}还有一个内置变量,这里叫做gl_FragColor,它从顶点着色器接收v_color。不知道你是否理解上面的行为,但你可能也会觉得如何处理点的位置和颜色已经准备好了,后面我们只需要使用a_position和a_color来设置数据即可。在3D对象传输数据之前,我们首先基于这两个着色器创建一个3D对象。这一步很简单,直接看代码:varimage3d=newimage3D(document.getElementsByTagName('canvas')[0],{"vertex-shader":vsCode,"fragment-shader":fsCode,depth:true});后续的所有操作,包括传图、绘图等,直接调用该对象上的接口即可。特别说明:vsCode和fsCode是上面两个shader的代码,都是字符串。传递数据终于可以给GPU传递数据了,所以我们先准备数据:varpoints=[];/**具体写法可以直接看最终代码,思路得到大概是:三个点拼接成一个三角形,每个点由6个数据组成,前3个代表点的位置,后3个代表点的颜色,每个三角形拼接成最后的图形。*///因此点数为varnum=points.length/6;这些三角形是如何确定的?对于xoz曲面,范围是-1到1,切成正方形,然后倒角:对于y值,由y=x2+z2计算。数据准备好,直接设置即可:image3d.Buffer().write(newFloat32Array(points)).use('a_position',3,6,0).use('a_color',3,6,3);数据写入缓冲区,然后赋值给a_position和a_color。因为画的是三角形,一共有num个,直接执行画图方法即可:image3d.Painter().drawTriangle(0,num);transformation虽然上面的话,图形应该已经出来了,但是我们看到最后的例子好像是Rotation,请问旋转效果是怎么出来的呢?聪明的你一定想到了顶点着色器,没错,我们只需要修改顶点着色器中内置变量gl_Position接收到的值,让它乘以一个矩阵即可。shader中对应代码修改:gl_Position=u_matrix*a_position;之后,我们不断重绘,在绘制之前,传递一个新的矩阵://创建一个相机对象varcamera=image3d.Camera({size:2}).rotateBody(0.9,0,1,0).rotateBody(0.3,1,0,0,0,0,1).moveBody(0.5,0,-1,0);setInterval(function(){//每次重绘前,围绕射线(0,0,0)旋转→(0,1,0)by0.05弧度camera.rotateBody(0.05,0,1,0);//传递相机image3d.setUniformMatrix("u_matrix",camera.value());//绘制painter.drawTriangle(0,数);},30);更多如果我们要加灯光和投影,或者说,我们能不能给图形贴上“皮肤”等等,怎么写,是不是不言而喻。是的,思路很简单,就是修改两个shader最后得到的变量值,怎么修改?然后你可以使用一系列的数学计算和着色器的内置函数。完整代码原文地址<样式>正文{边距:0;文本对齐:居中;溢出:隐藏;}抱歉,您的浏览器不支持画布!