实例渲染Instanced Rendering
0.前言
在此之前红宝书已经介绍了不少关于缓存和绘制的命令,并给出了用同样的顶点绘制几个三角形的例程,但是此前的例程实现起来非常麻烦,每个三角形要指定一次变换矩阵,假如还要更换颜色的话还要增加相应语句。如果想绘制的物体成千上万,这么一一指定管理起来比较混乱,因此,OpenGL给出了一个新的命令类型:实例渲染——Instanced Rendering。
1.函数介绍:
函数原形:
void glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primCount);
函数说明:
绘制多个指定类型的原语
mode:绘制的原语类型
first,count:内部调用glDrawArrays()时的参数
primCount:绘制重复的次数
此函数内部有一个gl_InstanceID 计数器用来自增表示每个实例,实例每次都被渲染器当作一个新的实例。
例如一个模型实例有120个三角型,想绘制10个类似的此种模型,那么调用将会类似于:
glDrawArraysInstanced(GL_TRIANGLES, 0, 120, 10);
同样的,OpenGL提供了一些列的其他同类绘制命令:
void glDrawElementsInstanced(
GLenum mode,
GLsizei count,
GLenum type,
const void* indices,
GLsizei primCount);
void glDrawElementsInstancedBaseVertex(
GLenum mode,
GLsizei count,
GLenum type,
const void* indices,
GLsizei instanceCount,
GLuint baseVertex);
目前看来,这几个命令与此前的绘制命令并无太大的差别,极其类似多重绘制命令,下面这个函数让他们产生了本质的区别:
函数原形:
void glVertexAttribDivisor(GLuint index, GLuint divisor);
函数说明:
指出index对应的索引数据在提供给着色器的时候,每隔多少个实例变换一次,如果设置为0则按照此前普通的形式,每个顶点提供一个新的数据。如果不是0,则每隔几个实例而不是顶点提供新的数据。
index:数组的索引
divisor:表示每多少个实例提供一次数据。
2.例3.9-3.12
书中给出了具体讲解的例子,这次例程错误比较少,下面首先给出运行结果然后给出注释的程序,此后给出分析讲解以及对书中程序的一些使用解释:
运行效果1(100个实例):
运行效果2(1000个实例,且加大了景深):
代码+注释:
#include "vapp.h"
#include "vutils.h"
#include "vmath.h"
#include "vbm.h"
#include <stdio.h>
using namespace vmath;
BEGIN_APP_DECLARATION(InstancingExample)
//这里用宏定义创建了一个类,继承的 VermillionApplication类具体可参见书中下载的代码
//定义了几个功能
virtual void Initialize(const char * title);
virtual void Display(bool auto_redraw);
virtual void Finalize(void);
virtual void Reshape(int width, int height);
//成员变量
float aspect;
//几个缓存的索引
GLuint color_buffer;
GLuint model_matrix_buffer;
//渲染器程序标号
GLuint render_prog;
//几个数据的索引
GLint model_matrix_loc;
GLint view_matrix_loc;
GLint projection_matrix_loc;
//产生了一个类,用于管理书中提供的模型
VBObject object;
//END_APP_DECLARATION()实际上就应为'};',不知为何在本例缺失
};//END_APP_DECLARATION()
//这里利用宏定义执行了很