Shader position vec4 or vec3
For vertex attributes, this will not matter. The 4th component is automatically expanded to 1.0
when it is absent.
That is to say, if you pass a 3-dimensional vertex attribute pointer to a 4-dimensional vector, GL will fill-in W
with 1.0
for you. I always go with this route, it avoids having to explicitly write vec4 (...)
when doing matrix multiplication on the position and it also avoids wasting memory storing the 4th component.
This works for 2D coordinates too, by the way. A 2D coordinate passed to a vec4
attribute becomes vec4 (x, y, 0.0, 1.0)
. The general rule is this: all missing components are replaced with 0.0
except for W
, which is replaced with 1.0
.
However, to people who are unaware of the behavior of GLSL in this circumstance, it can be confusing. I suppose this is why most tutorials never touch on this topic.
Related videos on Youtube
Skides
Updated on June 04, 2022Comments
-
Skides almost 2 years
I have read some tutorials about GLSL. In certain position attribute is a vec4 in some vec3. I know that the matrix operations need a vec4, but is it worth to send an additional element? Isn't it better to send vec3 and later cast in the shader vec4(position, 1.0)? Less data in memory - it will be faster? Or we should pack an extra element to avoid casting?
Any tips what should be better?
layout(location = 0) in vec4 position; MVP*position;
or
layout(location = 0) in vec3 position; MVP*vec4(position,1.0);
-
Skides over 10 yearsDoes it mean that I can use: glBufferSubData(GL_ARRAY_BUFFER, 0, vertex*3, data); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); and in shaders use the "layout(location = 0) in vec4 position;" expression?
-
Andon M. Coleman over 10 yearsYes, that is what this means. If you do this, GLSL will add a 1.0 for W every time you try to access it.
-
ThePhD over 8 yearsJust a quick extra question: does this apply to more than
GLfloat
? That is, would the same expansion happen for advec2
->dvec4
orivec2
->ivec4
? -
Andon M. Coleman over 8 years@ThePhD: Yes, this behavior applies throughout the pipeline (from texture fetches to vertex attributes). "... for uvec4 data, respectively. Unused components are filled in with (0, 0, 0, 1) (where 0 and 1 are either floating-point or integer values, depending on the format)." See paragraph 3 here.
-
ThePhD over 8 yearsThanks, that actually really helps me! (I was writing a verifier that verified one GLSL / HLSL layout matched with the next, and that input vertex data matched with the layout data being input, mostly for debug purposes while I try to figure out how NSight works.)
-
ThePhD over 8 yearsOoone last question.... does this only apply to compatibility profiles? (I'm still tracking one last bug that seems to be affected by my stride inputs / outputs...)
-
Andon M. Coleman over 8 years@ThePhD: Sorry, for the delay. Yes. That behavior stretches back to the existence of the old ARB assembly shading language. It's something GL has always done; filling in 1.0 for the
w
(ora
) coordinate makes things without a homogeneous coordinate scale properly and without an alpha channel opaque. -
keaukraine over 8 yearsDoes the same apply for OpenGL ES?
-
Andon M. Coleman over 8 years@keaukraine: Yes, this behavior has been a part of OpenGL since it was created. The fixed-function pipeline even works this way. This is why RGB textures have an implicit 1.0 for the alpha channel they do not store.
-
PeterT over 6 yearsI feel like this answer could be improved with reference to relevant parts of the spec.