如何使用多个对象的不同变换进行实例绘制



我对glDrawArraysInstanced()有点问题。

现在我正试着用棋子画一个棋盘。

我把所有的模型都装好了。

我试过只用实例画典当,结果画得很好。我会通过制服将一个带有变换矢量3的数组发送到着色器,并使用gl_InstanceID在数组中移动

这将通过循环(每个模型的单独绘制调用(来完成:

for (auto& i : this->models) {
i->draw(this->shaders[0], count);
}

最终导致:

glDrawArraysInstanced(GL_TRIANGLES, 0, vertices.size(), count);

其中顶点着色器为:

#version 460
layout(location = 0) in vec3 vertex_pos;
layout(location = 1) in vec2 vertex_texcoord;
layout(location = 2) in vec3 vertex_normal;
out vec3 vs_pos;
out vec2 vs_texcoord;
out vec3 vs_normal;
flat out int InstanceID;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
uniform vec3 offsets[16];
void main(void){
vec3 offset = offsets[gl_InstanceID];  //saving transformation in the offset 
InstanceID = gl_InstanceID; //unimportant
vs_pos = vec4(modelMatrix * vec4(vertex_pos + offset, 1.f)).xyz; //using the offset
vs_texcoord = vec2(vertex_texcoord.x,1.f-vertex_texcoord.y);
vs_normal = mat3(transpose(inverse(modelMatrix))) * vertex_normal;
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(vertex_pos + offset,1.f); //using the offset
}

现在我的问题是,我不知道如何以这种方式绘制多个对象并更改它们的转换,因为每次绘制调用的gl_InstanceID从0开始,因此我的带有转换的数组将从一开始就被再次使用(只会在典当位置上绘制下一块(。

任何帮助都将不胜感激。

您有两个问题。或者更确切地说,你有一个问题,但自然的解决方案会给你带来第二个问题。

问题的自然解决方案是使用一个基本实例渲染函数,如glDrawElementsInstancedBaseInstance。这些选项允许您为实例化的渲染调用指定一个启动实例。

这将引发第二个问题:gl_InstanceID不尊重基本实例。它将始终在[0,instancecount(范围内。只有实例数组才尊重基实例。因此,您必须使用实例数组渲染,而不是使用统一提供每实例数据。这意味着将每实例数据存储在缓冲区对象中(无论如何都应该这样做(以及经由VS输入来访问它,该VS输入的VAO指定特定属性被实例化。

这还具有不将实例计数限制为uniform限制的优点。

OpenGL 4.6/ARB_shader_draw_parameters允许访问gl_BaseInstance顶点着色器输入,该输入提供draw命令指定的baseinstance值。因此,如果您不想/不能使用实例化数组(例如,每个实例的数据量对于属性限制来说太大(,您将不得不依赖扩展/4.6功能。最近的桌面GL驱动程序提供了这一功能,所以如果你的硬件是相当新的,你应该能够使用它

最新更新