View more

View more

View more

### Image of the Day Submit

IOTD | Top Screenshots

### The latest, straight to your Inbox.

Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.

# gl_NormalMatrix / gl_ModelViewMatrix inside Fragment shader ?

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

7 replies to this topic

### #1dimensionX  Members

Posted 07 October 2004 - 12:12 PM

What is the word on using gl_NormalMatrix inside a fragment shader in OpenGL 2.0 ? I am using NVIDIA Quadro FX 500 with 61.76 driver gl_NormalMatrix does not seem to have any effect for transforming vectors or even points. Any advice would be of help. Thanks!

### #2phantom  Members

Posted 07 October 2004 - 12:57 PM

a code snippet would be helpfull....

### #3dimensionX  Members

Posted 07 October 2004 - 01:34 PM

-----------------
uniform sampler2D decalTexture;
uniform sampler2D bumpMapTexture;
uniform samplerCube cubeMapTexture;

varying vec2 texCoord;

varying vec3 T, B, N;
varying vec3 V, L;
varying vec3 cmV;

void main(void)
{
T = normalize(T);
B = normalize(B);
N = normalize(N);

V = normalize(V);
L = normalize(L);

cmV = normalize(cmV);

vec3 view, light, half;

/* Transform V & L to tangent-space and compute half vector */
view.x = dot(T, V);
view.y = dot(B, V);
view.z = dot(N, V);

light.x = dot(T, L);
light.y = dot(B, L);
light.z = dot(N, L);

half = normalize(light + view);

/* Fetch the Decal color and tangent-space normal */
vec3 decal = vec3 (texture2D(decalTexture, texCoord));
vec3 normal = vec3 (texture2D(bumpMapTexture, texCoord));

normal.x = 2.0 * normal.x - 1.0;
normal.y = 2.0 * normal.y - 1.0;
normal.z = 2.0 * normal.z - 1.0;

/* Compute Diffuse and Specular components */
float ndotl = max(dot(normal, light), 0.0);
float ndoth = pow(max(dot(normal, half), 0.0), 60.0);

/* Transform normal from Tangent-space to World space */
vec3 t = vec3(T.x, B.x, N.x);
vec3 b = vec3(T.y, B.y, N.y);
vec3 n = vec3(T.z, B.z, N.z);

vec3 cmNormal;
cmNormal.x = dot(t, normal);
cmNormal.y = dot(b, normal);
cmNormal.z = dot(n, normal);

/* Transform normal from World space to cubemap space */
cmNormal = vec3 (gl_NormalMatrix * cmNormal);
cmNormal = normalize(cmNormal);

vec3 refVector = reflect(-cmV, cmNormal);

vec3 refColor = vec3 (textureCube(cubeMapTexture, refVector));

vec3 fColor;
fColor.x = ndotl * (decal.x + refColor.x) + ndoth;
fColor.y = ndotl * (decal.y + refColor.y) + ndoth;
fColor.z = ndotl * (decal.z + refColor.z) + ndoth;

gl_FragColor = vec4 (vec3(fColor), 1.0);
}

----------------------------------------------------------------
I implemented the same method using ARB Vertex/fragment programs and it works perfectly.

The reason I declared T, B, N as varying is because I am not able to fetch the BumpMap normal inside the vertex shader.

I tested the rest of the stuff like (diffuse, specular, bumpshading) by changing the argument fColor in the last statment:

gl_FragColor = vec4 (vec3(fColor), 1.0);

to ndotl, ndoth respectively.

I tried using gl_NormalMatrix, glModelViewMatrix and even glTextureMatrix[0] (by loading the Inverse of the modelview transform into the texture unit 0 texture matrix stack). All gave the same effect no change.

Any clue would of great help, Thank you!

---------------------------------------------------------------
Below is the vertex and fragment shader for cube environment mapping which works perfectly.

---------------
varying vec3 N;
varying vec3 V;

void main(void)
{
gl_Position = ftransform();

vec3 vertex = vec3 (gl_ModelViewMatrix * gl_Vertex);

V = normalize(-vertex);

N = vec3 (gl_NormalMatrix * gl_Normal);
}

------------------
uniform samplerCube cubeMapTexture;

varying vec3 N;
varying vec3 V;

void main(void)
{
vec3 view = normalize(V);
vec3 normal = normalize(N);

vec3 refVector = reflect(-view, normal);

vec3 refColor = vec3 (textureCube(cubeMapTexture, refVector));

gl_FragColor = vec4 (vec3(refColor), 1.0);
}
----------------------------------------------------------------

### #4Trienco  Members

Posted 07 October 2004 - 06:55 PM

Quote:
 Original post by dimensionXWhat is the word on using gl_NormalMatrix inside a fragment shader in OpenGL 2.0 ?

not really a help because its nothing official, but.. expecting the normal and modelview to be applied to vertices and not fragment i wouldnt see why they should even be around at the fragment stage?

### #5dimensionX  Members

Posted 08 October 2004 - 02:20 AM

The orange book (OpenGL Shading Language) says it can be accessed and used in both the vertex and fragment shaders.

So if I can't access texture units inside a vertex shader and gl_normalMatrix does not have any effect inside the fragment shader, how do I get to implement my reflective bump mapping ?

I guess the only way is to send the gl_NormalMatrix from the application to tha gragment program as a uniform variable.

Did NVIDIA comment on this anywhere ?

Thanks!

### #6James Trotter  Members

Posted 08 October 2004 - 03:12 AM

gl_NormalMatrix is a built-in variable in glsl. Take a look at section 7.5 of the OpenGL shading language specification.

gl_NormalMatrix is the inverse transpose of the upper 3x3 part of the modelview matrix.

### #7dimensionX  Members

Posted 08 October 2004 - 04:12 AM

James,

Thank you for the pointer, I know it is a built-in variable.

What I am saying is it is not working inside the fragment shader like it does inside the vertex shader. Do you know why ?

Thanks!

### #8James Trotter  Members

Posted 09 October 2004 - 04:43 AM

I'm sorry, I should probably have read your post more thoroughly first...
I have a radeon 9600, and use RenderMonkey for coding GLSL shaders all the time. I consistently use gl_NormalMatrix, and there's no problem...

Here's some code that does per-pixel Phong shading:

/*	Author: James D. Trotter	29/09-2004	Phong illumination program	--------------------------	http://en.wikipedia.org/wiki/Phong_shading	The vertex shader transforms the	vertex-normal by the inverse	transpose of the modelview	matrix,	so that the	normal	is in world-space.	The eye-space vector from the	light to the vertex is trans-	formed into world-space, and	sent to the fragment shader.	The eye-space vector from the	vertex to the camera, (the	negative vertex coordinate,	since the camera is at the	origin in eye-space), is	transformed into world-space,	so that it can be used to	calculate the specular light	component in the fragment shader.*/// Position of the point-lightuniform vec4 lightPosition;// Values interpolated across the polyogonvarying vec3 normal; // Vertex-normalvarying vec3 viewVec; // World-space view vectorvarying vec3 lightVec; // World-space light vectorvoid main(void) {	// Get the vertex normal, transformed	// by the inverse transpose of the	// modelview-matrix	normal = gl_NormalMatrix * gl_Normal;	// Get the world-space vector	// from the light to the vertex.	vec4 lightToVertex = lightPosition - gl_Vertex;	lightVec = (gl_ModelViewMatrix * lightToVertex).xyz;	// Get the world-space vector from	// the vertex to the camera.	viewVec = (gl_ModelViewMatrix * gl_Vertex).xyz;	// Perform vertex transformations.	gl_Position = ftransform();}

/*	Author: James D. Trotter	29/09-2004	Phong illumination program:	---------------------------	http://en.wikipedia.org/wiki/Phong_shading	Using the interpolated vertex normal,	lighting is calculated according to	the phong illumination or reflection	model. All three lighting components -	diffuse, ambient, and specular - are	taken into account:	Diffuse:	L.N				where L is the tangent-space				vector from the light to the				vertex. And N is the				(interpolated) fragment normal.	Specular:	pow(R.V, n)				where R is the reflected light				vector around the normal N.				V is the tangent-space vector				from the vertex to the viewer.				n indicates the surface reflectivity.	Ambient:	The ambient term is added to				give general illumination. This				is needed because diffuse and				specular only accurately give				local lighting conditions.*/// Values interpolated across the polyogonvarying vec3 normal; // Vertex-normalvarying vec3 viewVec; // World-space view vectorvarying vec3 lightVec; // World-space light vector// Light propertiesuniform vec4 Ii; // Light brightness uniform vec4 Ia; // Ambient light term// Surface propertiesuniform vec4 Kd; // Reflection coefficientuniform vec4 Ks; // Specular coefficientuniform vec4 Ka; // Ambient coefficientuniform float n; // Surface reflectivityvoid main(void) {	// Normalize incoming vectors	vec3 L = normalize(lightVec);	vec3 V = normalize(viewVec);	// Calculate the diffuse component	vec4 Id = Kd * max(dot(L, normal), 0.0);	// Calculate reflection vector	vec3 R = normalize(reflect(L, normal));	// Calculate the specular component	vec4 Is = Ks * pow(max(dot(R, V), 0.0), n);	// Add the components together	gl_FragColor = Ia * Ka + Ii * (Id + Is);}