GLSL is defying all mathematical logic with simple lighting

It really is. And it’s bugging me alot.

I have a really simple raymarching shader set up generating terrain on a function of f(x, z) = sin(x) * -sin(z). Obviously this creates a rolling terrain, and this all works fine. My problem is with my lighting, for some reason my ambient value blatantly refuses to be applied. This could be some weird GLSL thing, I’m not sure.

My code to generate the lighting (point light currently) is here for reference:


// p is the position of the ray at its final intersection iteration

vec3 c = texture2D(iChannel0, p.xz).xyz;
vec3 n = calcNormal(p);
        
float b=dot(n, normalize(lightPos-p));
        
float r = 15.0;
float d = max(length(lightPos-p) - r, 0.0);
float denom = d/r + 1.0;
float attenuation = 1.0 / (denom*denom);
                
float ambient = 0.03;
        
col = ((b*c+pow(b,32.0))*(1.0-t*.01)*attenuation)+ambient;

I then assign gl_FragColor to col. This works just fine, specular lighting and diffuse lighting works. However the ambient value isn’t added at all. Even when I directly add 1.0 to col, the areas that wouldn’t be lit by the point light stay completely black. The WHOLE rest of the scene is white like expected. Very very strange.

I’d really appreciate any suggestions.

Here’s the link to the shader on shadertoy:
https://www.shadertoy.com/view/4tlGzr

Edit: removed some profanity I typed in my anger.

Hi,

GLSL itself is most likely just fine, but I reckon that after having a glimpse at your calculation that you produce negative values for those areas that should not receive diffuse or specular lighting, because there is a subtraction operator used in the final result. And adding +1 to it would likely not make the whole value greater than 0.0.
OpenGL renders all values less than or equal to 0.0 as black.

That’s just my guess.

EDIT: I think, the most serious source for your color value becoming negative, is actually your dot-product between ‘n’ and light direction. This will become negative iff the surface normal ‘n’ faces away from the light. It needs to be clamped with max(0.0, b).

Thanks, I’m not sure how I overlooked that. I suppose I don’t know exactly how my lighting works.
Anyways, that does seem to work. I had to change it to clamp to a minimum of 0.2 because if it was 0.0 it would multiply c (the texture value) and make it 0 obviously. So even when I applied ambient it would return varying shades of darkness. I suppose that 0.2 max kind of acts as my ambient. Anyways, it works, thanks! On to perlin/opensimplex noise.