立方体-每个面一种颜色

优质
小牛编辑
135浏览
2023-12-01

思路很简单,在线框模式的立方体源码基础上直接进行更改,添加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
]);