OpenGL学习脚印:创建更多的实例(instancing object)

本文介绍了OpenGL中的实例化技术(instancing object),用于高效渲染多个模型实例。内容包括渲染多个实例的方法,使用多个uniform传递实例数据的局限性,以及利用instance array传递数据的实现方式。通过对比实验,展示了instance array在性能上的优势,适用于渲染大量重复对象,如行星带、纳米战斗服机器人等场景。
摘要由CSDN通过智能技术生成

写在前面
前面我们学习了模型加载的相关内容,并成功加载了模型,令人十分兴奋。那时候加载的是少量的模型,如果需要加载多个模型,就需要考虑到效率问题了,例如下图所示的是加载了400多个纳米战斗服机器人的效果图:

更多的纳米战斗服

渲染一个模型更多的实例,需要使用到实例化技术,就是本节要介绍的instancing object方法。本节示例代码均可以从我的github下载

本节内容整理自:
www.learnopengl.com

渲染多个实例的方法

要渲染多个实例,基本的想法就是,在主程序中使用循环,在不同位置绘制多个物体,伪代码如下所示:

   for(GLuint i = 0; i < instanceCount; ++i)
   {
      // 分别设置每个物体的模型变换矩阵 model matrix
      // glDrawArrays(GL_TRIANGLES, ...)
   }

这种方式存在的缺点是,当要渲染多个模型的实例时,需要多次调用glDraw这类命令,而这类命令从CPU–>GPU是需要花费时间的,因为使用绘制命令时OpenGL需要做一些工作,例如通知GPU从哪个buffer里面读取数据。虽然GPU绘图很快,但是CPU–>GPU的命令发送,当量比较大时还是会成为瓶颈。

因此OpenGL提供了glDrawArrays和glDrawElements的绘制实例版本,分别对应为glDrawArraysInstanced和glDrawElementsInstanced 。实例版本的函数,多了一个参数,就是最后一个指定渲染多少个实例的参数。

下面以一个简单的绘制多个矩形的例子作为引例,开始熟悉绘制多个实例。

使用多个uniform传递实例数据

假设我们要绘制100个矩形,在顶点着色器中,我们使用一个uniform数组:

   #version 330 core

layout(location = 0) in vec2 position;
layout(location = 1) in vec3 color;

uniform vec2 offsets[100]; // 每个实例的位移量

out vec3 fColor;

void main()
{
    vec2 offset = offsets[gl_InstanceID]; // 通过gl_InstanceID索引每个实例的位移量
    gl_Position = vec4(position + offset, 0.5f, 1.0f);
    fColor = color;
}

通过gl_InstanceID来索引每个实例,而在主程序中,我们通过循环设置这个uniform数组的内容:

   //准备多个实例的位移量数据
glm::vec2 translations[100];
int index = 0;
GLfloat offset = 0.1f;
for (GLint y = -10; y < 10; y += 2)
{
for (GLint x = -10; x < 10; x += 2)
{
    glm::vec2 translation;
    translation.x = (GLfloat)x / 10.0f + offset;
    translation.y = (GLfloat)y / 10.0f + offset;
    translations[index++] = translation;
}
}
// 接着 向shader传递这100个translate uniform

最后通过实例版本函数绘制多个矩形:

shader.use();
glBindVertexArray(quadVAOId);
glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 100); // 使用instance方法绘制

得到的效果如下图所示:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值