Reference:Radiosity
Radiosity Basics
Radiosity is an extra calculation that more realistically computes the diffuse inter-reflection of light. This diffuse inter-reflection can be seen if you place a white chair in a room full of blue carpet, blue walls and blue curtains. The chair will pick up a blue tint from light reflecting off of other parts of the room. Also notice that the shadowed areas of your surroundings are not totally dark even if no light source shines directly on the surface. Diffuse light reflecting off of other objects fills in the shadows. Typically ray-tracing uses a trick called ambient light to simulate such effects but it is not very accurate.
Radiosity calculations are only made when a radiosity{}
block is used inside the global_settings{}
block.
The following sections describes how radiosity works, how to control it with various global settings and tips on trading quality vs. speed.
How Radiosity Works
The problem of ray-tracing is to figure out what the light level is at each point that you can see in a scene. Traditionally, in ray tracing, this is broken into the sum of these components:
- Diffuse
- the effect that makes the side of things facing the light brighter;
- Specular
- the effect that makes shiny things have dings or sparkles on them;
- Reflection
- the effect that mirrors give; and
- Ambient
- the general all-over light level that any scene has, which keeps things in shadow from being pure black.
POV-Ray's radiosity system, based on a method by Greg Ward, provides a way to replace the last term - the constant ambient light value - with a light level which is based on what surfaces are nearby and how bright in turn they are.
The first thing you might notice about this definition is that it is circular: the brightness and color of everything is dependent on everything else and vice versa. This is true in real life but in the world of ray-tracing, we can make an approximation. The approximation that is used is: the objects you are looking at have their ambient
values calculated for you by
checking the other objects nearby. When those objects are checked during this process, however, their diffuse
term is used. The brightness of radiosity in POV-Ray is based on two things:
- the amount of light gathered
- the diffuse property of the surface finish
Note: The following is an important behavior change!
Previously an object could have both radiosity and an ambient term. This is no longer the case, as when radiosity is used an objects ambient term is effectively set to zero. See the emission
keyword that has been added to the finish
block if the intent is to model a glowing object.
How does POV-Ray calculate the ambient term for each point? By sending out more rays, in many different directions, and averaging the results. A typical point might use 200 or more rays to calculate its ambient light level correctly.
Now this sounds like it would make the ray-tracer 200 times slower. This is true, except that the software takes advantage of the fact that ambient light levels change quite slowly (remember, shadows are calculated separately, so sharp shadow edges are not a problem). Therefore, these extra rays are sent out only once in a while (about 1 time in 50), then these calculated values are saved and reused for nearby pixels in the image when possible.
This process of saving and reusing values is what causes the need for a variety of tuning parameters, so you can get the scene to look just the way you want.
Adjusting Radiosity
As described earlier, radiosity is turned on by using the radiosity{}
block in global_setting
.
Radiosity has many parameters that are specified as follows:
global_settings { radiosity { [RADIOSITY_ITEMS...] } } RADIOSITY_ITEMS: adc_bailout Float | always_sample Bool | brightness Float | count Integer [,Integer] | error_bound Float | gray_threshold Float | low_error_factor Float | max_sample Float | media Bool | maximum_reuse Float | minimum_reuse Float | nearest_count Integer [,Integer] | normal Bool | pretrace_start Float | pretrace_end Float | recursion_limit Integer | subsurface Bool | brilliance Bool
Each item is optional and may appear in any order. If an item is specified more than once the last setting overrides previous values. Details on each item is given in the following sections.
Note: Considerable changes have been made to the way radiosity works in POV-Ray v3.7
compared to previous versions. Old scenes will not render with exactly the same results. It is not possible to use the #version
directive to get backward compatibility for radiosity.
adc_bailout
You can specify an adc_bailout for radiosity rays. Usually the default of 0.01 will give good results, but for scenes with bright emissive objects it should be set to adc_bailout = 0.01 / brightest_emissive_object
.
always_sample
Since always_sample off
is the default, POV-Ray will only use the data from the pretrace step and not gather any new samples during the final radiosity pass. This produces higher quality results, and quicker renders. It may also reduce the splotchy appearance of the radiosity samples, and can be very useful when reusing previously saved radiosity data. If you find the need to override the behavior, you can do so by specifying always_sample on
.
brightness
The brightness
keyword specifies a float value that is the degree to which objects are brightened before being returned upwards to the rest of the system. Ideally brightness should be set to the default value of 1.0. If the overall brightness doesn't seem to fit, the diffuse color of objects and/or the overall brightness of light sources (including emission > 0 objects) should be adjusted.
As an example, a typical problem encountered in radiosity scenes is, when setting pigment {rgb 1}
and diffuse 1.0
, then tweaking the light source(s) and ambient_light
setting to make the image look right. It just doesn't work properly in radiosity scenes, as it will give too strong inter-reflections. While you can compensate for this by reducing radiosity brightness, it's generally discouraged. In this case the surface properties should be fixed (e.g. diffuse set to something around 0.7, which is much more realistic).
An exception, calling for the adjustment of radiosity brightness, would be to compensate for a low recursion_limit
setting (e.g recursion_limit 1
). In such a case, increasing brightness
will help maintain a realistic overall brightness.
count
The integer number of rays that are sent out whenever a new radiosity value has to be calculated is given by count
. The default value is 35, if the value exceeds 1600, POV-Ray will use a Halton sequence instead of the default built-in sequence. When this value is too low, the light level will tend to look a little bit blotchy, as if the surfaces you are looking at were slightly warped. If this is not important to your scene (as in the case that you have a bump map or if you have a strong texture) then by all means use a lower number.
By default, POV-Ray uses the same set of directions for each new radiosity value to calculate. In order to cover more directions in total without increasing the number of rays to trace, count
accepts an optional second parameter which specifies the total number of directions from which to choose. POV-Ray will then draw directions from this pool in a round-robin fashion.
error_bound
The error_bound
float value is one of the two main speed/quality tuning values (the other is of course the number of rays shot). In an ideal world, this would be the only value needed. It is intended to mean the fraction of error tolerated. For example, if it were set to 1 the algorithm would not calculate a new value until the error on the last one was estimated at as high as 100%. Ignoring the error introduced by rotation for the moment, on flat surfaces this is equal to the fraction of the reuse distance, which in turn is the distance to the closest item hit. If you have an old sample on the floor 10 inches from a wall, an error bound of 0.5 will get you a new sample at a distance of about 5 inches from the wall.
The default value of 1.8 is good for a smooth general lighting effect. Using lower values is more accurate, but it will strongly increase the danger of artifacts and therefore require higher count
. You can use values even lower than 0.1 but both render time and memory use can become extremely high.
gray_threshold
Diffusely inter-reflected light is a function of the objects around the point in question. Since this is recursively defined to millions of levels of recursion, in any real life scene, every point is illuminated at least in part by every other part of the scene. Since we cannot afford to compute this, if we only do one bounce, the calculated ambient light is very strongly affected by the colors of the objects near it. This is known as color bleed and it really happens but not as much as this calculation method would have you believe. The gray_threshold
float value grays it down a little, to make your scene more believable. A value of .6 means to calculate the ambient value as 60% of the equivalent gray value calculated, plus 40% of the actual value calculated. At 0%, this feature does nothing. At 100%, you always get white/gray ambient light, with no hue.
Note: This does not change the lightness/darkness, only the strength of hue/grayness (in HLS terms, it changes S only). The default value is 0.0
low_error_factor
If you calculate just enough samples, but no more, you will get an image which has slightly blotchy lighting. What you want is just a few extra interspersed, so that the blending will be nice and smooth. The solution to this is the mosaic preview, controlled by
pretrace, it goes over the image one or more times beforehand, calculating radiosity values. To ensure that you get a few extra, the radiosity algorithm lowers the error bound during the pre-final passes, then sets it back just before the final pass. The low_error_factor
is a float tuning value which sets the amount that the error bound is dropped during the preliminary image passes. If your low error factor is 0.8 and your error bound is set to 0.4 it will really use an error bound of 0.32 during the first passes and 0.4 on the final pass. The default value is 0.5.
max_sample
Sometimes there can be splotchy patches that are caused by objects that are very bright. This can be sometimes avoided by using the max_sample
keyword. max_sample
takes a float parameter which specifies the brightest that any gathered sample is allowed to be. Any samples brighter than this will have their brightness decreased (without affecting color). Note however that this mechanism will somewhat darken the overall brightness in an unrealistic way. Specifying a non-positive value for max_sample
will allow any brightness of samples (which is the default).
maximum_reuse
The maximum_reuse
parameter works in conjunction with, and is similar to that of minimum_reuse
, the only difference being that it is an upper bound rather than a lower one. The default value is 0.200.
Note: If you choose to adjust either the minimum_reuse
or maximum_reuse
settings they are subject to the criteria listed below:
- If
minimum_reuse > maximum_reuse/2
with only one value is specified, a warning is issued and the unspecified value is adjusted. - If
minimum_reuse > maximum_reuse/2
with both values specified, a warning is issued and neither value is modified. - If
minimum_reuse >= maximum_reuse
, an error is generated.
minimum_reuse
The minimum effective radius ratio is set by minimum_reuse
float value. This is the fraction of the screen width which sets the minimum radius of reuse for each sample point (actually, it is the fraction of the distance from the eye but the two are roughly equal for normal camera angles). For example, if the value is 0.02, the radius of maximum reuse for every sample is set to whatever ground distance corresponds to 2% of the width of the screen. Imagine you sent a ray off to the horizon and it hits the ground at a distance of 100 miles from your eye point. The reuse distance for that sample will be set to 2 miles. At a resolution of 300*400 this will correspond to (very roughly) 8 pixels. The theory is that you do not want to calculate values for every pixel into every crevice everywhere in the scene, it will take too long. This sets a minimum bound for the reuse. If this value is too low, (which it should be in theory) rendering gets slow, and inside corners can get a little grainy. If it is set too high, you do not get the natural darkening of illumination near inside edges, since it reuses. At values higher than 2% you start getting more just plain errors, like reusing the illumination of the open table underneath the apple. Remember that this is a unit less ratio. The default value is 0.015.
nearest_count
The nearest_count
integer value is the minimum number of old radiosity values blended together to create a new interpolated value. There is no upper limit on the number of samples blended, all available samples are blended that match the error_bound
and maximum_reuse
settings. When an optional second parameter (adaptive radiosity pretrace) is specified after the nearest_count
keyword, pretrace will stop re-iterating over areas where, on average, that many average-quality samples are already present per ray. (The actual number of samples required to satisfy the nearest_count
settings is influenced by sample quality, with high-quality samples reducing the effective number of samples required, down to 1/4 of the parameter value in extreme cases, and low-quality samples increasing the number.) With a setting lower than 4, things can get pretty patchy, this can be useful for debugging. Conversely, the nearest_count
upper limit setting is 20, since values greater than 20 are not very useful in practice, and that is currently the size of the array allocated. The default value is 5.
pretrace_start and pretrace_end
To control the radiosity pre-trace gathering step, use the keywords pretrace_start
and pretrace_end
. Each of these is followed by a decimal value between 0.0 and 1.0 which specifies the size of the blocks in the mosaic preview as a percentage of the image size. The defaults are 0.08 for pretrace_start
and 0.04 for pretrace_end
.
recursion_limit
The recursion_limit
is an integer value which determines how many recursion levels are used to calculate the diffuse inter-reflection. The default value is 2, the upper limit is 20. In practice, values greater than 3 are seldom useful.
Configuring Radiosity
The following parameters deal with configuring radiosity and how it interacts with other features. See also these additional command line options for more control.
Importance
If you have some comparatively small yet bright objects in your scene, radiosity will tend to produce bright splotchy artifacts unless you use a pretty high number of rays, which in turn will tremendously increase rendering time. To somewhat mitigate this issue, full ray computations are performed only for a certain portion of sample rays, depending on the importance of the first object each ray encounters. Importance can be assigned on a per-object basis using the following syntax:
sphere { ... radiosity { importance IMPORTANCE } }
Where IMPORTANCE is a value in the range of greater than 0.0 to less than or equal to 1.0 specifying the percentage of rays to actually compute on average. A particular ray will only be fully computed if it is within the first COUNT*IMPORTANCE rays of the sampling sequence; due to the low-discrepancy sub-random nature of the sequence, this is mostly equivalent to a per-ray weighted random choice, while maintaining a low-discrepancy uniform distribution on a per-object basis. Rays actually computed are weighted to compensate for those not computed.
Objects derived from previously defined objects will default to the inherited importance. CSG components without an explicit importance value set will default to their parent object's importance. Other objects will normally default to importance 1.0
, however this can be changed in a default{}
block:
default { radiosity { importance DEFAULT_IMPORTANCE } }
Media and Radiosity
Radiosity estimation can be affected by media. To enable this feature, add media on
to the radiosity{}
block. The default is off
No Radiosity
Specifying no_radiosity
in an object block makes that object invisible to radiosity rays, in the same way as no_image
, no_reflection
and no_shadow
make an object invisible to primary, reflected and shadow test rays, respectively.
Normal and Radiosity
Radiosity estimation can be affected by normals. To enable this feature, add normal on
to the radiosity{}
block. The default is off
Save and Load Radiosity Data
In general, it is not a good idea to save and load radiosity data if scene objects are moving. Even after the data is loaded, more samples may be taken during the final rendering phase, particularly if you've specified always_sample on
.
Note: The method to load and save radiosity data has been changed to a command line option. See section radiosity load and save for more details.
Subsurface and Radiosity
To specify whether radiosity sampling should honor subsurface light transport, you should place the following in the global settings radiosity
block:
global_settings { radiosity { subsurface BOOL } }
If this setting is off
, the default, radiosity based diffuse illumination is computed as if the surrounding objects had subsurface light transport turned off. Setting this to on
may improve realism especially in the presence of materials with high translucency, but at some cost in rendering time.
See the section Subsurface Light Transport for more information about the role of subsurface
in the global settings block.
Brilliance and Radiosity
By default, radiosity computations presume that the rendered finishes all have a brilliance setting of 1. In scenes that make heavy use of radiosity, not only may this cause surfaces to look excessively dull but most importantly it does not account for real world's diversity in their physical properties.
New as of POV-Ray v3.8, you can force radiosity to respect the brilliance finish parameter, by specifying brilliance on
in the radiosity block. #version 3.8
or higher needs to be set, and this feature does come at a cost of rendering speed, especially when combining surfaces with various different brilliance settings in
close proximity.
Tips on Radiosity
Have a look at the Radiosity Tutorial to get a feel for what the visual result of changing radiosity parameters is.
If you want to see where your values are being calculated set radiosity count
down to about 20, set radiosity nearest_count
to 1 and set gray_threshold
to 0. This will make everything maximally patchy, so you will be able to see the borders between patches. There will have been a radiosity calculation at the center of most patches. As a bonus, this is quick to run. You can then change the error_bound
up and down to see how it changes things. Likewise
modify minimum_reuse
.
One way to get extra smooth results: crank up the sample count (we have gone as high as 1300) and drop the low_error_factor
to something small like 0.6. Bump up the nearest_count
to 7 or 8. This will get better values, and more of them, then interpolate among more of them on the last pass. This is not for people with a lack of patience since it is like a squared function. If your blotchiness is only in certain corners or near certain objects try tuning the error bound instead. Never drop it by more than a little at a time, since the run time will get very long.
Sometimes extra samples are taken during the final rendering pass, if you've specified always_sample on
. These newer samples can cause discontinuities in the radiosity in some scenes. To decrease these artifacts, use a pretrace_end
of 0.04 (or even 0.02 if you are really patient and picky). This will cause the majority of the samples to be taken during the preview passes, and decrease the artifacts created during the final rendering pass. Be sure to force POV-Ray to only use the data from the pretrace step and not gather any new samples during the final radiosity pass, by removing always_sample on
from within the global_settings
radiosity block.
If your scene uses ambient objects (especially small ambient objects) as light sources, you should probably use a higher count (100-150 and higher). For such scenes, an error_bound of 1.0 is usually good. A higher value causes too much error, but lower causes very slow rendering. It is important to adjust adc_bailout.