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");

GLSL顶点着色器未接收vbo数据

首先,不能将结构用作顶点着色器的输入。您应该只使用四个独立的顶点属性:

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结构的大小(以字节为单位)。偏移量是从绑定缓冲区的开始到第一个顶点的属性的偏移量(以字节为单位)。如果将massradius更改为floats,则它们将是: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。