【问题标题】:GLSL - vertex shader and batching using uniform buffer objectGLSL - 使用统一缓冲区对象的顶点着色器和批处理
【发布时间】:2019-09-18 09:20:16
【问题描述】:

我有以下顶点着色器:

#version 450 core
...
layout (binding=2, std140) uniform MATRIX_BLOCK
{
   mat4 projection;
   mat4 view;
   mat4 model[128];
   mat4 mvp[128];
};

layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
layout (location = 3) in uint object_idx;

out vec2 TexCoord;
flat out uint instance_idx;

void main()
{  
  gl_Position = mvp[object_idx] * vec4(aPos.x, aPos.y, aPos.z, 1.0);  
  TexCoord = aTexCoord;
  instance_idx = object_idx;
}

我正在使用统一缓冲区来传递 128 个模型和模型视图投影矩阵,这些矩阵由对象 ID 索引。对象 id 使用顶点属性 object_idx 传递给着色器;基本上每个顶点,除了有 x,y,z 坐标和 u,v 纹理坐标外,还有一个与之关联的对象 id。这个想法是能够将多个对象的数据存储在同一个缓冲区中,但仍然为每个单独的对象使用特定的转换矩阵。这是我(可能是愚蠢的)尝试将多个对象批处理在一起以通过单个绘制调用绘制它们,而无需重新绑定任何东西,使用 glDrawElements 渲染三角形。

但是,它不起作用。当我这样做时

gl_Position = mvp[object_idx] * vec4(aPos.x, aPos.y, aPos.z, 1.0);

然后,object_idx 为 0 的三角形会在预期位置很好地渲染,但顶点的 object_idx 不是 0 的三角形不会出现在任何地方。我想我可能弄错了转换矩阵,所以为了调试,我将可能的对象减少到只有 2 个(0 和 1)并使用

gl_Position = mvp[1-object_idx] * vec4(aPos.x, aPos.y, aPos.z, 1.0);

这导致 object_idx = 0 的所有三角形都呈现在 mvp[1] 的预期位置,但同样没有 object_idx = 1 的三角形出现在任何地方。所以至少我知道变换矩阵是正确的。然后我尝试了

gl_Position = mvp[0] * vec4(aPos.x, aPos.y, aPos.z, 1.0);

并渲染 所有 三角形(使用对象 0 的变换矩阵)和

gl_Position = mvp[1] * vec4(aPos.x, aPos.y, aPos.z, 1.0);

使用对象 1 的变换矩阵渲染 所有

所以,很明显我不明白关于顶点着色器或 glDrawElements 是如何工作的真正基本的东西。

所以,我的问题:

当我使用 object_idx 对 mvp 转换矩阵进行“动态”查找时,为什么我的所有三角形都没有被渲染,当我尽我所能检查它时,所有数据都按原样传递到顶点着色器中应该是?

【问题讨论】:

标签: opengl glsl


【解决方案1】:

我在这里做一个有根据的猜测:

layout (location = 3) in uint object_idx;

使用uint 属性输入需要使用函数glVertexAttribIPointer() 设置属性指针(注意其中额外的I)。

使用标准的glVertexAttribPointer 函数将始终设置浮点属性(并且使用类型GL_INT 会从整数转换为浮点数)。从技术上讲,当您在着色器中读取像 uint 这样的浮点属性时,它将是未定义的,但很可能 0 保持 0 因为它们的浮点和整数表示通常是相同的,但这有效只是偶然。

除了这个问题,存储每个顶点的对象索引也是非常低效的。为了有效地批处理您的绘图调用,您应该查看multi draw callsgl_DrawID(最初来自GL_ARB_shader_draw_parameters)功能。您可能还会发现approaching zero driver overhead (AZDO) techniques 很有用。

【讨论】:

  • 你真的很擅长有根据的猜测。将代码更改为使用 glVertexAttribIPointer,它现在按预期工作。我已经阅读了有关 AZDO 和间接多重绘制的信息,但我(显然)是一个 OpenGL 初学者,所以我正在一步一步地做。我会检查 gl_DrawID。谢谢一百万,这让我发疯了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多