GLSL: vertex world space position when glRotatef..

Hi all,

I am trying to get the vertex world space position in the vertex shader while I have some vertex transformation in my openGl code.

This is clearly screen position:
gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;

This is eye position:
gl_ModelViewMatrix * gl_Vertex;

And this is world space position BUT BEFORE the gl transformation:
gl_Vertex;

so this last line, doesn’t take into account glTranslatef(), glRotatef() and glScalef().
Is it possible to get it in shader?
I guess I should try to avoid the use of glTransformation when I want to use Shaders…
If so, how can I replace my glTransformation?
I mean how can I easilly calculate the amtric transformation I have to apply my vertex?

thanks a lot in advance,

Best
Loic

The issue you’re having is that there are actually four coordinate spaces (object, world, view, clip) and only two matrix stacks. What you would like is this:

<object coords>
   (x model matrix)
<world coords>
   (x view matrix)
<eye coords>
   (x projection matrix)
<clip coords>

However, in OpenGL, the model matrix and view matrix are implicitly concatenated (hence, the term modelview matrix) and therefore, you don’t really have access to world coordinates. What you really have is:

<object coords>
   (x model-view matrix)
<eye coords>
   (x projection matrix)
<clip coords>

The good news is that, because you’re using shaders, the matrix stacks don’t necessarily have to be used for the purposes they are named for. There’s a few options I can think of:
[ul][li] Use the model-view matrix stack as a model matrix and use bake your world-eye coordinate transformation into the projection matrix. Essentially, you’re creating a gl_Model matrix and a gl_ViewProjection matrix. That means, do all your glTranslatef, glRotatef, etc. calls that take your vertices from world space to eye space on your projection matrix, and only use the model-view matrix for object to world coordinate transformation. Then, your world coordinates will simply be:[/li]

gl_ModelViewMatrix * gl_Vertex

Of course, then you’d lose your eye coordinates (which are often needed for lighting). It would also break some other stuff like gl_NormalMatrix.[li] Abuse one of the other matrix stacks (such as the texture matrices). Use the model-view matrix as just a model matrix, use a texture matrix as your view matrix. This is kind of hacky, but as this is all shader code and you can use the matrices for whatever you want, you should be good to go.[*] Don’t use GL’s matrix stacks at all. Roll your own matrix class and pass the matrices to the shader as uniforms. That way, you can have as many matrices and coordinate spaces as you need. In fact, the matrix stacks are deprecated in GL 3.0+ for precisely this reason - fixed function is gone and in shaders, the built-in matrices don’t necessarily have a defined meaning.[/ul][/li]Cheers,

Graham

[quote=“Graham Sellers”]
[li] Don’t use GL’s matrix stacks at all. Roll your own matrix class and pass the matrices to the shader as uniforms. That way, you can have as many matrices and coordinate spaces as you need. In fact, the matrix stacks are deprecated in GL 3.0+ for precisely this reason - fixed function is gone and in shaders, the built-in matrices don’t necessarily have a defined meaning.[/li][/quote]

I completely agree with this. Once you have your own matrix class, I think you will find this method more flexible and cleaner, and, as Graham mentioned, it is OpenGL 3+ ready.

Regards,
Patrick

Hi,
thanks a lot for comments…

I am indeed trying to change my code in order to avoid use of glTransformation…
Since I need to do these modifications rather quickly, I’ve just created a function that take as input an array of vertices and get the ModelView projection matrix and apply it to my vertices (before I create the VBO.)

		glPushMatrix();
		glLoadIdentity();
		glRotatef(57.29f*Phi_                        ,0,0,1);
		glRotatef(57.29f*FROG_COORD::EtaToTheta(Eta_),0,1,0);		
		TransformVerticesArray(positionData, VBO_VerticesN_);
		glPopMatrix();

void TransformVerticesArray(GLfloat* VerticesArray, unsigned int NVertices){
GLfloat m[16];
glGetFloatv (GL_MODELVIEW_MATRIX, m);

for(unsigned int i=0;i&lt;NVertices;i++){
	unsigned int offset = i*3;
	float A = m[0 ]*VerticesArray[offset+0] + m[4 ]*VerticesArray[offset+1] + m[8 ]*VerticesArray[offset+2] + m[12]*1.0f;
	float B = m[1 ]*VerticesArray[offset+0] + m[5 ]*VerticesArray[offset+1] + m[9 ]*VerticesArray[offset+2] + m[13]*1.0f;
	float C = m[2 ]*VerticesArray[offset+0] + m[6 ]*VerticesArray[offset+1] + m[10]*VerticesArray[offset+2] + m[14]*1.0f;
	VerticesArray[offset+0] = A;
	VerticesArray[offset+1] = B;
	VerticesArray[offset+2] = C;
}

}

thanks again,
Loic

Sorry, I can’t miss to mention that programmable pipeline doesn’t need to operate with matrices at all.
I’m using quaternions instead (visit http://code.google.com/p/kri/ for more info).

If I am following your code correctly, every time the viewer moves, e.g. every time you need to update the modelview matrix, you transform each vertex on the CPU. I suppose if you only care about fixed views, this doesn’t matter a whole lot but if the view changes frequently, this can lead to a performance problem. GPUs are very good at multiplying vectors and matrices, and doing so in a massively parallel way. In many cases, we use vertex shaders to avoid touching each vertex on the CPU like you are doing here. But if you need to code quickly, and that code is working for you, then by all means roll with it.

Regards,
Patrick

Hi pjcozzi,

you are perfectly right and indeed I should have stressed in my previous email that my objects are completely static (only the camera move). So it is not so important in my case because I build the objects (so I transform my vertices) only once at the software initialisation. Then the VBO are built (STATIC STREAM) and I only use these.

I am usingt he sahders in order to do other kind and more subtile vertices transformation:
like X,Y,Z -> R,Phi,Theta
or fisheye view…

thanks a lot,
Loic

Ok. Good to hear. If you only write the VBO once and use it many times, always use STATIC, but if it is only used a few times, STREAM is appropriate.

Patrick