graphics3draytracinglightingshading

Shading with squared falloff always makes everything black


I have recently tried to change the current way I calculate diffuse lighting in my RayTracer. It used to be calculated like this:

 float lambert = (light_ray_dir * normal) * coef;
 red += lambert * current.color.red * mat.kd.red;
 green += lambert * current.color.green * mat.kd.green;
blue += lambert * current.color.blue * mat.kd.blue;

where coef is an attenuation coefficient that starts at 1 for each pixel and is then attenuated for each reflected ray that is generated by this line:

coef *= mat.reflection;

This worked well.

But I decided to try something more realistic and implemented this:

float squared_attenuation = LIGHT_FALLOFF * lenght;
light_intensity.setX ((current.color.red /*INTENSITY*/)/ squared_attenuation);
light_intensity.setY ((current.color.green  /*INTENSITY*/)/ squared_attenuation);
light_intensity.setZ ((current.color.blue  /*INTENSITY*/)/ squared_attenuation);
red   += ALBEDO * light_intensity.getX() * lambert * mat.kd.red;
green += ALBEDO * light_intensity.getY() * lambert * mat.kd.green;
blue  += ALBEDO * light_intensity.getZ() * lambert * mat.kd.blue;

where LIGHT_FALLOFF it is a constant value:

#define LIGHT_FALLOFF M_PI * 4

and length it is the length of the vector that goes from the point light center to the intersect point:

inline float normalize_return_lenght ()  {
     float lenght = sqrtf (x*x + y*y + z*z);
     float inv_length = 1/lenght;
     x = x * inv_length, y = y * inv_length, z = z * inv_length;
     return lenght;
  }

float lenght = light_ray_dir.normalize_return_lenght ();

The problem is that all this is generating nothing more than a black screen! The main culprit is the length that goes as the divisor in the light_intensity.set. It makes the final color values being some value ^ -5. However, even if I replace it by one (ruining my goal of a realistic light attenuation), I still get color values to close to zero still, hence a black image.

I tried to add another light_sources closer to the objects, however the fact that the models that shall be shaded are made of multiple polygons with different coordinates, make hard to determine a goodl ocation for them.

So I ask. It seems normal to you that this is happening or it seems a bug? For me theory, does not seems strange for me, since the attenuation is quadratic.

Is does not seem, there is a some hint as to where to place the light sources, or to anything as can get an image that is not all black?

Thanks for reading all this!

P.S: Intensity is commented out because on the example that I used to do my code, it was one


Solution

  • So you are assuming that the light has a luminosity of "1" ? How far away is your light? If your light is - say - 10 units away, then they contribution from the light will be 1/10, or a very small number. This is probably why your image is dark. You need to have quite large numbers for your light intensity if you are going to do this. In one of my scenes, I have a light that is about 1000 units away (pretending to be the Sun) and the intensity is 380000!! Another thing ... to simulate reality, you should be using 1 / length^2. The light intensity falls off with the square of distance, not just with distance. Good luck!