Problem of glVertexAttrib(...)

i wrote a simple shader, in the vertex shader ,i declare a variable: in vect4 color;
i use it like that gl_FrontColor = color;

However , i want to change the value of color by using glVertexAttrib(…), so i wrote
the following code ,but it does not change the color to red.
why???can someone explain this to me ?
void Shader::init(const char *vsFile, const char *fsFile)
{
…;
glShaderSource(…);
glCompileShader(…);
glAttachShader(…);

…;
GLfloat c[]={1.0,0.0,0.0,1.0};
GLint loc;
loc=glGetAttribLocation(shader_id,“color”);
glVertexAttrib3fv(loc,c);
glBindAttribLocation(shader_id,loc,“color”);

glLinkProgram(shader_id);
}

Use glVertexAttrib the same way you would use glColor: between glBegin() and glEnd() calls.

Your calls in Shader::Init should be in the following order:


glCompileShader(...);
glAttachShader(...);

glBindAttribLocation(...);
glLinkProgram(...);

If you specify the location before linking, there is no need to call glGetAttribLocation, as you know what value to use when you call glVertexAttrib. Be sure to call glEnableVertexAttribArray(…) with the specific location index or else it will not be active in the shaders.

glCompileShader(…);
glAttachShader(…);

glBindAttribLocation(…);
glLinkProgram(…);

i follow the same order in my origin code above ,but it does not work, nothing happens .can you tell me where is the error ???

Did you enable the index?

Enable index?can you explain it in detail?

i do not use glDrawArrays(),do i have to enable the index?

For example, lets say that you assigned ‘color’ to location 3, you would have to call glEnableVertexAttribArray(3) before its value can be used in the shader. Yes, you have to call it regardless of if you use vertex arrays or not.

is it correct if i write the code like that:
GLint loc;
loc=glGetAttribLocation(shader_id,“color”);
glEnableVertexAttribArray(loc);
glVertexAttrib1f(loc,10.0);
glBindAttribLocation(shader_id,loc,“color”);

but it still does not work .

in the orange book,it says like that if i use glBindAttribLocation ,i will not need to enable the index

Interesting, I didn’t know that. If you use BindAttribLocation, why do you need to call GetAttribLocation? You would normally call GetAttribLocation after a program is linked and you don’t know the location of the variable. Call BindAttribLocation before linking so that you won’t need to call GetAtttribLocation at a later stage. Look at the documentation for VertexAttrib.

Here are some questions

  1. Are you calling glUseProgram before your draw calls?
  2. Are you calling glVertexAttrib before glUseProgram? You should call it once you know the location of ‘color’ in the active program.
  3. Do you have a fragment shader? If so, do you do the following

gl_FragColor = gl_Color;

it works ! thanks a lot!

So … what exactly was the problem?

i delete glGetAttribLocation and glEnableAttribArray
,and then just use
glVertexAttrib1f(loc,10.0);
glBindAttribLocation(shader_id,loc,“color”);

before link,it pass the value to "color " correctly.

That works because

The current generic attribute values are part of the context state, not part of the program. So if you’re expecting the value you provide with glVertexAttrib1f to be stored with the program, you’d be mistaken. Only the most recent value set prior to a draw call will be used.

If you’re always disabling the vertex array to use a constant value, then maybe you should be using a uniform instead, which are stored with the program.

It also seems a bit strange that you’re using a single float value for a color(glVertexAttrib1f), rather than 4 values (glVertexAttrib4f) to represent RGBA.

I still don’t understand why you call glVertexAttrib during the shader init. As Dan said, if you intend to use a fixed value, e.g. 10.0, you should use uniforms instead.

I wonder, why didnt ARB decide to deprecate this usecase (along with whole lot of useless entry points).

I think the case is not deprecated because immediate mode provides a way to change small amounts of data per batch with lower overhead than uniforms.

I think the case is not deprecated because immediate mode provides a way to change small amounts of data per batch with lower overhead than uniforms.

Except that:

1: Nobody does that.

2: There has been absolutely no benchmarking demonstrating that this is indeed lower overhead than changing uniforms.

Also, as to not introduce confusion, immediate mode IS deprecated (or removed, whatever).
‘Current’ vertex attributes arent … and are being expanded, adding joy to GL api every now and then, like with doubles and packed vertices (this packed stuff is really cute imo :)).