GLSL OpenGL 3.x如何指定通用顶点属性索引和语义之间的映射?

Mat*_*Mat 1 opengl glsl opengl-3

我正在从HLSL切换到GLSL

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

glVertexAttribPointer(  GLuint      index, 
    GLint   size, 
    GLenum      type, 
    GLboolean   normalized, 
    GLsizei     stride, 
    const GLvoid *      pointer);
Run Code Online (Sandbox Code Playgroud)

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

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

Nic*_*las 7

GLSL中没有"语义"这样的东西.只有属性索引和顶点着色器输入.

有两种顶点着色器输入.3.1中删除的那种(以"gl_"开头的那种)和用户定义的种类.删除的种类不能设置glVertexAttribPointer; 每个变量都有自己的特殊功能.gl_Normalhad glNormalPointer,gl_Colorhave glColorPointer,等等.但是那些功能不再是核心OpenGL了.

用户定义的顶点着色器输入与属性索引相关联.每个命名输入都按以下方式之一分配索引,从最重要的顺序到默认值:

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

    layout(location = 3) in vec4 position;
    
    Run Code Online (Sandbox Code Playgroud)

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

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

    GLuint program = glCreateProgram();
    glAttachShader(program, some_shader);
    glBindVertexAttrib(program, 3, "position");
    glLinkProgram(program);
    
    Run Code Online (Sandbox Code Playgroud)

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

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

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