Ray tracing scene with 2 lights and sphere I'm writing my implementation of ray tracer and I've got result which you can see at this image.


So you can see that some dark parts are overlapping. And I have them even in the part where it should be bright in my opinion. There are two lights one from above and the second one from right-bottom corner.

And I have two questions. Is it right? I really tried to google some references but failed. I'm not still sure that results in my imagination are correct ones.

And the second one where does it come from?

I use usual lambertian shading model and have something like this in my code:

pixel = (0, 0, 0)
normal = get normal of sphere in point of intersection;
normal = unit vector of normal;
for each light from light_set {
    light = unit vector of light;
    pixel = pixel + diffuseColor * max(0, scalar multiplication of light and normal);
}


I'm really struggling to find out the reason where this strange thing is coming from. But couldn't find it.

UPD0: added some of my real code. The part which is described here is next:

Material mat = surfaces[closestSurfase]-&gt;getMaterial();
Color pixel = Color(0, 0, 0);
Vector3f normal = surfaces[closestSurfase]-&gt;getNormal(point).getUnitVector();
Vector3f view = -ray.getDirection().getUnitVector();
for (size_t i = 0; i &lt; lights.size(); ++i) {
    Vector3f normal_light = lights[i]-&gt;getDirection().getUnitVector();
    Vector3f specVect = (normal_light + view).getUnitVector();
    float intenst = lights[i]-&gt;getIntensity();
    pixel = pixel + mat.getDiffuse() * std::max(0.0f, normal_light.dotMultiply(normal)) * intenst;
}
result-&gt;setPixel(x, y, pixel);


Or you can find more here: https://github.com/minebv/ray_tracer/tree/lambertian_shading_fix/src

Described above is from Camera's method getRender.

UPD1: It looks like the problem in the mixing colors in gamma space instead linear one, as answered @PaulHK .

But I've still some kind of problem. Here you can see 2 renders.

At the left one I make all work after transformation all colors into linear space, I mean it's like this in my code:

pixel = pixel + mat.getDiffuse().toLinear() * std::max(0.0f, normal_light.dotMultiply(normal)) * intenst;


At the right one I make transformation after multiplying:

pixel = pixel + (mat.getDiffuse() * std::max(0.0f, normal_light.dotMultiply(normal)) * intenst).toLinear();


And I didn't forget to make pixel into gamma space again after all job.

As for me, the right one is more correct. But then there is a question: why should I make multiplication on angle into gamma space? Or is it my incorrect way to think about what is right?

UPD3:it looks like the whole thing really was about mixing colors in gamma space instead of linear one. Here is result with ambient light.


Also about overlapping lights, it was my incorrect way of thinking. I finally found reference material where they have the same thing. Found it at blender docs.

Thank everyone for answers.
I think what you're describing is what happens when you mix colours in gamma space. You should be using linear colour space when mixing.

When reading colours of lights and materials, convert them from gamma->linear using the inverse gamma function.

colourLin = pow(colourLight, 2.2);
... do lambert calculation here and accumulate in 'colour' variable ..

// On output (linear-&gt;gamma conversion)
gl_FragColor = pow(colour, 1.0/2.2);


There is an in depth chapter in GPU Gems on this topic: The Importance of Being Linear.