The classical shadowbuffer - as supported in Blender until now - creates an image with Z values, as seen from a Spot Lamp, and uses these Z values to determine if a shadow gets received. By carefully tweaking the buffer resolution and clipping information you can define the quality of shadows. However, this system always will suffer the limitation of a buffer size, and it has to be calculated for an entire scene in advance, making it not part of the threaded tile-render system.
Recently several papers have been published on a succesful alternative method. Instead of creating a regular image from the Lamp point of view, it maps all to-be-rendered samples (the image pixels) to "Lamp space", and uses these samples to determine if faces in a scene are casting shadow. This method is called "Irregular Z buffering" because all such samples cannot be simplyy stored in a regular X-Y grid in Lamp space.
Because each sample is individually tested for shadow, it results in crispy and sharp shadows just like for ray-traced shadows. This method now is available in Blender.
To store these irregular samples two methods were tested. The first method uses per Lamp a fixed size X-Y look-up table, which has the advantage that existing scan converting for zbuffering can be re-used. An alternative method stores the samples in a Kd-tree (a BSP tree with axis-aligned seperation of cells).
Both methods were tested. The first was easier to implement and relatively fast, but suffered the big problem of having a fixed size table, which demands to still tweak table size for rendering and giving slow renders for extreme cases (like lighting a large city with a single lamp).
The second method, using a Kd-tree, proved to be slightly slower in optimal cases, but it suffered no slowdown at all for extremer cases.
Paper references (pdf):
Gregory Johnson et al, University of Texas, Austin.(Regular grid method).
Timo Aila and Samuli Laine, Helsinki University of Technology.(BSP method).
The "Shadow and Spot" panel now offers a menu to choose buffer type. Here you can set the buffer to become "Irregular".
As usual you have to indicate the clipping start/end range. However, this now won't affect shadow quality as much as for the Classical buffer type.
Bias
The main reason to set these values is still the "Bias", which is for this kind of buffer only a fraction of the biasing compared to Classical Shadow buffers, but still has to be a sufficient large value to prevent floating point accuracy issues.
The default Bias value of '1.0' represents for Irregular Shadow buffers 0.0005 of the total depth range (between clip start/end). For Classical Shadow buffers this is 0.01.
Note: the Bias implementation is a candidate to implemented better, it could become a scene-independent constant.
Threading and Memory use
Best feature of this new buffer is that it is being created entirely within a thread, for each tile being rendered. Memory allocation and freeing is also done only within the thread itself. Especially for very large scenes this will give a significant benefit.
Before actual shading happens, the shadows are calculated in a pre-process. Per Lamp all the samples are converted and inserted in a Kd-tree and checked for shadow. Only the end-result (shadow value per pixel) is stored for usage while shading.
Memory overhead of a Irregular Shadow buffer is as follows (assuming a 1920x1024 HD frame, OSA 8, 6 x 4 tiles):
- persistant storage per Scene rendered: 0.0 MB
- creating shadow buffer; storing all samples, 8 (OSA) x 24 (sample size) x 81920 (pixels in part) = 15 MB + 0.5 MB (KD tree)
- storage of shadow result (per lamp): 4 (float) x 81920 (pixels in part) = 320k
Only while creating the shadow buffer a peak allocation is required. This peak is freed entirely for each Lamp, so the amount of Irregular Buffers only depends on the storage of the shadow results.
Note that with a single part render, this peak can easily become 380 MB for a HD frame.
Irregular shadows are also created for each Render Layer again. However, like for Classical Shadow buffers, shadow casting faces are all visible Scene layers, unless the Lamp "Lay" option is used; in that case it uses faces in the visible Lamp layers.
What doesn't work...
Since this method directly works with the samples of the scanline render system, shadow casted by Irregular Buffers are not visible for ray-traced mirrors, ray-traced transparent or for solid Halos.
Soft shadow is also not possible, nor is 'halo step' possible.
Demo files
Here you can load two example files for quick testing:
Because of the way Irregular buffers work, support for transparent shadow casters can be quite simply added, hardly without extra render time.
The current implementation only supports a fixed transparency per face, no textures are being evaluated. The transparency value can be controlled with the new Material option "Shad A" (Shadow Alpha) in the "Material" panel.
The monkey head image to the right shows a regular Solid material with a Shadow Alpha set to 0.4.
The picture with the windows shows transparent shadows casted by Ztransp faces.
Obviously the biggest benefit would be when Ztransp pixels could als receive shadow with Irregular buffers. However, that would mean that all of the to-be-rendered samples will have to be included in the Kd-tree. In cases when multiple transparent layers overlap (can be 100s in case of hair strands) the memory overhead will raise a lot.
As for solid faces, this is only during creation of the shadow buffer, memory that gets all freed before actual shading happens.
The last two pictures here show Ztransp faces and transparent shadow.
Strands
Strands are tested for shadow casting in the Irregular buffer with the exact width as being rendered. This gives acceptable shadow with short distances, but when strands are far away from where they cast shadow on aliasing can occur.
Although Irregular buffer shadow for strands was tested and works fine, it still will give quite long rendering times for Ztransp strands, especially when 100s of strands cover a single pixel. In that case all these samples have to be inserted in the Kd-tree and tested for shadow, even when not visible.
A much better choice for strand shadow is to use regular shadow buffers. It's also time to investigate the Deep Shadow Buffer system...
The main calls for Irregular buffer shadow are:
void ISB_create(RenderPart *pa, struct APixstr *apixbuf);
void ISB_free(RenderPart *pa);
float ISB_getshadow(ShadeInput *shi, ShadBuf *shb);
The 'create' and 'free' calls are within a part render, just before and after actual shading of the Solid and Z-Transparent layers. These calls go over all Lamps, and if required create the buffers.
Creating a buffer consists of the following steps: