HELP: GLSL Lighting problem.

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
christianclavet
Posts: 1638
Joined: Mon Apr 30, 2007 3:24 am
Location: Montreal, CANADA
Contact:

HELP: GLSL Lighting problem.

Post by christianclavet »

Hi, I'm really noob in shaders and tried to improve the terrain shader that was made by Andres for our project.

This shader use the vertex height in the model to blend and to put tiled texture on a model.
For the texturing, it work perfectly as intented. I found some GLSL code in a tutorial site on GLSL and tried to add a directional light using GL_LightSource[0] and defined directly a position for this light in the shader.

The shader "work" kinda, on NVIDIA Hardware and on INTEL HD hardware. Tried it on AMD RADEON HD 7750 and the light channel give me a total black and darken the terrain completely.

Here is a screenshot with the light being properly cast over the terrain: (Render like this on NVIDIA and INTEL HD)
Image
If I use the same on RADEON HD 7750, the image is all dark (rest of rendering is still ok, we can still see the blending of the textures)

EDIT: With some friends, we tested the shader with multiple AMD RADEON cards:
- NVIDIA GTX: work
- INTEL HD: work
- AMD RADEON 4800 SERIES: Work
- AMD MOBILITY 5400 SERIES: Work
- AMD RADEON 7000 SERIES: Fail (Compile but wrong rendering)
So far this problem seem to occur only on the RADEON 7000 series of cards. I don't know what to think now!

Most of it is done in the fragment/pixel shader, so here is the code:

Code: Select all

uniform sampler2D terrainLayer0;
uniform sampler2D terrainLayer1;
uniform sampler2D terrainLayer2;
uniform sampler2D terrainLayer3;
 
uniform float plateau;
uniform int terrainTextureScale;
uniform int terrainScale;
 
uniform int editingTerrain;
 
uniform vec4 AmbientLight;
 
varying vec3 normal;
varying vec3 position;
varying vec4 worldCoord;
 
void main() 
{
    float scale = float(terrainScale);
        
    vec2 texCoord = vec2(gl_TexCoord[0]);
    
    vec4 tex0    = texture2D( terrainLayer0, texCoord.xy*float(terrainTextureScale));
    vec4 tex1    = texture2D( terrainLayer1, texCoord.xy*float(terrainTextureScale));
    vec4 tex2    = texture2D( terrainLayer2, texCoord.xy*float(terrainTextureScale));
    vec4 tex3    = texture2D( terrainLayer3, texCoord.xy*float(terrainTextureScale));
 
    //tex1 = mix( tex0, tex1, min(1.0-normal.y,1.0) );
    
    // First layer of composition soil & grass blending
    float position2=position.y+200.0;
    if (position2>128.0 && position2<256.0)
        tex1 = mix( tex1, tex0, 1.0-(position2-128.0)/128.0);
    
    if (position2<=128.0)   
        tex1=tex0;
    
    // Second composition of first block and rock blending
    if (position2>256.0 && position2<512.0)
        tex2 = mix( tex1, tex2, ((position2-256.0)/256.0));
 
    if (position2<=256.0)
        tex2 = tex1;
        
    // Third composition of first block and snow blending
    if (position2>620.0 && position2<768.0)
        tex3 = mix( tex2, tex3, ((position2-620.0)/148.0));
        
    if (position2<=620.0)
        tex3 = tex2;
 
    vec4 tex10 = tex3;
    
    //Plateau band
    if(position.y>(plateau-1.5) && position.y<(plateau+1.5) && editingTerrain==1) 
        tex10=vec4(0.0,0.5,0.0,0.5);
        
    // Directional light no attenuation (Sun)
    vec3 norm = normalize(normal);
    vec3 sunVector = normalize(vec3(0,50000,-50000) - worldCoord.xyz);
    float sunDir = max(0.0, dot(norm, sunVector));
    
    vec4 diffuse;
    diffuse = (gl_LightSource[0].diffuse * sunDir*1.45); //1.45 brighten the whole texture
    
    // Rendering with 1 directional light source 
    vec4 finalColor = ((0.45+diffuse) * vec4(tex10.rgb, 1.0))*AmbientLight; //0.45 diffuse the shadowing
    
    // Rendering with no light source
    //vec4 finalColor = (vec4(tex10.rgb, 1.0))*AmbientLight;
    
    //Fog blending
    float fog = (gl_Fog.end - gl_FogFragCoord) * gl_Fog.scale;
    gl_FragColor = mix(gl_Fog.color,finalColor, fog);
}
EDIT: Added the vertex shader as the problem could be inside this instead. It seem that on AMD 7000 series of cards, some of the returning varying are wrong. (My idea about this, but why?)

Code: Select all

#version 150 compatibility
varying vec3 normal;
varying vec3 position;
varying vec4 worldCoord;
 
void main(void)
{
    //gl_Position = ftransform();
    gl_Position =  gl_ModelViewProjectionMatrix * gl_Vertex;
    gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
    gl_FogFragCoord = gl_Position.z;
    normal = gl_Normal.xyz;
    position = gl_Vertex.xyz;
    worldCoord = gl_ModelViewMatrix * gl_Vertex;
}
 
I think the problem occur in that part (EDIT: GL_LightSource[0].diffuse is being used and is OK for this ATM)

Code: Select all

// Directional light no attenuation (Sun)
    vec3 norm = normalize(normal);
    vec3 sunVector = normalize(vec3(0,50000,-50000) - worldCoord.xyz);
    float sunDir = max(0.0, dot(norm, sunVector));
    
    vec4 diffuse;
    diffuse = (gl_LightSource[0].diffuse * sunDir*1.45); //1.45 brighten the whole texture
    
    // Rendering with 1 directional light source 
    vec4 finalColor = ((0.45+diffuse) * vec4(tex10.rgb, 1.0))*AmbientLight; //0.45 diffuse the shadowing
Have some questions:
With Irrlicht how GL_LigthSource[0] is used? (I have created a Irrlicht directional light in Irrlicht, but does'nt seem to link to that). Have someone have more information on GL_LightSource? I'm not sure I understand well how this work.

Would it be way to use the Irrlicht light information to be sent to the shader via UNIFORMS? So I could perhaps change that part of code here and hopefully have a OK rendering on AMD Hardware also? If I pass the light information via uniform, how to get the .diffuse?

Also got question about Irrlicht Directionnal light... Is there a command to increase the intensity? I barely see the light effect on the non-shader models.
Last edited by christianclavet on Tue Oct 15, 2013 2:06 pm, edited 5 times in total.
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Re: GLSL Lighting problem.

Post by Nadro »

If you use the latest trunk please don't use any built-in GLSL variables related to fixed pipeline lighting. gl_LightSource is depend on GL_COLOR_MATERIAL state + used values in glMaterialfv (for material color etc.) methods and GL_LIGHTING state + used values in glLightfv methods (eg. position etc.). From performance point of view you should send uniforms manually in shader callback. You can set current used material in shader callback via OnSetMaterial method and next you can use values from this material in OnSetConstants method etc. Of course in shader callback you can also read lights values, so you can send it as uniforms too.

Remember that you don't need update all uniform in each OnSetConstants call - if uniform value didn't change.
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
christianclavet
Posts: 1638
Joined: Mon Apr 30, 2007 3:24 am
Location: Montreal, CANADA
Contact:

Re: GLSL Lighting problem.

Post by christianclavet »

Hi, Nadro! Thank for your reply.
If you use the latest trunk please don't use any built-in GLSL variables related to fixed pipeline lighting.
So it will be no longer supported starting from 1.9?
gl_LightSource is depend on GL_COLOR_MATERIAL state + used values in glMaterialfv (for material color etc.) methods and GL_LIGHTING state + used values in glLightfv methods (eg. position etc.).
You mean GL States used by Irrlicht? This part is too advanced... I don't even know how to use the view matrices... :( barely understand how this work, my math skills are too poor.
Of course in shader callback you can also read lights values, so you can send it as uniforms too.
Sorry, how can I send a light to a uniform? (except it's position or color, like a vec3, vec4)

From what I understand now, is that the GL_LightSource, (is a build-in variable), that use the fixed pipeline lighting (from what you mention), but since they use the fixed pipeline lighting mechanism, I will have to find another way to light the model. So redo all the GLSL code that is doing the lighting.

EDIT:
I checked the docs on the openGL web site, could this help? I added this to the top of the shader code:

Code: Select all

#version 150 compatibility
Because right now, even if it using the fixed pipeline lighting, it work on NVidia and INTEL. The only hardware that did not render properly was AMD (Shader compile was ok, but bad rendering)

I'm using Irrlicht 1.8.0 on the project right now.

I searched the web for any tutorial about glsl directional lighting that don't use the fixed pipeline, and did not find any... If someone has some infos or tutorials on creating directional lighting (like the fixed pipeline was doing) it would be greatly appreciated. Right now my main problem is to make the shader render properly on AMD hardware.
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Re: GLSL Lighting problem.

Post by Nadro »

Hi,

Yes in v1.9 it will be not supported. I added information about it in changes.txt file. What about lighting? You can check eg. COpenGLNormalMapRenderer.cpp file from line 260 to 282 where we're sending lighting informations as uniforms. You can do it in the same way in your own shader. If you use OpenGL 2.x driver (Irrlicht use it) you don't need "#version" statement in GLSL. This keyword is important only for OpenGL3.x+ drivers.

Cheers,
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
christianclavet
Posts: 1638
Joined: Mon Apr 30, 2007 3:24 am
Location: Montreal, CANADA
Contact:

Re: GLSL Lighting problem.

Post by christianclavet »

What about lighting? You can check eg. COpenGLNormalMapRenderer.cpp file from line 260 to 282 where we're sending lighting informations as uniforms.
Thanks for the information! So GL_LightSource[0].diffuse is NOT a "map" of a channel, but only the diffuse color of the light!
After a test, determined that it is not the problem (GL_LightSource[0].diffuse). I entered a "static" value and the result was the same.

The problem might come from the vertex shader that returning the "normal" or "worldCoord" values of the vertices and that the pixel shader use like this:

Code: Select all

    vec3 norm = normalize(normal);
    vec3 sunVector = normalize(vec3(0,50000,-50000) - worldCoord.xyz);
    float sunDir = max(0.0, dot(norm, sunVector));
Sundir will return the intensity of the light for the pixel based on the "normal" direction and the angle of the light. Will then be multiplied in with the diffuse map.
SunVector should normally, take a world coordinate of the light and use it in model space, and return a directional vector (If I understand this correctly)

I think this part is ok in the pixel shader, but since it use the "normal" or "worldCoord" from the vertex shader, the problem is probably there.
Is there something in this vertex shader code that could cause the normal or worldcoord function to return a dark value? (This is happening only on AMD Radeon HD, work fine on NVidia, and INTEL HD)

Code: Select all

varying vec3 normal;
varying vec3 position;
varying vec4 worldCoord;
 
void main(void)
{
    //gl_Position = ftransform();
    gl_Position =  gl_ModelViewProjectionMatrix * gl_Vertex;
    gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
    gl_FogFragCoord = gl_Position.z;
    normal = gl_Normal.xyz;
    position = gl_Vertex.xyz;
    worldCoord = gl_ModelViewMatrix * gl_Vertex;
}
christianclavet
Posts: 1638
Joined: Mon Apr 30, 2007 3:24 am
Location: Montreal, CANADA
Contact:

Re: HELP: GLSL Lighting problem.

Post by christianclavet »

Hi, Just to update on my problem with the shader. The rendering is only wrong on AMD RADEON 7000 SERIES of cards. I was able to see the rendering done correctly yesterday on a friend computer that have an old AMD RADEON 4850.

Look like the SERIES 7000 doesnt like the normals information coming back in the varying, but I don't know why.
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Re: HELP: GLSL Lighting problem.

Post by Nadro »

You should output normal as a final fragment result for compare those values. Are you sure that problems is related to normals? Maybe you should update drivers?
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
christianclavet
Posts: 1638
Joined: Mon Apr 30, 2007 3:24 am
Location: Montreal, CANADA
Contact:

Re: HELP: GLSL Lighting problem.

Post by christianclavet »

Hi, The shader has been tested on 3 systems that failed to render the shading properly. I was also thinking the video card driver was the culprit but it was updated to the lastest version on each system. Irrlicht report support for GLSL 4.X and OPENGL 4.X for those cards.

2 different system with a Radeon HD 7750 and another system with a radeon hd 7850. Each of them, return "dark" and uniform shadowing. If you check how the shadowing is done, it's based on the vertice normal with the light position (world space). For me it look like the normal value is not returned properly into the fragment shader. (At least that my only logic conclusion)

Nice idea for the normal as final value. I could see that to be 100% sure.
EDIT:
Confirmed! Your trick exposed directly the problem.

Tested the shader on an NVidia GTX 560: Terrain is green turning with red color depending on the faces, I see gradation of colors on the hills. So the shader render correctly.

Same shader on the AMD RADEON 7850: Terrain is all FLAT red. I don't see gradation at all of the colors on the hills. So this is definitively the normal that is not returned properly from the varying.

Does someone know what could cause that?
Post Reply