03-instancing 工程分析详解

本文介绍了OpenGL编程中的VBM二进制模型结构,重点解读了如何通过VBM_HEADER、VBM_ATTRIB_HEADER和VBM_FRAME_HEADER解析模型数据,并详细讲解了glVertexAttribDivisor在多实例渲染中的作用。通过实例展示了divisor参数对顶点属性渲染频率的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

opengl编程指南第8版源码怎么下载、编译,请参考《opengl编程指南第8版源码编译详细说明》

1. 程序启动

 请参考《03-drawcommands工程分析详解》

 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直接丢弃不处理了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值