Optimising Reflection blur
From LightWiki
Optimising Reflection Blur using Nodes
Creating believability and 'photo-realism' in renders these days means using blurry reflection, instead of 'specular' which is a cheap CGI cheat. Unfortunately, while computers get ever faster, this still remains a tremendously slow process, which can increase your render times many fold, much like radiosity can. In the LightWave v9 series there have been a huge number of improvements in the rendering core, including faster ray tracing, speedier reflection blurring and the addition of the nodal shading system, but everything is relative, it can be still really slow down your render time.
Here are a number of tricks and techniques, both for render settings, and using very simple node setups, which hopefully should see a drop in your render times.
Contents |
The scene
The scene is very simple, a set of four boxes, with bevelled edges, sitting on a plane (figure 1). The point of this scene is to create 'total internal reflection' where a reflection ray will bounce off one surface, and keep bouncing off more surfaces, until its ray recursion limit is reached. In any scene with reflective surfaces you will need to have a 'ray recursion' or 'ray depth' setting to keep render times within sane levels. In the real world a photon will bounce between two reflective surfaces indefinitely, until it loses energy and is absorbed by a surface. In a rendering engine this would mean render time could be infinite, so to mitigate this you set how many times a ray will bounce. Especially in the case of blurry reflections this is an acceptable compromise, because the further it bounces, the less detail will be resolved, to the point that it would no longer be readable to the human eye that it was doing anything. Usually in a scene you set the ray recursion to be a minimum possible value to allow for any surfaces where a ray will reflect off (reflection) or pass through (transparency) as each bounce costs render times. The default of 16 is usually WAY too high for most scenes. The material in the scene is a very simple energy conserving surface, using a Fresnel gradient (figure 2). Energy conserving simply means that:Diffuse + Reflection = 100% or less
Quite often people set up reflection independently to diffuse. However diffuse simply means 'diffuse reflection' and reflection is 'specular reflection'. They are both models for describing how light will reflect off a surface. You cannot have more light reflecting off a surface than you have hitting it, hence it is important to make sure the sum of them is 100% or less. The easiest way to do this is to simply use an invert node, so that whatever reflection is, diffuse is the opposite. Many renderers don't actually have a diffuse channel (or its equivalent) and automatically configure it this way, as it's almost a redundant step.
With scene set up with a reflection node set to give a 20% blur and the standard quality it renders in 39 minutes 14 seconds. Your results may vary depending on your antialiasing settings, adaptive sampling, radiosity, the size of the render, and of course your computer specifications, but this is our baseline, and all these renders have been done on the same computer, using the exact same settings.
Reflection quality settings
The first optimisation I did here was to lower the reflection quality of the material to 0 (figure 3). The reflection quality refers to sample rays sent out by each bounce. More samples result in a smoother result, and as you can see in this picture, it is slightly grainier in some areas, though acceptable in others. This trick works well in the modern 'advanced cameras' because they take additional samples only where needed, so only the noisy areas need to be re-sampled.One of the reasons why reflection blur can take SO long is that each bounce sends out a number of sample rays, each combined to get an average value. Each of those sample rays then sends out an equal number of sample rays, for the next bounce, so by three or four recursions each pixel that you have rendered might have sent out thousands of rays!
In this case the render time only decreased to 38 minutes 32 seconds and introduced some grain. Part of the reason that it wasn't quite as successful at lowering the render time was due to the amount of recursion inherent in that scene, and the fact the antialiasing had to compensate for the lower samples. This technique can result in minimal speed improvements, or huge speed improvements, usually where it's mostly only sampling the background.
Note: This setting won't do anything in FPrime, as it has its own sampling schema. This only works for LightWave renderer.
The sampling method used in the 'reflection node' looks slightly different than the native LightWave reflection blur, for the same value. The reason I used in this case is that it can go as low as 0 samples, where as the native one can only go as low as 1.
Stopping blurring after the first bounce
One thing that many other renderers do to speed up blurred reflections/refractions is to simply stop blurring after the initial surface blur. It's not physically accurate, however it's not usually that noticeable, because the surface is blurred, you can't really tell what's going on in the reflected objects
It's something that many have wanted to be able to do with LightWave, however, ironically, it is possible, it just involves some node trickery!
The setup is simple (figure 4) but I will explain it: The Spot Info node (explanations of Spot Info here and here) gives you extra info about a 'spot' in a render, or to put it simply a single pixel in the render. In this case I take the 'sampled ray' output and feed it into a gradient. I set position 0 to my reflection value, and position 1 to black. In this example I have exposed position 1 so that you can then feed a scalar value into it, such as a texture, if you wanted that effect. What this is telling LightWave is that when the ray fires from the camera and hits that spot, (position 0), it will have this value, and then when it hits the next bounce surface, (position 1) it will have the next value. You could use this technique for all sorts of applications, however this has a lot of practical use.The render time is drop far more impressive 19 minutes 50 seconds and looks visually identical to the previous version.
Note: This setting may speed up FPrime, though I haven't been able to test it, due to the current iteration of FPrime not liking 9.6.
The extra spot node info wasn't added till about 9.2 or 9.3, so you cannot do this trick with vanilla LightWave 9.0
The output type of the spot node is pink this means that it is an 'integer value', or in other words a whole number, hence I have used a stepped gradient type: You cannot have half a bounce, a ray has either bounced or it has not, so make sure you use whole values with this spot type.
This method will also work equally well with refraction blurring too, using the exact same method.
Stopping ray recursion per surface
Another feature often asked for in LightWave is a per-surface ray recursion setting, while it can cause issues for things like glass, this also can be great for speeding up renders, as the extra bounces on some surfaces are not needed, whereas they are in others.
Again using the spot node, you can achieve the same effect (figure 5). In this case I used a logic node for the same effect, instead of a gradient, indeed either works (figure 6). If you take a look at the logic node, it is using the 'bounces' output, and using the 'a is greater than b' option. What this is saying to LightWave is "if the number of bounces is greater than 1, make it black (0) if not use this scalar input (my Fresnel node, which could also include textures, etc.)". In this case the minimum number of acceptable bounces is usually 1, because the observer should see the reflection of the reflection, but you could increase it, if needed.The render time again has dropped to 15 minutes 57 seconds. This looks almost identical again though increasing the number of bounces will eventually result in almost the same appearance. Increasing LightWave's global recursion value will not increase render time of this surface, but it will increase if other surfaces don't use it.
Note: This method should also theoretically work with FPrime.
If you have a glass object sitting on top of a reflective object, using this, it will suffer from the same problem as if you had too low a recursion value.
Again this will work with refraction blur, but may cause issues, from not enough bounces, if the value is too low.
Oversampling
Using oversampling, in the camera settings can also reduce the render time, and smooth out the grain in an image, though sometimes it can introduce some blotchiness. This is a very subjective trick which doesn't always work and can be very scene-dependant, but oversampling with a low value can speed up render time, and create a smoother effect. In this case I used the Mitchell Sharp reconstruction filter and a oversampling value of 0.5 (previously just 0.1) and the render time came down again to 11 minutes 40 seconds and removes some of the sampling grain
Conclusion
Hopefully you will be able to implement these tricks into your work-flows. The one downside to using them is that inherently the nodes themselves represent a render hit over using conventional surfaces. However in this example I have reduced the render time to only 29.79% of the original. your results may vary hugely, depending on the scene. try it for yourself. Here is the sample scene so you can compare it on your system.
Tobian.


