floze
11-14-2005, 12:26 AM
Ok, here's another wannabe-exploit thread. This time about the physical_light shader, coming with the base mentalray for maya installation.
I know many people are using the physical_light. Usually they use it with the intention, well, to obtain physical correct renderings. I'm sure most of them dont know that sometimes they put the fox in charge of the henhouse this way. Why this?
First, physical_light does cause problems when used together with maya standard shaders, like maya blinn for example. Here's a rendering with raytracing set to on, the material is the default maya lambert, the light is a physical_light with intensity 200000 attached to a maya pointlight:
http://individual.floze.de/fileadmin/files/cgtalk/physical_light/raytraced.jpg
Looks good so far, but what happens when raytracing is turned off? Here's an example:
http://individual.floze.de/fileadmin/files/cgtalk/physical_light/noraytrace.jpg
What's that illuminated rim around the lower right of our sphere? Looks like physical_light shades both sides of our object, regardless where the normal is pointing at. Hm, let's see if the problem persists if we use mentalray shaders instead of the maya lambert:
http://individual.floze.de/fileadmin/files/cgtalk/physical_light/noraytrace_mrLambert.jpg
Apparently it renders correct. So, if you plan to use native maya shaders instead of custom mentalray shaders, physical_light might cause problems. What I came across for example, is that extremely bright finalgathering blotches (blotches that are not caused by insufficient rays) were caused by this fact.
Second, physical_light lacks of almost every neat feature the maya lights have: raytrace shadow attributes like light radius, amount of shadow rays, shadow ray depht limit, shadow color, light fog, light glow, intensity curve, barn doors (if you ever use it..), decay regions, and last but not least the capability to emit diffuse or specular only.
With this in mind, I went out to find a 'substitute' for the physical_light. To anticipate but hopefully not to lower the suspense (heh) I can say that this has been succesfully accomplished by exactly 75%.
Foremost we need to know what the key-features of physical_light are: It is a) the decay, following physical light's inverse-square falloff law. And more important b) it works perfectly together with the ligth's photon emission attributes, creating a physically plausible correlation between direct and indirect illumination.
To maintain this correlation, we need to find an exact conversion factor for the light's intensity. Well, if you ever tried to approximate a maya light's intensity to a physical_light one's, you probably came up with the factor 12.5, +-0.1 maybe. Hmm, why this? The physical_light's source code gives the answer: at line 109 it states switch(areatype) {
case miLIGHT_NONE: /* point, spot or directional*/
/*
* distance attenuation: 4 Pi r^2 is the area of a
* sphere around the point. Same normalization as for
* spherical light
*/
f = type==miLIGHT_DIRECTION ? 1 : 1 / (4 * M_PI * r2);
break;
..which means, the formula for distance attenuation (for point, spot and directional lights) is 1 divided by 4*pi, multiplied by the radius^2, or 1/(4*3.14159*radius^2). Now, if we use a maya light, the radius^2 thingy is handled by simply switching the decay rate attribute to quadratic. The 4*pi needs to be handled manually though. So, if our physical light had an intensity of 200000.000, we need to switch our maya pendant to a quadratic decay rate, and we need to divide the intensity by 4*pi - let's have a look, the maya light's intensity is 15915.494 now:
http://individual.floze.de/fileadmin/files/cgtalk/physical_light/raytraced_mayalight.jpg
Ugh! Exact same result!
This also clarifies why most people tend to set their photon intensity to 10 times their direct light intensity when using maya lights with quadratic decay. Well, now they know that they actually should either divide the direct light intensity by 4*pi (=~12.566), or multiply the photon intensity by 4*pi. This way, physical_light can safely be 'emulated' in case of point, spot or directional lights.
Conclusion:
maya light intensity = physical_light intensity / 4*pi (=~12.566)
But what about (flat) area lights? Well, here's a simple point light, with physical_light attached (intensity 10000.000) and mentalray area light set to true, type rectangle - it's sampling is set to 1/1 and the number of antialiasing samples is min/max 1/1 to avoid irregular noise for our test:
http://individual.floze.de/fileadmin/files/cgtalk/physical_light/areaRect.jpg
Let's try to apply what we learned above. Physical_light detached, intensity divided by 4*pi, decay rate quadratic:
http://individual.floze.de/fileadmin/files/cgtalk/physical_light/areaRect_mayaPoint_4pi.jpg
Hmm, that didnt work out. Let's have a look at the physical_light's source code again: case miLIGHT_RECTANGLE: /* rectangular area light */
mi_query(miQ_LIGHT_AREA_R_EDGE_U, state, light, &u);
mi_query(miQ_LIGHT_AREA_R_EDGE_V, state, light, &v);
mi_vector_prod(&normal, &u, &v);
mi_vector_normalize(&normal);
mi_vector_to_light(state, &dir, &state->dir);
mi_vector_normalize(&dir);
/*
* Compute area-to-point form factor (except cos at
* the receiver). <cosine> is cos at sender. Returning
* 2 means "no color and stop sampling".
*/
cosine = mi_vector_dot(&normal, &dir);
if (cosine <= 0)
return((miBoolean)2);
if (paras->cos_exp != 0 && paras->cos_exp != 1)
cosine = pow(cosine, paras->cos_exp);
/*
* cos term and distance attenuation. No area term
* since "color" of the light is energy, not radiance.
*/
f = cosine / (M_PI * r2);
break;
As you can see, in the line next to the last, pi only is used. So let's try that - intensity divided by pi only (10000/pi = 3183.099):
http://individual.floze.de/fileadmin/files/cgtalk/physical_light/areaRect_mayaPoint_1pi.jpg
Better, but there's still a big difference for some reason..? Well, it has to do with the cosine_exponent attribute of the physical_light. The cosine_exponent is narrowing the light's default cosine distribution by taking cosine to cos_exp's power - so if we use a physical_light again and set cosine_exponent to 0 it should be equal to what we just rendered with the maya light:
http://individual.floze.de/fileadmin/files/cgtalk/physical_light/areaRect_cos0.jpg
Same result! Sweet! But didnt we want to emulate a physical_light with maya lights, not vice versa? So how can we simulate this cosine_exponent? I had to experiment, and found out that a maya spot light's dropoff attribute has the very same effect - only drawback is that you need to max the spot light's cone angle (~179.994°) - this can get a bit annoying, because the displayed cone get's incredibly huge and we cannot scale it down, since the area light reads the same scale as well and would get scaled down too. So I switched my maya light to type spot light with cone angle 179.994, penumbra 0 and dropoff 1 - intensity again is physical_light's intensity/1pi (and dont forget to switch decay rate to quadratic again, as it gets switched to 'No Decay' when switching light type):
http://individual.floze.de/fileadmin/files/cgtalk/physical_light/areaRect_mayaSpot.jpg
It's the exact same result as with physical_light.
Conclusion:
For rectangle and disc area lights:
maya light intensity = physical_light intensity / 1pi (=~3.142)
maya spot light's dropoff (with cone angle maxed) = physical_light's cosine_exponent
For sphere, cylindrical and geometric area lights:
maya light intensity = physical_light intensity / 4*pi (=~12.566)
note: cosine_exponent does apply to flat area lights only
Well, this perfectly emulates physical_light's intensity and cosine_exponent. But what about the cone attribute? The cone attribute simply represents (out of the manual) 'the cosine of the opening angle of the inner solid cone'. With maya lights this can easily be imitated by using a negative penumbra angle (a positive penumbra would make the cone angle actually wider).
So what's left is the threshold attribute of the physical_light. That's why my success goes as far as exactly 75% (4 attributes to be 'emulated', 1 failed, makes a loss of success of 25%, heh). The threshold attribute sometimes helps to effectively reduce the amount of shadow rays when using finalgathering. It's kinda useless though when used solely with direct lighting. However, this optimization cannot be achieved by a standard maya light - maybe in future?
With the above correlations in mind, you hopefully better understand the interplay of direct and indirect (photon) intensity and you can get physically plausible solutions without abandoning maya's native lights and material shaders.
I hope you enjoyed another experiment that maybe lets you get a bit more out of mentalray than usual.
I know many people are using the physical_light. Usually they use it with the intention, well, to obtain physical correct renderings. I'm sure most of them dont know that sometimes they put the fox in charge of the henhouse this way. Why this?
First, physical_light does cause problems when used together with maya standard shaders, like maya blinn for example. Here's a rendering with raytracing set to on, the material is the default maya lambert, the light is a physical_light with intensity 200000 attached to a maya pointlight:
http://individual.floze.de/fileadmin/files/cgtalk/physical_light/raytraced.jpg
Looks good so far, but what happens when raytracing is turned off? Here's an example:
http://individual.floze.de/fileadmin/files/cgtalk/physical_light/noraytrace.jpg
What's that illuminated rim around the lower right of our sphere? Looks like physical_light shades both sides of our object, regardless where the normal is pointing at. Hm, let's see if the problem persists if we use mentalray shaders instead of the maya lambert:
http://individual.floze.de/fileadmin/files/cgtalk/physical_light/noraytrace_mrLambert.jpg
Apparently it renders correct. So, if you plan to use native maya shaders instead of custom mentalray shaders, physical_light might cause problems. What I came across for example, is that extremely bright finalgathering blotches (blotches that are not caused by insufficient rays) were caused by this fact.
Second, physical_light lacks of almost every neat feature the maya lights have: raytrace shadow attributes like light radius, amount of shadow rays, shadow ray depht limit, shadow color, light fog, light glow, intensity curve, barn doors (if you ever use it..), decay regions, and last but not least the capability to emit diffuse or specular only.
With this in mind, I went out to find a 'substitute' for the physical_light. To anticipate but hopefully not to lower the suspense (heh) I can say that this has been succesfully accomplished by exactly 75%.
Foremost we need to know what the key-features of physical_light are: It is a) the decay, following physical light's inverse-square falloff law. And more important b) it works perfectly together with the ligth's photon emission attributes, creating a physically plausible correlation between direct and indirect illumination.
To maintain this correlation, we need to find an exact conversion factor for the light's intensity. Well, if you ever tried to approximate a maya light's intensity to a physical_light one's, you probably came up with the factor 12.5, +-0.1 maybe. Hmm, why this? The physical_light's source code gives the answer: at line 109 it states switch(areatype) {
case miLIGHT_NONE: /* point, spot or directional*/
/*
* distance attenuation: 4 Pi r^2 is the area of a
* sphere around the point. Same normalization as for
* spherical light
*/
f = type==miLIGHT_DIRECTION ? 1 : 1 / (4 * M_PI * r2);
break;
..which means, the formula for distance attenuation (for point, spot and directional lights) is 1 divided by 4*pi, multiplied by the radius^2, or 1/(4*3.14159*radius^2). Now, if we use a maya light, the radius^2 thingy is handled by simply switching the decay rate attribute to quadratic. The 4*pi needs to be handled manually though. So, if our physical light had an intensity of 200000.000, we need to switch our maya pendant to a quadratic decay rate, and we need to divide the intensity by 4*pi - let's have a look, the maya light's intensity is 15915.494 now:
http://individual.floze.de/fileadmin/files/cgtalk/physical_light/raytraced_mayalight.jpg
Ugh! Exact same result!
This also clarifies why most people tend to set their photon intensity to 10 times their direct light intensity when using maya lights with quadratic decay. Well, now they know that they actually should either divide the direct light intensity by 4*pi (=~12.566), or multiply the photon intensity by 4*pi. This way, physical_light can safely be 'emulated' in case of point, spot or directional lights.
Conclusion:
maya light intensity = physical_light intensity / 4*pi (=~12.566)
But what about (flat) area lights? Well, here's a simple point light, with physical_light attached (intensity 10000.000) and mentalray area light set to true, type rectangle - it's sampling is set to 1/1 and the number of antialiasing samples is min/max 1/1 to avoid irregular noise for our test:
http://individual.floze.de/fileadmin/files/cgtalk/physical_light/areaRect.jpg
Let's try to apply what we learned above. Physical_light detached, intensity divided by 4*pi, decay rate quadratic:
http://individual.floze.de/fileadmin/files/cgtalk/physical_light/areaRect_mayaPoint_4pi.jpg
Hmm, that didnt work out. Let's have a look at the physical_light's source code again: case miLIGHT_RECTANGLE: /* rectangular area light */
mi_query(miQ_LIGHT_AREA_R_EDGE_U, state, light, &u);
mi_query(miQ_LIGHT_AREA_R_EDGE_V, state, light, &v);
mi_vector_prod(&normal, &u, &v);
mi_vector_normalize(&normal);
mi_vector_to_light(state, &dir, &state->dir);
mi_vector_normalize(&dir);
/*
* Compute area-to-point form factor (except cos at
* the receiver). <cosine> is cos at sender. Returning
* 2 means "no color and stop sampling".
*/
cosine = mi_vector_dot(&normal, &dir);
if (cosine <= 0)
return((miBoolean)2);
if (paras->cos_exp != 0 && paras->cos_exp != 1)
cosine = pow(cosine, paras->cos_exp);
/*
* cos term and distance attenuation. No area term
* since "color" of the light is energy, not radiance.
*/
f = cosine / (M_PI * r2);
break;
As you can see, in the line next to the last, pi only is used. So let's try that - intensity divided by pi only (10000/pi = 3183.099):
http://individual.floze.de/fileadmin/files/cgtalk/physical_light/areaRect_mayaPoint_1pi.jpg
Better, but there's still a big difference for some reason..? Well, it has to do with the cosine_exponent attribute of the physical_light. The cosine_exponent is narrowing the light's default cosine distribution by taking cosine to cos_exp's power - so if we use a physical_light again and set cosine_exponent to 0 it should be equal to what we just rendered with the maya light:
http://individual.floze.de/fileadmin/files/cgtalk/physical_light/areaRect_cos0.jpg
Same result! Sweet! But didnt we want to emulate a physical_light with maya lights, not vice versa? So how can we simulate this cosine_exponent? I had to experiment, and found out that a maya spot light's dropoff attribute has the very same effect - only drawback is that you need to max the spot light's cone angle (~179.994°) - this can get a bit annoying, because the displayed cone get's incredibly huge and we cannot scale it down, since the area light reads the same scale as well and would get scaled down too. So I switched my maya light to type spot light with cone angle 179.994, penumbra 0 and dropoff 1 - intensity again is physical_light's intensity/1pi (and dont forget to switch decay rate to quadratic again, as it gets switched to 'No Decay' when switching light type):
http://individual.floze.de/fileadmin/files/cgtalk/physical_light/areaRect_mayaSpot.jpg
It's the exact same result as with physical_light.
Conclusion:
For rectangle and disc area lights:
maya light intensity = physical_light intensity / 1pi (=~3.142)
maya spot light's dropoff (with cone angle maxed) = physical_light's cosine_exponent
For sphere, cylindrical and geometric area lights:
maya light intensity = physical_light intensity / 4*pi (=~12.566)
note: cosine_exponent does apply to flat area lights only
Well, this perfectly emulates physical_light's intensity and cosine_exponent. But what about the cone attribute? The cone attribute simply represents (out of the manual) 'the cosine of the opening angle of the inner solid cone'. With maya lights this can easily be imitated by using a negative penumbra angle (a positive penumbra would make the cone angle actually wider).
So what's left is the threshold attribute of the physical_light. That's why my success goes as far as exactly 75% (4 attributes to be 'emulated', 1 failed, makes a loss of success of 25%, heh). The threshold attribute sometimes helps to effectively reduce the amount of shadow rays when using finalgathering. It's kinda useless though when used solely with direct lighting. However, this optimization cannot be achieved by a standard maya light - maybe in future?
With the above correlations in mind, you hopefully better understand the interplay of direct and indirect (photon) intensity and you can get physically plausible solutions without abandoning maya's native lights and material shaders.
I hope you enjoyed another experiment that maybe lets you get a bit more out of mentalray than usual.
