Jump to content
  • Advertisement
Sign in to follow this  
dimensionX

OpenGL gl_NormalMatrix / gl_ModelViewMatrix inside Fragment shader ?

This topic is 5030 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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!

Share this post


Link to post
Share on other sites
Advertisement
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);
}
----------------------------------------------------------------

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!