Inverse Transpose ModelView Matrix

Started by
4 comments, last by adam17 19 years ago
how do i get this? do i have to calculate it on my own or is there an opengl function that already has it constructed? im trying to write a simple lighting shader in Cg but the normal is not being calculated right. it stays pointing in one direction while the object is rotating. im pretty sure that i need to multiply it by the inverse transpose modelview matrix.
Advertisement
there is a CGGL function for getting state matrices, the last parameter to this function will let you select various forms of the matrix, the matrix itself, the inverse, the transpose, and the inverse transpose, it's in the cg_GL runtime documentation (if you have the CG Toolkit). And by the by you only need to transform the normal by the upper 3x3 part of this matrix. A typecast to float3x3 in the shader will get this upper 3x3 part.
i figured out how to get the matrix but when i switch between the shader and the normal pipeline the normal seems to negate direction. once side of the model is lit going through the pipeline, when the shader is running the opposite side was lit.

here is my shader code:
void main(  float4 pos:		POSITION,			float3 normal:	NORMAL,			float3 Kd:		DIFFUSE,						out float4 opos:	POSITION,		out	float4 color:	COLOR,			uniform float4x4	modelViewMatrix,	uniform float4x4	modelViewMatrixIT,	uniform float3		lightpos,	uniform float3		lightcol){	opos = mul(modelViewMatrix, pos);	float4 P = pos;	float3 N = normal;	N = mul((float3x3)modelViewMatrixIT, N);	N = normalize(N);	float4 Lp= float4(lightpos, 1);	float4 L = normalize(Lp-P);	float  diffuselight = max(dot(N, L), 0);	float3 diffuse = Kd * lightcol * diffuselight;	color.xyz = diffuse;	color.w = 1;}


and here is the code for setting up the shader:
cgGLEnableProfile(vp);		cgGLBindProgram(lightingvp);		//set normal position in VP program		normal = cgGetNamedParameter(lightingvp, "normal");		cgGLSetParameter3fv(normal, face_normal);		modelViewMatrix = cgGetNamedParameter(lightingvp, "modelViewMatrix");		cgGLSetStateMatrixParameter(modelViewMatrix, 									CG_GL_MODELVIEW_PROJECTION_MATRIX,									CG_GL_MATRIX_IDENTITY);		modelViewMatrixIT=cgGetNamedParameter(lightingvp, "modelViewMatrixIT");		cgGLSetStateMatrixParameter(modelViewMatrixIT, 									CG_GL_MODELVIEW_PROJECTION_MATRIX,									CG_GL_MATRIX_INVERSE_TRANSPOSE);		Kd		 = cgGetNamedParameter(lightingvp, "Kd");		lightpos = cgGetNamedParameter(lightingvp, "lightpos");		lightcol = cgGetNamedParameter(lightingvp, "lightcol");		cgGLSetParameter3fv(Kd, diff_col);		cgGLSetParameter3fv(lightpos, light_pos);		cgGLSetParameter3fv(lightcol, light_dif);


any ideas at what is going wrong?
You shouldn't be passing in your normal like that, since it's a semantic CG will get it automatically from OpenGL. Also, placement of that code that communicates with CG is important, gotta make sure the modelview matrix is indeed set, i.e. you've loaded identity and set up any modelling/viewing transformations.
Quote:Original post by adam17
  modelViewMatrix = cgGetNamedParameter(lightingvp, "modelViewMatrix");cgGLSetStateMatrixParameter(modelViewMatrix,CG_GL_MODELVIEW_PROJECTION_MATRIX,CG_GL_MATRIX_IDENTITY); modelViewMatrixIT=cgGetNamedParameter(lightingvp, "modelViewMatrixIT");cgGLSetStateMatrixParameter(modelViewMatrixIT,CG_GL_MODELVIEW_PROJECTION_MATRIX,CG_GL_MATRIX_INVERSE_TRANSPOSE);


I think here is the error. You pass the inverse transpose of the CG_GL_MODELVIEW_PROJECTION_MATRIX to modelViewMatrixIT. This will convert your normal from object space to CLIP SPACE, which is quite weird... The transformed normal vector and the light vector must both be in the same space - usually world or eye space. I assume, your light vector is given in world space, so you should be passing CG_GL_MODELVIEW_MATRIX to modelViewMatrixIT instead of CG_GL_MODELVIEW_PROJECTION_MATRIX.

Apart from that, to prevent confusion: Your "modelViewMatrix" is indeed the modelViewProjectionMatrix (= Projection * ModelView), so you should name it like that.

Quote:
  float3 N = normal;  N = mul((float3x3)modelViewMatrixIT, N);


Usually, a normal vector is identified with a zero-w-coordinate IIRC. So the code should be
  float4 N = float4(normal,0);  N = mul(modelViewMatrixIT, N);


Quote:
  //set normal position in VP program  normal = cgGetNamedParameter(lightingvp, "normal");  cgGLSetParameter3fv(normal, face_normal);


As digitex devil already mentioned, you can simply use glNormal3fv(face_normal) to pass the face normal. Since the name "normal" is bound to NORMAL in your definition of the main-CG-routine, the CG compiler will recognize it correctly.

ive been playing around with the code and it stopped working. i tried fixing it and couldnt so i rewrote the cg portion. i made the changes like you guys suggested. the model still isnt being displayed. is there any kind of tool that i can use to compile the shader and make sure its working properly? is there a tool for making sure all of the information is getting passed correctly from my applicaion into the shader?

This topic is closed to new replies.

Advertisement