立方体-每个面一种颜色
思路很简单,在线框模式的立方体源码基础上直接进行更改,添加varying变量,引入顶点数据颜色,立方体6个面,每个面可以分为两个三角面绘制出来,也就是说每个面需要定义6个点,6个点需要定义36个顶点。
着色器程序
着色器程序参考颜色插值varying
的使用方法添加即可,就不再列出。
顶点数据
/**
创建顶点位置数据数组data,Javascript中小数点前面的0可以省略
**/
var data=new Float32Array([
.5,.5,.5,-.5,.5,.5,-.5,-.5,.5,.5,.5,.5,-.5,-.5,.5,.5,-.5,.5, //面1
.5,.5,.5,.5,-.5,.5,.5,-.5,-.5,.5,.5,.5,.5,-.5,-.5,.5,.5,-.5, //面2
.5,.5,.5,.5,.5,-.5,-.5,.5,-.5,.5,.5,.5,-.5,.5,-.5,-.5,.5,.5, //面3
-.5,.5,.5,-.5,.5,-.5,-.5,-.5,-.5,-.5,.5,.5,-.5,-.5,-.5,-.5,-.5,.5,//面4
-.5,-.5,-.5,.5,-.5,-.5,.5,-.5,.5,-.5,-.5,-.5,.5,-.5,.5,-.5,-.5,.5,//面5
.5,-.5,-.5,-.5,-.5,-.5,-.5,.5,-.5,.5,-.5,-.5,-.5,.5,-.5,.5,.5,-.5 //面6
]);
/**
创建顶点颜色数组colorData
**/
var colorData = new Float32Array([
1,0,0, 1,0,0, 1,0,0, 1,0,0, 1,0,0, 1,0,0,//红色——面1
0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,//绿色——面2
0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,//蓝色——面3
1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,//黄色——面4
0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0,//黑色——面5
1,1,1, 1,1,1, 1,1,1, 1,1,1, 1,1,1, 1,1,1 //白色——面6
]);
深度测试
/**执行绘制之前,一定要开启深度测试,以免颜色混乱**/
gl.enable(gl.DEPTH_TEST);
可以尝试把深度测试的语句注释掉,测试代码,观察视觉效果,你会看到面颜色混乱,比如立方体后面的颜色掩盖前面的颜色。执行gl.drawArrays()
方法后,GPU开始绘制图形,默认的规则是后生成的像素覆盖前面生成的像素, 绿色的面是左侧可见面,但是如果没有gl.enable(gl.DEPTH_TEST);
语句,你会看到本来处于底面不可见的黑色面会把绿色面覆盖,原因很简单,你可以看到代码中黑色面的顶点数据是面5在绿色面2的后面, 黑色面和绿色面在x,y坐标上是有重叠的,黑色与绿色重叠部分会被后生成的像素覆盖。说到这里你应该明白gl.enable(gl.DEPTH_TEST);
语句的作用,顶点装配、光栅化后片元是携带坐标信息的, x,y坐标对应的就是显示器平面,z值就是深度信息,执行该语句就可以识别出黑色面和绿色面的前后位置关系,所有位置靠前的会显示在屏幕上,靠后的像素会被隐覆盖掉。
gl.enable()
是WebGL的方法,该方法的功能就像它的名字一样,可以开启某项功能,参数gl.DEPTH_TEST
表示深度功能。GPU是一块数字电路, 渲染管线的每一个环节都是一个带有某种功能的数字电路单元,只是有些支持可编程,有些不支持可编程,有些可以设置开启或关闭,有些完全不可设置,对于顶点、片元着色器是可以编程的,这两个处理器可以执行编译后的着色器语言, GPU深度检测功能是可设置的,默认是关闭的,再执行绘制命令之前执行代码gl.enable(gl.DEPTH_TEST);
就可以打开GPU的深度测试功能。
渲染管线图
初学WebGL,关键在于建立渲染管线的概念,WebGL渲染顶点数据数据就像富士康的一条流水线一样,一个硬件单元负责一个功能。
在前面几节课程中对WebGL渲染管线的讲解主要是顶点着色器和片元着色器两个硬件单元,还有顶点着色器和片元着色器两个着色器之间的图源装配、光栅器。这节课关于WebGL渲染管线又给大家引入了一种功能单元"深度测试",关于深度测试在整个流水线上所处的位置可以参考下图,在下面的WebGL渲染管线所表达的流水线中有些功能单元你可能还不了解,这没有关系,可以先不管,只要你通过这几节课程建立了WebGL渲染管线的概念,就算达到课程的目的了,有了渲染管线的概念,对于接下来WebGL的学习就会比较顺利了,这也是WebGL编程和javascript编程为什么稍有不同的原因,所有WebGL编程的特殊地方,都和WebGL渲染管线就像流水线一样完成渲染过程有关。
测试
可以把所有的颜色都改为红色,然后执行绘制,你会发现并没有立体的视觉效果,生活中单色的物体也有立体感,这好像不符合生活常识,事实上生活中即使单色的物体在一个自然的光场环境下,它的反射到你眼睛的每个像素点颜色并不是单色是有微小的差异, 即使都是红色,两个像素的红色与红色R值分量会有微小的差异。
白、蓝、绿处于其他三个面的前面,是可见面。可以把三个面设置为红色R分别为1、0.9、0.8来测试效果。你可以发现R值差异了0.1,你会有很强的立体感,其实你可以继续使用更小的差值,来测试你的眼睛视觉变化。这其实相当于手动编写颜色值,模拟自然界光场, 如果有兴趣可以学习下一节课程,如何模拟真实自然界的太阳光、灯光等各种类型光线在物体表面反射光场的分布,不仅不同的面会出现R值不同,一个面上的R值也会不同,呈现某种规律的变化,比如金属在阳光下会有局部高光现象。
/**
创建顶点颜色数组colorData
**/
var colorData = new Float32Array([
1,0,0, 1,0,0, 1,0,0, 1,0,0, 1,0,0, 1,0,0, //红色——面1
.9,0,0, .9,0,0, .9,0,0, .9,0,0, .9,0,0, .9,0,0,//R=0.9——面2
.8,0,0, .8,0,0, .8,0,0, .8,0,0, .8,0,0, .8,0,0,//R=0.8——面3
1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, //黄色——面4
0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, //黑色——面5
1,0,0, 1,0,0, 1,0,0, 1,0,0, 1,0,0, 1,0,0, //R=1——面6
]);