gl_NormalMatrix / gl_ModelViewMatrix inside Fragment shader ?

Started by
6 comments, last by James Trotter 19 years, 6 months ago
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!
Advertisement
a code snippet would be helpfull....
Fragment Shader:-
-----------------
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.

Vertex Shader:-
---------------
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);
}

Fragment Shader:-
------------------
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);
}
----------------------------------------------------------------
Quote:Original post by dimensionX
What 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?
f@dzhttp://festini.device-zero.de
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!
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.
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!
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:

Vertex shader:
/*	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();}


Fragment shader:
/*	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);}


Here gl_NormalMatrix is used to transform the normal vectors in the vertex shader. If you remove gl_NormalMatrix, you're going to get some weird and wrong results. Why don't you try it?

This topic is closed to new replies.

Advertisement