Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to blend colors

Tags:

raytracing

I'm currently coding a raytracer. I wonder how to blend a primitive color with a light color. I've seen many combinations.

Some just add the two colors. This gives me very strange results.

Some mutiply each components. It looks ok, but in the primitive is blue ({0, 0, 1}) and the light is red ({1, 0, 0}), it is just black. Is it the normal behavior ?

I've also seen the screen blending mode (screen(C1, C2) = C1 + C2 - C1 * C2)) which is more logical for me since in the above case, colors will actually blend.

Same question for reflected rays colors : how to blend them with the local color ?

Bonus question: should a point on a primitive that it not illuminated be black ? I've seen stuff like "the half of the color".

like image 328
Tangui Avatar asked Nov 09 '10 11:11

Tangui


1 Answers

It's actually way more complicated. The light and surface material interact via a formula called a bidirectional reflectance distribution function (BRDF, for short), a 4-dimensional function whose inputs are the direction of the light and direction of the viewing angle (both relative to the surface normal, i.e. the unit vector perpendicular to the surface), and whose output is the ratio of the outgoing radiance in the view direction to the incoming irradiance from the light's direction.

There's not an easy way to explain it in this short space. Perhaps you could check out the Wikipedia article, as well as its links and references, or even crack open a decent computer graphics textbook?

But suffice it to say that for many BRDF's, it is akin to "multiplication", in that a perfectly reflective Lambertian pure red surface illuminated by a perfectly blue light ought to look black.

There are several complicating factors: No real light, other than a laser, emits a pure primary color with the other components being 0.0. (Avoid this if you want a realistic image.) No real surface reflects all in one wavelength with the other color components being 0.0. (Avoid this if you want a realistic image.) And no material is really quite lambertian (purely diffuse) -- generally there is some specular component that tends to reflect light at the surface, before they get to any underlying pigment, and therefore that portion of the reflected light will tend to look like the color of the light, not the surface. Unless it's metallic, in which case the "color" of the metal does influence the specular. Sigh. Like I said, it's complicated, and you need to actually read up on the physics (as well as the 40 years of computer graphics research in which all these problems have been solved long before you ever contemplated the problem).

Bonus answer ("what happens to a point that is not illuminated"): points truly not illuminated should be black. But surely you knew that, as well as the fact that in any real-world situation, there isn't any point that gets no illumination (and can also be photographed). A more interesting formulation of the question goes like this: my renderers is only considering direct light paths from sources, not all the indirect paths (object to object) that illuminate the darker corners, so how do I prevent it from going black? A cheap answer is to add an "ambient" light that just throws a constant amount of light everywhere. This is what people did for a long time, and it looked quite fake as you would imagine. A better approach is to use various "global illumination" techniques. Look it up. But definitely don't just "illuminate it half as much," unless you're aiming for a very stylistic (as opposed to realistic) appearance.

like image 121
Larry Gritz Avatar answered Oct 15 '22 16:10

Larry Gritz