I still didn't get rid of some annoying bugs in my glsl shader (GL 2.0)... I searched for a solution of this problem for over 3 weeks now, but I didn't get any. There are many examples and explanations on google, but none of them really works.
First of all, here is my fragmentshader code. After that I will explain what exactly the problem is:
//fragmentshader
const int MAX_POINT_LIGHTS = LL.MAX_POINT_LIGHTS;
const int MAX_DIR_LIGHTS = LL.MAX_DIR_LIGHTS;
const int MAX_TEXTURES = LL.MAX_TEXTURES;
//float-precision
precision mediump float;
//varyings
varying vec2 texcoord;
varying vec3 normal;
varying vec3 position;
varying float depth;
//pointlights
uniform float pl_range[MAX_POINT_LIGHTS];
uniform vec3 pl_position[MAX_POINT_LIGHTS];
uniform vec3 pl_color[MAX_POINT_LIGHTS];
uniform vec3 pl_specular[MAX_POINT_LIGHTS];
//dirlights
uniform vec3 dl_direction[MAX_DIR_LIGHTS];
uniform vec3 dl_position[MAX_DIR_LIGHTS];
uniform vec3 dl_color[MAX_DIR_LIGHTS];
uniform vec3 dl_specular[MAX_POINT_LIGHTS];
//cameras
uniform vec3 camera;
//fog
uniform vec4 uVecFog;
uniform float uFogNear;
uniform float uFogFar;
//material
uniform vec3 mat_diff;
uniform vec3 mat_spec;
uniform float mat_shine;
uniform float mat_elum;
//texture
uniform sampler2D uTexture;
//ambientlight
vec4 ambient = vec4(0.0,0.0,0.0,0.0);
void main() {
vec3 N = normalize(normal);
vec3 V = normalize(camera - position);
vec4 diff = vec4(0.0,0.0,0.0,0.0);
vec4 spec = vec4(0.0,0.0,0.0,0.0);
//dirlights
for(int i=0;i<MAX_DIR_LIGHTS;i++) {
vec3 L = -normalize(dl_direction[i]);
vec3 R = -normalize(reflect(L,N));
float RV = max(dot(R,V),0.0);
float S = pow(max(dot(R,V),0.0),mat_shine);
float F = clamp(dot(L,N),0.0,1.0);
diff += vec4(F * mat_diff * dl_color[i],1.0);
spec = vec4(S * mat_spec * dl_specular[i],1.0);
}
//pointlights
for(int i=0;i<MAX_POINT_LIGHTS;i++) {
vec3 L = normalize(pl_position[i] - position);
vec3 R = -normalize(reflect(L,N));
float D = distance(pl_position[i],position);
float DF = clamp(1.0 - D/pl_range[i],0.0,1.0);
float S = pow(max(dot(R,V),0.0),mat_shine);
float F = clamp(DF * max(dot(L,N),0.0),0.0,1.0);
diff += vec4(F * mat_diff * pl_color[i],1.0);
spec += vec4(DF * S * mat_spec * pl_specular[i],1.0);
}
//fog
float fogDensity = 0.0;
if (depth > uFogFar) {
fogDensity = 1.0;
} else if(depth > uFogNear) {
float newDepth = depth-uFogNear;
fogDensity = newDepth/(uFogFar-uFogNear);
} else if (depth < uFogNear) {
fogDensity = 0.0;
}
vec4 vecFog = uVecFog * fogDensity;
//texturecolor
vec4 colortex = texture2D(uTexture,vec2(texcoord.x,-texcoord.y));
//final fragmentcolor
gl_FragColor = mix((ambient + colortex * (diff + vec4(mat_diff * mat_elum,1.0)) + spec),vecFog,fogDensity);
}
There are give following variable-values, where:
- pl_ are pointlightvalues,
- dl_ are directionallightvalues,
- mat_diff is the diffuse-value for the material,
- also mat_spec, mat_elum, mat_shine for material specular, elumination and shininess,
- N = Normal,
- V = View-Vector to Vertex,
- L = Light-Vector to Vertex,
- R = Reflection Vector,
- D = Lightdistance,
- DF = Distancefactor for blending light,
- S = Calculated Specularityfactor,
- F = Dotproduct from L,N
- and diff, spec vectorsum of the calculated diffuse/spec-vectors.
Now there occures following problem: Pointlights themself run perfect. Directionallights themself run perfect, too. But together they won't work very well. I'll precise the problem: I've got 4 Pointlights and 4 Directionallights for maximum. For testing i've used 4 Pointlights and 1 Directionallight.
- If i commented out the for-loop calculation the directionallights, i got following result:
- If i commented out the for-loop for pointlights, i got following result:
- If i enabled both for-loops, following happens:
The directionallight seems to be ignored completly. The car is lighted only by the pointlights instead.
So, what I found out: If I change the order of the for-loops, pointlights -> directionallights, instead of dirlights -> pointlights, the effect swaps: pointlights are ignored, directionallight is computed.
What I found out too, this problem must be up to: pow() function or dividing by zero, but: If I comment out follwing lines of code:
spec = vec4(S * mat_spec * dl_specular[i],1.0);
spec += vec4(DF * S * mat_spec * pl_specular[i],1.0);
i can get following result:
-> The diffuse color is computed normally for point AND directionallights!
So I thought of how to eliminate this problem, because I thought about 0 powered by 0 leads to a math error. Dividing by zero, too.... How can I avoid values that are undefined?
isnan() or isinf() functions seem not to exist in android-glsl.
Andy solutions or tipps what I could do better, that this will work? I would be glad about any answer if it could help a little bit. This makes me mad since 3 weeks. Thanks so much for helpers! :)
More information about the code: https://github.com/Chrise55/Llama3D
Chrise