【问题标题】:GLSL - Uniform locations in GLSL 1.2 and depth testing in shadersGLSL - GLSL 1.2 中的统一位置和着色器中的深度测试
【发布时间】:2012-07-30 04:48:23
【问题描述】:

两个问题:

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

  2. 我刚刚完成了我的第一个 GLSL 渲染,看起来就像我忘记启用深度测试一样,各种多边形相互叠加。我启用了深度测试:

    glEnable(GL_DEPTH_TEST);
    

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

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

【问题讨论】:

  • “不支持统一位置” 这些是属性位置,而不是统一位置。请更改您的问题以使用正确的术语。
  • 您在第 1 点上错了,OSX 10.7 和 10.8 都支持 GLSL 1.50 和 ARB_explicit_attrib_location。 (根据我的测试,它们似乎都支持带有显式属性位置的 GLSL 3.30,但这没有记录)

标签: c++ opengl glsl shader


【解决方案1】:

属性位置指定在 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 找出哪个与实际的着色器代码一起工作。因此,您可以将“位置”和“轴”映射到索引 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 的含义等有一个约定。

【讨论】:

    【解决方案2】:

    在 OpenGL 3.3+ 上,您有 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。可以实现几乎相同的功能,但您必须每次都绑定属性,因为它会在固定管道上。

    【讨论】:

    • GLSL 1.2 是 OpenGL 2.1 - OSX 上的最新版本
    猜你喜欢
    • 2017-11-03
    • 1970-01-01
    • 1970-01-01
    • 2011-09-04
    • 2011-08-26
    • 1970-01-01
    • 1970-01-01
    • 2022-01-04
    • 1970-01-01
    相关资源
    最近更新 更多