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

时间:2014-09-09 02:36:05

标签: c# opengl glsl buffer shader

我有一个顶点着色器,我正在尝试使用顶点着色器渲染内容。当我使用普通的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");

2 个答案:

答案 0 :(得分:1)

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

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更改为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而不是double s)

最后,如果您在着色器中明确设置顶点输入的位置,program.BindAttribLocation(0, "in_entity");将不会执行任何操作。

答案 1 :(得分:0)

解决了这个问题,这是一个跨步和抵消的问题。对于那些寻找答案的人:步幅是数组中一个元素的总大小(以字节为单位),偏移量是字段前的字节数。所以严格来说:

struct A {
    Vector4f pos;
    Vector4f norm;
}

两次调用的步幅均为32.第一次偏移为0,第二次为16次。