GLSL顶点着色器未接收vbo数据
本文关键字:vbo 数据 顶点 GLSL | 更新日期: 2023-09-27 18:21:12
我有一个顶点着色器,我正试图使用顶点着色器从中渲染内容。当我使用纯vec3"in"属性时,我就可以使用它,但现在我需要传递某些信息。我制作了一个结构,用于顶点着色器、几何体着色器和计算着色器。
struct StellarEntity
{
vec3 position;
vec3 velocity;
double mass;
double radius;
};
这是我的顶点着色器(当然结构就在那里):
#version 430
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;
layout(location = 0) in StellarEntity in_entity;
void main()
{
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(in_entity.position, 1.0);
}
我认为问题可能在于绑定顶点属性的方式。
vao = new VAO();
//"entities" is a StellarEntity[256] with all data initialized
vao.BufferData(BufferTarget.ArrayBuffer, entities, BufferUsageHint.StaticDraw);
vao.VertexAttribPointer(0, 3, VertexAttribPointerType.Double, false, 0, 0);
vao.VertexAttribPointer(0, 3, VertexAttribPointerType.Double, false, 0, 0);
vao.VertexAttribPointer(0, 1, VertexAttribPointerType.Double, false, 0, 0);
vao.VertexAttribPointer(0, 1, VertexAttribPointerType.Double, false, 0, 0);
我真的不了解步幅和偏移(VertexAttribPointer的最后两个参数),所以我把它们放在0…
编辑:忘记调用BindAttributeLocation,所以它在这里:
//"program" being my shaderprogram, after the linking (worked fine for simple shaders)
program.BindAttribLocation(0, "in_entity");
首先,不能将结构用作顶点着色器的输入。您应该只使用四个独立的顶点属性:
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 velocity;
layout(location = 2) in double mass;
layout(location = 3) in double radius;
(我认为在这里使用double
应该三思。在GPU上,它们的性能不如浮点。)
其次,步幅是一个顶点的属性和下一个顶点属性之间的字节偏移。在您的情况下,它应该是StellarEntity
结构的大小(以字节为单位)。偏移量是从绑定缓冲区的开始到第一个顶点的属性的偏移量(以字节为单位)。如果将mass
和radius
更改为float
s,则它们将是:0、12、24&28.您的"VertexAttribPointer"调用然后变为:
vao.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 32, 0);
vao.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 32, 12);
vao.VertexAttribPointer(2, 1, VertexAttribPointerType.Float, false, 32, 24);
vao.VertexAttribPointer(3, 1, VertexAttribPointerType.Float, false, 32, 28);
(免责声明:我不使用C#,所以我假设OpenGl绑定是直接的,vec3
类型使用float
s而不是double
s)
最后,如果显式设置着色器中顶点输入的位置,program.BindAttribLocation(0, "in_entity");
将不会执行任何操作。
解决了这个问题,这是一个跨步和偏移问题。对于那些寻找答案的人来说:步长是数组中一个元素的总大小(以字节为单位),偏移量是字段之前的字节数。所以对于一个严格的:
struct A {
Vector4f pos;
Vector4f norm;
}
两次通话的步幅都是32。第一个偏移量将为0,第二个偏移量为16。