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!
gl_NormalMatrix / gl_ModelViewMatrix inside Fragment shader ?
Started by dimensionX, Oct 07 2004 12:12 PM
7 replies to this topic
Sponsor:
#3 Members - Reputation: 100
Posted 07 October 2004 - 01:34 PM
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);
}
----------------------------------------------------------------
-----------------
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);
}
----------------------------------------------------------------
#4 Members - Reputation: 1338
Posted 07 October 2004 - 06:55 PM
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?
#5 Members - Reputation: 100
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!
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!
#6 Members - Reputation: 432
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.
gl_NormalMatrix is the inverse transpose of the upper 3x3 part of the modelview matrix.
#8 Members - Reputation: 432
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:
Vertex shader:
Fragment shader:
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?
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-light
uniform vec4 lightPosition;
// Values interpolated across the polyogon
varying vec3 normal; // Vertex-normal
varying vec3 viewVec; // World-space view vector
varying vec3 lightVec; // World-space light vector
void 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 polyogon
varying vec3 normal; // Vertex-normal
varying vec3 viewVec; // World-space view vector
varying vec3 lightVec; // World-space light vector
// Light properties
uniform vec4 Ii; // Light brightness
uniform vec4 Ia; // Ambient light term
// Surface properties
uniform vec4 Kd; // Reflection coefficient
uniform vec4 Ks; // Specular coefficient
uniform vec4 Ka; // Ambient coefficient
uniform float n; // Surface reflectivity
void 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?






