【问题标题】:GLSL vertex shader not receiving vbo dataGLSL顶点着色器不接收vbo数据
【发布时间】:2014-09-09 02:36:04
【问题描述】:

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

stride 和 offset(VertexAttribPointer 的最后两个参数)我不是很懂,所以我把它们放在了 0...

编辑:忘了打我的 BindAttributeLocation 电话,所以在这里:

//"program" being my shaderprogram, after the linking (worked fine for simple shaders)
program.BindAttribLocation(0, "in_entity");

【问题讨论】:

    标签: c# opengl glsl buffer shader


    【解决方案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;
    

    (我认为你应该三思而后行在这里使用doubles。在 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 类型使用 floats 而不是 doubles)

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

    【讨论】:

    • 有效!我仍然不知道为什么我不能在我的结构中使用双打,我可以在我的质量和半径中使用它们吗?我试图代表恒星和行星...它们的质量(以千克为单位)远远超出浮标,我需要精确!
    • 只要您的目标是 OpenGL 4.0 或更高版本,就可以使用双打。通常会有性能损失和一些限制(实际上我所知道的唯一一个是双精度片段着色器输入必须符合flat)。
    • GuyRT,你看起来很适合glsl,也许你可以帮我解决我的最后一个问题?在那之后,我将能够毫无问题地编写我的整个程序......谢谢! link
    • 我没有在计算方面做过任何严肃的事情,但我会看看。
    【解决方案2】:

    解决了这个问题,这是一个步幅和偏移问题。对于那些寻找答案的人:步幅是数组中一个元素的总字节数,偏移量是该字段之前的字节数。所以对于一个严格的:

    struct A {
        Vector4f pos;
        Vector4f norm;
    }
    

    两个调用的步幅都是 32。第一个偏移量是 0,第二个是 16。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-11
      • 1970-01-01
      相关资源
      最近更新 更多