Jump to content


Materials and light transport


61 replies to this topic

#1 Alienizer

    Member

  • Members
  • PipPipPipPip
  • 435 posts

Posted 06 April 2012 - 03:39 AM

I've read many things all different, and kind of confusing. When a light hit a surface, it is either reflected in part or in whole, or absorbed, to preserve and distibute the light energy without adding or removing from it (conservasion of energy), but is the following correct and true?... if frand(0..1) < material.color.max(0..1) then reflect else absorb, and if reflect, then the reflected.light = incoming.light * material.color?

#2 Reedbeta

    DevMaster Staff

  • Administrators
  • 5308 posts
  • LocationSanta Clara, CA

Posted 06 April 2012 - 04:00 AM

The part that's not reflected is absorbed. (Or, in the case of a transparent surface, the part that's not reflected is transmitted.)

So if you calculate reflected light = incoming * material color, then that's the reflected light, period. No need to do any randomization type of stuff.

This tends to create photons with a wide distribution of values. Some photons are directly from a light source and will be very bright while others have been bounced a few times and are dim. This is not wrong - you'll still get a correct rendering result - but my understanding is that the trouble with this is it tends to worsen the noise. You'll need more photons and/or more rendering time to get a high-quality image.

So in photon mapping, people often take some steps to try to keep all the photons at about the same power. One way to do this is, instead of multiplying each photon by the material color when it gets reflected, you randomly either absorb the photon or reflect it. If you forget about colors and think about monochrome rendering for a minute, you can see that if you have a surface that reflects 20% of the light, that it's equivalent to either reflect all the photons and multiply each one's power by 0.2, or reflect only 20% of the photons but keep the same power (the rest are absorbed, i.e. thrown away).

In full-color rendering you have three different color channels (or more) but you can only pick one probability to reflect the photon, so people usually pick the max of the three colors or the average of them. Then you have to multiply the photon by material color divided by whatever probability you used. That ensures the photon gets colored properly, but the amount of reflected light is correct overall.
reedbeta.com - developer blog, OpenGL demos, and other projects

#3 Alienizer

    Member

  • Members
  • PipPipPipPip
  • 435 posts

Posted 06 April 2012 - 01:46 PM

View PostReedbeta, on 06 April 2012 - 04:00 AM, said:

Then you have to multiply the photon by material color divided by whatever probability you used

What do you mean by "divided by whatever probability you used"?

#4 Reedbeta

    DevMaster Staff

  • Administrators
  • 5308 posts
  • LocationSanta Clara, CA

Posted 06 April 2012 - 05:15 PM

Um - the arithmetic operation of division. :) photon power * material color / probability.
reedbeta.com - developer blog, OpenGL demos, and other projects

#5 Alienizer

    Member

  • Members
  • PipPipPipPip
  • 435 posts

Posted 06 April 2012 - 06:16 PM

:lol: Yes, but what probability? I mean, if I absorb it when frand(0..1) > color.max, and bounce it when not, isn't that probability of it's own?

#6 Reedbeta

    DevMaster Staff

  • Administrators
  • 5308 posts
  • LocationSanta Clara, CA

Posted 06 April 2012 - 07:26 PM

I'm talking about the probability you'd use to choose whether to reflect it. As in "you can only pick one probability to reflect the photon, so people usually pick the max of the three colors or the average of them. Then you have to multiply the photon by material color divided by whatever probability you used".
reedbeta.com - developer blog, OpenGL demos, and other projects

#7 Alienizer

    Member

  • Members
  • PipPipPipPip
  • 435 posts

Posted 06 April 2012 - 07:40 PM

ok, so if I have a probability of frand(0..1) say 0.8 and 0.8 > color.max then the reflectedColor = color * material / 0.8 ?

#8 Reedbeta

    DevMaster Staff

  • Administrators
  • 5308 posts
  • LocationSanta Clara, CA

Posted 06 April 2012 - 08:07 PM

If you meant "reflect if frand(0, 1) < 0.8", then yes.
reedbeta.com - developer blog, OpenGL demos, and other projects

#9 Alienizer

    Member

  • Members
  • PipPipPipPip
  • 435 posts

Posted 06 April 2012 - 09:22 PM

oh! do you mean that 0.8 is the reflection factor? In this case, 80% as in a slightly smoked mirror? If not, then I'm still confused! I thought that color.max is used with frand to know if it is to be reflected or not!

#10 Reedbeta

    DevMaster Staff

  • Administrators
  • 5308 posts
  • LocationSanta Clara, CA

Posted 06 April 2012 - 09:48 PM

The material color is the reflection factor; they're the same thing. A material looks like a certain color because it reflects different fractions of R, G, and B light.

But you don't have separate R, G, and B photons (well, you could, but this isn't the way it's typically done); you just have a photon, and you must decide whether to reflect or absorb it. You must somehow condense three numbers, the RGB material color, down to one number, the probability for reflecting or absorbing.

A reasonable way to do this is to choose the max of the RGB components (although personally I would probably choose the weighted average by eye sensitivies to R, G, and B, rather than the max).

But when you reflect the photon it must pick up the material color. So you multiply the photon color by the material color. But now you've incorporated the material color twice - once to calculate the probability to reflect a photon, and once to modify the photon color. That's wrong, so you must compensate. You can do this by dividing the photon color by the probability. That way the photons still pick up the material color but the total amount of reflected light is correct.

In other words, you're splitting the material color into an overall intensity - which tells you the probability to reflect a photon - and the actual color part, which tells you how to change the color of a photon when it reflects. These two when multiplied together must give the original material color, so it follows that the "color part" = material color / probability.
reedbeta.com - developer blog, OpenGL demos, and other projects

#11 Alienizer

    Member

  • Members
  • PipPipPipPip
  • 435 posts

Posted 06 April 2012 - 10:09 PM

ok, that make sense. So I have a function...

float Luminance(const vec3 clr) {
return 0.212671f * clr.r + 0.71516f * clr.g + 0.072169f * clr.b;
}

So the probability of reflection is...

bool p = frand(0..1) < Luminance(materialColor);

if (p) {
reflectedColor = photon * materialColor / Luminance(materialColor);
}

Is that right?

#12 Reedbeta

    DevMaster Staff

  • Administrators
  • 5308 posts
  • LocationSanta Clara, CA

Posted 07 April 2012 - 12:40 AM

Yep, that looks right.
reedbeta.com - developer blog, OpenGL demos, and other projects

#13 Alienizer

    Member

  • Members
  • PipPipPipPip
  • 435 posts

Posted 07 April 2012 - 01:05 AM

Looking on the net for renders of the Cornell box (red and blue walls), I don't see any with strong color bleeding. Is that correct? I mean, if I were to paint my bedroom with a red and blue walls and turn on the light, wouldn't the white walls appear much more red and blue from what we see in renders? Maybe I got to try that :lol:

#14 Reedbeta

    DevMaster Staff

  • Administrators
  • 5308 posts
  • LocationSanta Clara, CA

Posted 07 April 2012 - 02:23 AM

Color bleeding is kinda the whole point of the Cornell box. :) But color bleeding isn't always very strong; it depends on how saturated and intense the colors are.
reedbeta.com - developer blog, OpenGL demos, and other projects

#15 Alienizer

    Member

  • Members
  • PipPipPipPip
  • 435 posts

Posted 07 April 2012 - 02:28 AM

True! But have you ever seen a photo of a room painted (red/blue) just like the Cornell box to see how the colors are bleeding? Ik now they have a small model they made. but it's not red/blue, and it's a model, not a real big room like a bedroom or bigger.

#16 Reedbeta

    DevMaster Staff

  • Administrators
  • 5308 posts
  • LocationSanta Clara, CA

Posted 07 April 2012 - 02:31 AM

No, I haven't seen such a photo. But the size doesn't matter as long as everything is to scale, including the light source. And the colors don't matter either as long as the side walls are two different colors.
reedbeta.com - developer blog, OpenGL demos, and other projects

#17 Alienizer

    Member

  • Members
  • PipPipPipPip
  • 435 posts

Posted 07 April 2012 - 02:46 AM

ok, thanks Reedbeta. But let me bug you some more :wub:

I've been trying to make my lights nice and I have a hard time. What I mean is, take the Cornell box for example, the light on the ceiling is square. When I render that, the light is not anti-aliased because it is so bright. So what I did is store the photon comming out of the light right where it leaves the light. Looks ok on large lights, but again, no anti-alias on small lights because the area is so small and packed with photons. So I dumped that and instead I read the light color at trace time, but the light is almost black! So I don't know how to handle this, and for glass for example, I like to have the light shinning on them, but it's eather very faint or too bright that it looks stupid! Any idea? you are the genius :)

#18 Reedbeta

    DevMaster Staff

  • Administrators
  • 5308 posts
  • LocationSanta Clara, CA

Posted 07 April 2012 - 03:25 AM

I'm not sure I understand what the problem is. Of course, if you are raytracing and you hit a light source, it should return the color of the light. The light should get antialiased the same way everything else does, i.e. by shooting more rays per pixel. I didn't get what you were trying to do with storing the emitted photons at the light - that doesn't make sense because the photon map represents incoming light at a surface, not outgoing (reflected or emitted) light.

One thing to check is that the total photon power is scaled correctly. If you set the radiance of the light - that is, the color that rays return when they hit it - then you can calculate the total power as light color * pi * the area of the light's geometry. (The pi is to convert from radiance to irradiance, i.e. it's the integral of cos(theta) over the hemisphere.) This total power should equal the total power of all photons emitted from that light.
reedbeta.com - developer blog, OpenGL demos, and other projects

#19 Alienizer

    Member

  • Members
  • PipPipPipPip
  • 435 posts

Posted 07 April 2012 - 04:49 AM

I was trying something new but like you said, it makes no sense. So I did whaty you said, and it works perfect for one light only. But when I have more than one light, each with different power and size, they come out dark gray!?

#20 Reedbeta

    DevMaster Staff

  • Administrators
  • 5308 posts
  • LocationSanta Clara, CA

Posted 07 April 2012 - 05:32 AM

When you have multiple light sources, are you keeping the photon power scaled correctly, so the total power of all the photons emitted from each light equals light color * pi * area of that light? You'll have to increase the number of photons when you add more lights, or else increase the power on each photon, if you keep the same total number of photons.
reedbeta.com - developer blog, OpenGL demos, and other projects





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users