GLSL - GLSL 1.2中的统一位置和着色器中的深度测试

时间:2012-07-29 01:21:13

标签: c++ opengl glsl shader

两个问题:

  1. 我在使用不同着色器的大型VBO中渲染元素。在GLSL 1.2中我必须使用,如果我是正确的,因为它是OSX上的最新版本不支持统一位置,我认为这意味着属性的位置是编译器决定的位置。有没有办法解决?例如,当我的VBO使用interleaved(x,y,z,nx,ny,nz,texU,texV)时,我需要多个着色器才能在每次相同的位置访问这些属性。然而,我发现编译器给它们不同的位置导致该位置是法线,依此类推。我需要他们的位置与我的VBO属性位置一致。

  2. 我刚刚完成了第一次GLSL渲染,看起来我忘了启用各种多边形渲染的深度测试。我启用了深度测试:

    glEnable(GL_DEPTH_TEST);
    

    问题仍然存在。是否有不同的方式使用着色器启用它们?我认为深度缓冲区会解决这个问题吗?

    问题2解决了。原来是一个SFML问题,我需要在创建窗口时指定OpenGL设置。

2 个答案:

答案 0 :(得分:2)

属性位置在3个位置之一中指定,按从最高优先级到最低优先级的顺序排列:

  1. 通过使用GLSL 3.30(或更好)或ARB_explicit_attrib_location扩展语法layout(location = #),其中#是属性索引。因此,如果我有一个名为position的输入,我会像这样给它索引3:

    layout(location = 3) in vec4 position;
    

    这是我处理此问题的首选方法。几乎任何仍受支持的硬件(不是英特尔)都可以使用Explicit_attrib_location。

  2. 通过glBindVertexAttrib进行明确关联。在链接程序之前调用此函数。要做到这一点,我们会这样做:

    GLuint program = glCreateProgram();
    glAttachShader(program, some_shader);
    glBindVertexAttrib(program, 3, "position");
    glLinkProgram(program);
    

    您可以设置多个属性。实际上,您可以将多个属性名称设置为相同的索引。这个想法是能够自动设置一堆映射,让OpenGL找出哪一个与实际的着色器代码一起工作。所以你可以将“position”和“axis”映射到索引3,只要你没有将着色器放入具有这两个输入的系统中,你就可以了。

    请注意,您还可以设置不存在的属性。您可以为“正常”提供未在着色器中指定的属性。 那很好;链接器只关心实际存在的属性。因此,您可以为此类事物建立复杂的约定,并在链接之前运行其上的每个程序:

    void AttribConvention(GLuint prog)
    {
      glBindVertexAttrib(program, 0, "position");
      glBindVertexAttrib(program, 1, "color");
      glBindVertexAttrib(program, 2, "normal");
      glBindVertexAttrib(program, 3, "tangent");
      glBindVertexAttrib(program, 4, "bitangent");
      glBindVertexAttrib(program, 5, "texCoord");
    }
    
    GLuint program = glCreateProgram();
    glAttachShader(program, some_shader);
    AttribConvention(program);
    glLinkProgram(program);
    

    即使某个特定着色器没有所有这些属性,它仍然有效。

  3. 让OpenGL分配它。如果不以其他方式之一为属性分配属性索引,则GLSL链接器将为您分配属性索引。您可以使用glGetAttribLocation获取后链接属性。

    我真的不建议这样做,因为OpenGL将任意分配索引 。因此,使用名为position的属性的每个着色器可能具有不同索引中的位置。我不认为这是个好主意。因此,如果您无法在着色器中明确设置它,那么至少在链接之前在OpenGL代码中明确设置它。这样,你可以有一个关于什么属性索引0意味着什么,索引1意味着什么等的约定。

答案 1 :(得分:1)

在OpenGL 3.3+上你有VAO,当你使用VAO时,你会将VBO绑定到它,你可以按照自定义顺序定义属性:http://www.opengl.org/sdk/docs/man3/xhtml/glEnableVertexAttribArray.xml(记住属性必须是连续的)

可以在XNA上找到一个很好/简单的实现方法:VertexDeclaration,您可能也希望看到所有的Vertex *类型。

有关使v3与SFML一起使用的一些提示: http://en.sfml-dev.org/forums/index.php?topic=6314.0

有关如何创建和使用VAO的示例:http://www.opentk.com/files/issues/HelloGL3.cs

(这是C#,但我猜你会得到它)

更新:

在v2.1上你也有http://www.opengl.org/sdk/docs/man/xhtml/glEnableVertexAttribArray.xml,但是你无法创建VAO。可以实现几乎相同的功能,但是每次都必须绑定属性,因为它将在固定管道上。