PDA

View Full Version : Problem with lighting in GLSL



Alessandro_dup1
12-25-2004, 01:37 AM
I have a problem which i hope i can explain (there is also a screenshot here (http://www.flightzone.us/trouble.jpg) )
I currently have a 3d world where objects can rotate freely, and a camera that can be rotated as well to pan all the world.
When the camera is rotated, light "follows" the camera to mantain correct lighting.
I do the following and it works:

glLoadIdentity();
glTranslatef(0,0,-50);
glRotatef(cameraz_pov, 0.0, 0.0, 1.0);
glRotatef(camerax_pov, 1.0, 0.0, 0.0);
glRotatef(cameray_pov, 0.0, -1.0, 0.0);
LightPos2[0]=0; LightPos2[1]=200; LightPos2[2]=-50;
glLightfv(GL_LIGHT2, GL_POSITION, LightPos2);
glRotatef(psi, 0, -1, 0);
glRotatef(theta, 1, 0, 0);
glRotatef(phi, 0, 0, -1);
Draw_Objects();
As you can see i set light position after camera controls.

Now, i decided to convert to GLSL, but the problem is that when i rotate the camera light doesn't, messing up the lighting. I can't figure out how to overcome to that. The shader does it job lighting the object but, again, i'd like that when camera is rotated, lighting would properly go with that.
The GL fixed routine has been modified as follows:



glLoadIdentity();
glTranslatef(0,0,-50);
glRotatef(cameraz_pov, 0.0, 0.0, 1.0);
glRotatef(camerax_pov, 1.0, 0.0, 0.0);
glRotatef(cameray_pov, 0.0, -1.0, 0.0);
glUniform3fARB(glGetUniformLocationARB(g_programOb j, "LightPosition"), 0.0, 200.0, -50.0);
glUseProgramObjectARB( g_programObj );
glRotatef(psi, 0, -1, 0);
glRotatef(theta, 1, 0, 0);
glRotatef(phi, 0, 0, -1);
Draw_Objects();
glUseProgramObjectARB( NULL );
Vertex prog:

varying vec2 v_texCoord;
uniform vec3 LightPosition;
const float SpecularContribution = 0.3;
const float DiffuseContribution = 1.0 - SpecularContribution;
varying float LightIntensity;
varying vec2 MCposition;
void main(void)
{
vec3 ecPosition = vec3 (gl_ModelViewMatrix * gl_Vertex);
vec3 tnorm = normalize(gl_NormalMatrix * gl_Normal);
vec3 lightVec = normalize(LightPosition - ecPosition);
vec3 reflectVec = reflect(-lightVec, tnorm);
vec3 viewVec = normalize(-ecPosition);
float diffuse = max(dot(lightVec, tnorm), 0.0);
float spec = 0.0;

if (diffuse > 0.0)
{
spec = max(dot(reflectVec, viewVec), 0.0);
spec = pow(spec, 16.0);
}

LightIntensity = DiffuseContribution * diffuse +
SpecularContribution * spec;

MCposition = gl_Vertex.xy;
gl_Position = ftransform();
v_texCoord = gl_MultiTexCoord0.xy;
v_color = gl_Color;
}
Frag Prog:

uniform vec3 BrickColor, MortarColor;
uniform vec2 BrickSize;
uniform vec2 BrickPct;
uniform sampler2D testTexture;
varying vec2 v_texCoord;
varying vec4 v_color;


varying vec2 MCposition;
varying float LightIntensity;

void main(void)
{
BrickSize[0]=0.3;
BrickSize[1]=0.15;
BrickPct[0]=0.0;
BrickPct[1]=0.4;
BrickColor[0]=1;
BrickColor[1]=1;
BrickColor[2]=1;
MortarColor[0]=.8;
MortarColor[1]=.8;
MortarColor[2]=.8;
vec3 color;
vec2 position, useBrick;
position = MCposition / BrickSize;
if (fract(position.y * 0.5) > 0.5)
position.x += 0.5;
position = fract(position);
useBrick = step(position, BrickPct);
color = mix(MortarColor, BrickColor, useBrick.x * useBrick.y);
color *= LightIntensity;
gl_FragColor = vec4 (color*texture2D( testTexture, v_texCoord ), 1);
}
Any help would be greatly appreciated. Merry Xmas to everybody !

Alessandro_dup1
12-25-2004, 02:20 AM
I think i solved it, but i'd like to hear some advices anyway if this is a clever way to do it.
I modified the main function as follows:


glUseProgramObjectARB( g_programObj );
LightPos2[0]=0; LightPos2[1]=0; LightPos2[2]=0;
glLoadIdentity();
glTranslatef(0,0,-50);
glRotatef(cameraz_pov, 0.0, 0.0, 1.0);
glRotatef(camerax_pov, 1.0, 0.0, 0.0);
glRotatef(cameray_pov, 0.0, -1.0, 0.0);
LightPos2[0]=0; LightPos2[1]=-5; LightPos2[2]=-4;
glRotatef(psi, 0, -1, 0);
glRotatef(theta, 1, 0, 0);
glRotatef(phi, 0, 0, -1);
Draw_Objects();
glUseProgramObjectARB( NULL );
And in the vertex program i grab the light position as follows:



LightPosition=gl_LightSource[2].position;
In practice i set light at 0,0,0 before camera controls and then i set it where i want it before drawing the object.