1

我正在从 HLSL 切换到 GLSL

在顶点缓冲区中定义顶点属性时,必须调用

glVertexAttribPointer(  GLuint      index, 
    GLint   size, 
    GLenum      type, 
    GLboolean   normalized, 
    GLsizei     stride, 
    const GLvoid *      pointer);

并传递一个索引。但是如何指定哪个索引映射到着色器中的哪个语义?

例如gl_Normal。如何指定gl_Normal在顶点着色器中使用时,我希望这是索引为 1 的通用顶点属性?

4

1 回答 1

7

GLSL 中没有“语义”之类的东西。只有属性索引和顶点着色器输入。

有两种顶点着色器输入。在 3.1 中删除的种类(以“gl_”开头的种类)和用户定义的种类。移除的种类不能glVertexAttribPointer;设置 这些变量中的每一个都有自己的特殊功能。gl_Normalhad glNormalPointergl_ColorhadglColorPointer等。但是这些功能不再存在于核心 OpenGL 中。

用户定义的顶点着色器输入与属性索引相关联。每个命名输入通过以下方式之一分配一个索引,从最覆盖到默认:

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

    layout(location = 3) in vec4 position;
    

    这是我首选的处理方法。Explicit_attrib_location 可用于几乎所有仍受支持的硬件(不是英特尔)。

  2. 通过 显式关联glBindAttribLocation。在链接程序之前调用此函数。要做到以上几点,我们会这样做:

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

    您可以设置多个属性。实际上,您可以将多个属性名称设置为同一个索引。这样做的想法是能够自动设置一堆映射并让 OpenGL 找出哪个与实际的着色器代码一起使用。因此,您可以将“位置”和“轴”映射到索引 3,只要您不将着色器放入具有这两个输入的系统中,就可以了。

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

    我真的不建议这样做,因为 OpenGL 会任意分配索引。因此,每个使用命名属性的着色器都position可能在不同的索引中具有位置。我不认为这是一个好主意。因此,如果您不能在着色器中显式设置它,那么至少在链接之前在您的 OpenGL 代码中显式设置它。这样,您可以对属性索引 0 的含义、索引 1 的含义等有一个约定。

于 2012-03-05T04:15:28.373 回答