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]->getMaterial();
Color pixel = Color(0, 0, 0);
Vector3f normal = surfaces[closestSurfase]->getNormal(point).getUnitVector();
Vector3f view = -ray.getDirection().getUnitVector();
for (size_t i = 0; i < lights.size(); ++i) {
Vector3f normal_light = lights[i]->getDirection().getUnitVector();
Vector3f specVect = (normal_light + view).getUnitVector();
float intenst = lights[i]->getIntensity();
pixel = pixel + mat.getDiffuse() * std::max(0.0f, normal_light.dotMultiply(normal)) * intenst;
}
result->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.