Reputation: 4501
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?
Upvotes: 1
Views: 1708
Reputation: 474426
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:
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).
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.
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.
Upvotes: 8