PDA

View Full Version : Problem of glVertexAttrib(...)



apapaxionga
04-03-2011, 09:49 AM
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);
}

DarkGKnight
04-03-2011, 10:23 AM
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.

apapaxionga
04-03-2011, 10:51 AM
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 ???

DarkGKnight
04-03-2011, 10:53 AM
Did you enable the index?

apapaxionga
04-03-2011, 11:16 AM
Enable index?can you explain it in detail?

apapaxionga
04-03-2011, 11:20 AM
i do not use glDrawArrays(),do i have to enable the index?

DarkGKnight
04-03-2011, 11:21 AM
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.

apapaxionga
04-03-2011, 11:31 AM
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 .

apapaxionga
04-03-2011, 11:40 AM
in the orange book,it says like that if i use glBindAttribLocation ,i will not need to enable the index

DarkGKnight
04-03-2011, 12:17 PM
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 (http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml#description).

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;

apapaxionga
04-03-2011, 08:47 PM
it works ! thanks a lot!

DarkGKnight
04-04-2011, 05:43 AM
So ... what exactly was the problem?

apapaxionga
04-04-2011, 06:21 AM
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.

Dan Bartlett
04-04-2011, 06:59 AM
That works because
Current generic attribute values define generic attributes for a vertex when a vertex array defining that data is not enabled

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.

DarkGKnight
04-04-2011, 07:43 AM
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.

kyle_
04-04-2011, 01:26 PM
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).

bsupnik
04-04-2011, 03:30 PM
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.

Alfonse Reinheart
04-04-2011, 03:43 PM
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.

kyle_
04-07-2011, 12:02 PM
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 :)).