0

I'm implementing an illumination model using as reference Phong formulation. It's not quite clear for me yet how to appropriately make possible to render material in different colors. I'm not using textures. The basic equations that I'm using for each pixel, given a light point, is shown below:

Result.R := Ia.R*ka.R + P.IL.R*((M.kd.R*LN) + (M.ks.R*Power(Max(VR,0),M.Ns)));
Result.G := Ia.G*ka.G + P.IL.G*((M.kd.G*LN) + (M.ks.G*Power(Max(VR,0),M.Ns)));
Result.B := Ia.B*ka.B + P.IL.B*((M.kd.B*LN) + (M.ks.B*Power(Max(VR,0),M.Ns)));

Result.R := Round(Result.R*255/3);
Result.G := Round(Result.G*255/3);
Result.B := Round(Result.B*255/3);

(* Where:
  Result : (R,G,B) color of pixel;
  Ia: intensity of Ambient Light for each component R, G, B;
  ka: material coefficient for reflection of ambient light;
  P: Dot Light;
  IL: intensity of Dot Light for each component R, G, B;
  kd: material coefficient for diffuse reflection of Dot Light;
  ks: material coefficient for specular reflection of Dot Light;
  LN: dot product (L.N);
  VR: dot product (V.R);
  L: Vector from pixel to Dot Light;
  N: Normal vector on the pixel;
  V: Vector from pixel to Observer;
  R: Reflected vector of L relative to N; *)

The maximum value for each equation is 3, because each parcel (Ia.R*ka.R, for example) is at most 1. I adapt the result so each component (Result.R, Result.G and Result.B) stay in the range from 0 to 255.

It's not exactly programmed this way, because when there's more than one Dot Light, I calculate the sum of the Diffuse and Specular components of all lights in Result. The Ia*ka components don't change. Instead of dividing above by 3, it's then divided by another number (if there are 2 Dot Lights, it's divided by 5. If there are 3, by 7, and so on).

This kind of implementation allows me to control the material color through the ka, kd and ks coefficients. The light color overall is controled by Ia and P.IL. The model which I've been following is similar to this one I found on Wikipedia.

I would like to know then if I commited some kind of mystake, if I misinterpreted Phong's formulation. I know there are many versions of Phong's Illumination Model, but I would like to learn which ones give the possibility of changing the material and lights colors.

Thanks in advance, I appreciate all the attention and help :)

1 Answers1

1

One mistake you are making is normalizing your values instead of clamping. You should at the very end, clamp your result between 0 and 1. By dividing the numbers like that, you are saying each light source contributes less the more light sources there are.

Let's say for example there are 10 very very powerful lights shining on the same area, but only one is turned on. In this case we'd expect a really larger number still because even one light is very bright (close to 1), but because you divide them out, it's only a tiny fraction of what it should have been.

Second is you missed this line: "Although the above formulation is the common way of presenting the Phong reflection model, each term should only be included if the term's dot product is positive. (Additionally, the specular term should only be included if the dot product of the diffuse term is positive.)"

This quantity: P.IL.R*((M.kd.RLN) + (M.ks.RPower(Max(VR,0),M.Ns))) Should be multiplied by a factor B. Where B is one is dot(L * N) > 0, and 0 otherwise. This is because if dot(L*N) < 0, then the light is shining below the other side of the surface and we don't want to count that.

ciel712
  • 46
  • 3
  • Ok, I didn't post the part of the code that does the Second comment you pointed. Sorry about that. Though I am still confused about the number of lights. If I keep adding new lights it would have to keep becoming each time brighter. But if I have one very bright light, wouldn't the effect be the same? – André Castanho Aug 27 '16 at 10:31
  • But about the way I handle the colors, is there something ackward? – André Castanho Aug 27 '16 at 10:38
  • Is there something about your results that indicate to you the color is off? You should not be normalizing the colors either, instead of Round(...) you should do Clamp(Result.R, 0, 255). The ambient, specular, and diffuse should each be able to have the range 0-1 on their own. You are saying they have range 0-0.333. So that means if I don't have specular or ambient, I can never have a white pixel just based on diffuse. – ciel712 Aug 28 '16 at 07:55
  • Sorry if I explain it strangely. Let me put it simply. Pretend each light has diffuse contribution of 1. So ten lights = 10 * 1 = 10. But this is outside our range. So it should be 1. Doing (10 * 1) / 10 = 1 to restrict the value to this maximum is wrong in certain scenarios. Because what if we have ten lights, but only one is turned on? Then 9 * 0 + 1 * 1 = 1 should be our result. But if you did (9 * 0 + 1 * 1) / 10 = 0.1 then it is too dark. – ciel712 Aug 28 '16 at 08:10
  • I will check if I verify the lights to be turned on or not, before dividing. But, letting out this part of many lights, when I divide by 3 I consider each parcel, like Ia*ka, have the range 0-1. So it would not be 0-0.333 – André Castanho Aug 28 '16 at 12:26
  • Result.R is already clamped between 0-3. I don't use the function clamp, but I make sure is at most 3, and that each parcel is at most 1. Then is normalized to 0-255. – André Castanho Aug 28 '16 at 12:49
  • The point is not whether they are on or not, they could be 0.5. The point is if you divide the number by the number of lights it will always be too dark. This is why you need to clamp instead of dividing. The same issue is with the color. Each "parcel" you call it, is too dark because you divide it by 3. If you are always dividing the range 0-1 by 3, it becomes 0-0.333. Each of the ambient, specular and diffuse will be 1/3 the brightness it should be. This is why you need to clamp instead of normalize. – ciel712 Aug 29 '16 at 18:16
  • Also to be clear you only need to clamp once, at the very end. In the middle, all your calculations to make it easier could be done in floating point to avoid overflow. Then clamp between 0 and 1 and convert to byte before displaying. – ciel712 Aug 29 '16 at 18:18
  • Here's another example: Each light has diffuse contribution of 0.75. So if you have 10 lights, 10 * 0.75 = 7.5. We cannot display 7.5, so we display 1 instead. If you did the math as division, you'd get (10 * 0.75) / 10 = 0.75 instead of 1. The correct way is to do Clamp(10 * 0.75, 0, 1) = 1. – ciel712 Aug 29 '16 at 18:21
  • I will test that. But it's a strange concept for me. I thought the sum would result in a number like a % of the range 255. – André Castanho Aug 29 '16 at 21:10