简体   繁体   中英

GLSL OpenGL 3.x how to specify the mapping between generic vertex attribute indices and semantics?

I'm switching from HLSL to GLSL

When defining vertex attributes in of a vertexbuffer, one has to call

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

and pass an index. But how do I specify which index maps to which semantic in the shader?

for example gl_Normal . How can I specify that when using gl_Normal in a vertex shader, I want this to be the generic vertex attribute with index 1?

There is no such thing as a "semantic" in GLSL. There are just attribute indices and vertex shader inputs.

There are two kinds of vertex shader inputs. The kind that were removed in 3.1 (the ones that start with "gl_") and the user-defined kind. The removed kind cannot be set with glVertexAttribPointer ; each of these variables had its own special function. gl_Normal had glNormalPointer , gl_Color had glColorPointer , etc. But those functions aren't around in core OpenGL anymore.

User-defined vertex shader inputs are associated with an attribute index. Each named input is assigned an index in one of the following ways, in order from most overriding to the default:

  1. Through the use of the GLSL 3.30 or ARB_explicit_attrib_location extension syntax layout(location = #) , where # is the attribute index. So if I have an input called position , I would give it index 3 like this:

     layout(location = 3) in vec4 position; 

    This is my preferred method of handling this. Explicit_attrib_location is available on pretty much any hardware that is still being supported (that isn't Intel).

  2. Explicit association via glBindAttribLocation . You call this function before linking the program. To do the above, we would do this:

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

    You can set multiple attributes. Indeed, you can set multiple attribute names to the same index. The idea with that is to be able to just set a bunch of mappings automatically and let OpenGL figure out which one works with the actual shader code. So you could have "position" and "axis" map to index 3, and as long as you don't put a shader into this system that has both of those inputs, you'll be fine.

  3. Let OpenGL assign it. If you don't assign an attribute index to an attribute in one of the other ways, the GLSL linker will assign it for you. You can fetch the attribute post-linking with glGetAttribLocation .

    I really don't advise this, because OpenGL will assign the indices arbitrarily . So every shader that uses an attribute named position may have the position in a different index. I don't think it's a good idea. So if you can't explicitly set it in the shader, then at least explicitly set it in your OpenGL code before linking. That way, you can have a convention about what attribute index 0 means, what index 1 means, etc.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM