Jump to content

  • Log In with Google      Sign In   
  • Create Account


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.

  • You cannot reply to this topic
7 replies to this topic

#1 dimensionX   Members   -  Reputation: 100

Like
0Likes
Like

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!

Sponsor:

#2 phantom   Moderators   -  Reputation: 7114

Like
0Likes
Like

Posted 07 October 2004 - 12:57 PM

a code snippet would be helpfull....

#3 dimensionX   Members   -  Reputation: 100

Like
0Likes
Like

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);
}
----------------------------------------------------------------

#4 Trienco   Crossbones+   -  Reputation: 2126

Like
0Likes
Like

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 dimensionX   Members   -  Reputation: 100

Like
0Likes
Like

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!

#6 James Trotter   Members   -  Reputation: 432

Like
0Likes
Like

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.

#7 dimensionX   Members   -  Reputation: 100

Like
0Likes
Like

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!

#8 James Trotter   Members   -  Reputation: 432

Like
0Likes
Like

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:

/* 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?




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.



PARTNERS