gl_NormalMatrix / gl_ModelViewMatrix inside Fragment shader ?
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!
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);
}
----------------------------------------------------------------
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?
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!
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.
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!
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:
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-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
Popular Topics
Advertisement