opengl编程指南第8版源码怎么下载、编译,请参考《opengl编程指南第8版源码编译详细说明》
1. 程序启动
2. vbm二进制结构说明
本工程从vbm结构读取了三维模型。vbm文件的结构是本工程的难点,下面进行讲解:
vbm一个二进制的模型文件,一开始是个 VBM_HEADER 结构,在作者的设计中,该文件分为新版和旧版,旧版的头部结构为 VBM_HEADER_OLD,但是从数据来看,根本就不需要考虑旧版。
在 VBM_HEADER 之后,是若干个 VBM_ATTRIB_HEADER 结构,该结构用来说明每个顶点包含哪些属性,每个属性又包含哪些分量。从数据来看,以上三个模型,都是包含三个属性的,分别是顶点坐标,包含 4 个 GLfloat 分量,顶点法向量,包含 3 个 GLfloat 分量,纹理贴图坐标,包含两个 GLfloat 分量。这和我上一篇中对顶点格式的设计简直一模一样。
在 VBM_ATTRIB_HEADER 之后,是若干个 VBM_FRAME_HEADER,看来该作者设计该格式是可以支持动画的。不过以我扒出的数据来看,以上三个模型文件都只包含一帧。
在 VBM_FRAME_HEADER 之后就是顶点数据。从头文件中可以得到顶点的个数,以及每个顶点包含哪些属性,以及每个属性包含几个分量,就很容易算出顶点数据的长度。
顶点数据之后,就是索引数据。我读源代码,同时还发现顶点数据之后是材质信息。这两组数据是有点混淆的。好在,以我扒出的数据来看,以上三个模型文件既没有使用索引,也没有包含任何材质,那倒是让我省事了不少。
3 glVertexAttribDivisor
glVertexAttribDivisor
modifies the rate at which generic vertex attributes advance when rendering multiple instances of primitives in a single draw call. If divisor
is zero, the attribute at slot index
advances once per vertex. If divisor
is non-zero, the attribute advances once per divisor
instances of the set(s) of vertices being rendered. An attribute is referred to as instanced if its GL_VERTEX_ATTRIB_ARRAY_DIVISOR
value is non-zero.
大概的意思是:当单次调用绘制函数渲染多个图元实例时,glVertexAttribDivisor修改了通用顶点属性向前的比例即每次绘制的步长,即是逐顶点还是每隔
divisor
个实例渲染
一次。如果参数
divisor
是0,则glVertexAttribDivisor函数第一个参数index表示的顶点属性每个顶点就执行渲染一次,如果
divisor
非0,则参数index表示的顶点属性每隔
divisor
实例就渲染一次。这就话的意思说白了就是当divisor
为0时,则每个顶点中参数index表示的顶点属性就渲染一次(逐顶点
渲染
,以点为单位
渲染
);而如果
divisor
非0,则每divisor
实例,就渲染一次。例如:一次渲染100个三角形(这里每个三角形就是一个实例),如果
divisor
为0,则每个三角形都绘制(逐顶点
渲染
,以点为单位
渲染
,当然,这还跟硬件的UFO有关,参考《OpenGL中的Uniform block size 的大小限制》);如果
divisor
为1,则第0, 1, 2, 3,4,5.....个三角形会被绘制即每个三角形都会被绘制(逐实例
渲染
,以实例为单位
渲染
),也就是说每1个三角形才绘制一次(相比前面的
divisor
为0结果相同,但效率要高很多);如果
divisor
为3,则第0, 3, 6, 9,12,15......个三角形会被绘制,而第1,2,4,5,7,8,9,10,11,13,14......不会绘制,直接丢弃,也就是说每隔3个三角形才绘制一次,以此类推。
第180行代码为:
glVertexAttribDivisor(3, 1);
即每个实例都绘制,结果如下:
将第二个参数改为30,即每隔30个实例绘制一次,其间的实例不处理,直接丢弃,结果如下:
可以看到只有第0,30、60、90、120、150、180,共7个VBM绘制了,中间的VBM直接丢弃不处理了。