Click to go Home  
Render times
User Profiles
Macros / Scripts
Materials / VSL
User images
Image Contest
Realsoft images
VRgrafix images
Mech Turtle
By David Coombs, 2002

The RealSoft3D ray-tracing process - Part 5: Secondary Rays

By David Coombes

Foreword to Part 5

This part explains the way reflections and refractions are calculated using secondary rays, and hence why RealSoft3D is termed a recursive ray-tracer. This concept is fundamental to a good "mental image" of RealSoft3D. Hopefully this should open up the big picture and make tapping it's power that much easier.

What is a reflection

Diagram showing reflected light

Here's a very common representation of a reflection. It shows a yellow sphere above a mirror. The sphere is illuminated by what light sources surround it. The arrows show the direction the light is travelling. Light bounces from the sphere and travels to the camera, and to the mirror where it is reflected towards the camera. The blue line is the surface normal - the line perpendicular to the surface. With all reflections, the angle of the light from the reflected surface (sphere) relative to the surface normal is equal to the angle of the light from the reflecting surface (floor) relative to the surface normal.

If the floor is matte white, with one directional light from the front-left, the image in the camera would look like this.

With the floor as a perfect mirror, 100% of the light from the sphere is reflected

If the floor is a perfect green mirror, 100% of the green light from the surface is reflected and none of the red or blue...

How to produce a reflection

Let's have a look at that diagram again. We can already see how tracing rays is used to create the scene. For the light travelling from the sphere directly to the camera, RealSoft3D traces a ray from the camera to the sphere. The values of the sphere's properties, such as colour, direction of the surface, amount of illumination, etc., are then stored in channels and used to create the final image colour. When examining the floor, also a ray is cast. But in this instance we need to show not just the floor but also what the floor is reflecting. RealSoft3D has an elegant solution for this.
We already possess a procedure for evaluating a surface by casting a ray. What happens with a reflection is that this procedure is invoked again, only this time tracing a ray from the point on the mirror that the camera sees, in the direction that the ray is reflected. The default actions of RealSoft3D are to add the Surface:Illumination of the reflection to the Surface:Illumination of the mirror. When a ray cast invokes another ray, this other ray is called the Secondary Ray.


The Secondary Ray shader

Referring back to the render pipeline diagram of Part 4, you'll see the presence of the secondary ray shader after surface illumination. Whenever a material involves reflections or refractions, this shader is invoked. It casts a secondary ray which evaluates a surface exactly as normal, and then this data is made available to the secondary ray shader in the Traced Ray sample. This sample's channels holds the information regarding the reflection, such as Traced Ray:Illumination storing the illumination of the reflected surface, and Traced Ray:Distance storing the distance from mirrored surface to reflected surface. Secondary ray adds reflections to a surface by adding the amount of reflected light (Traced Ray:Illumination * Surface:Reflection) to the surface's illumination, Surface:Illumination. Lets look at this process by walking through the tracing of the reflected ray shown in the above diagram.

This shows some of the shaders (most of the usually executed ones) in order of execution, listing the results from those shaders if they change any of the channel data. As you can see, the first ray trace process does not finish until the second process has because it is waiting for the results of that secondary ray shader. When the second ray has finished, the result of it's Surface:Illumination becomes the value of Traced Ray:Illumination in the secondary ray shader.

How to produce a refraction

Though the term refraction implies the splitting of light into different colours, in RealSoft3D it relates to creating transparency effects by letting light pass through a surface. Such refractions are created in the same way as reflections, casting a secondary ray, only with refractions the secondary ray is cast the other side of the surface. Also, the direction of the ray is affected by the refractive index of the material.  By default refracted rays travel in the same direction as the initial ray. Instead of multiplying the illumination of the secondary ray by Surface:Reflection, transparency secondary rays are multiplied by Surface:Transparency.

To recap, when a surface is reflective (Surface:Reflection is not 0), a secondary ray is cast in the direction the ray would be reflected off the surface. When a surface is transparent (Surface:Transparency is not 0), a secondary ray is cast in the direction the ray would be refracted, usually the same direction as the first ray. The default actions of secondary ray are to add to Surface:Illumination the following...

    Reflection: Surface:Illumination += Traced Ray:Illumination * Surface:Reflection
    Transparency: Surface:Illumination += Traced Ray:Illumination * Surface:Transparency

If a surface is both reflective and transparent, the secondary ray shader is invoked twice, once for each ray cast.


I called this method 'elegant' because it doesn't need complicated layers of extra procedures to produce reflections and refractions. The same procedure of casting a ray is used recursively, calling itself again when needed. This does throw up the question as to what happens when you have reflections of reflections?  The diagram opposite shows such a situation. Two parallel mirrors are viewed from an angle such that a traced ray is reflected from one side to the other and back again.  As you can see, the first ray cast invokes another secondary ray, which in turn invokes another secondary ray, which in turn...six rays are shown in the diagram. When a non-reflective surface is hit, it's illumination is added to Surface:Illumination of the mirror, which then becomes the Traced Ray:Illumination of the previous ray cast. Imagine a non-reflective object where the 6th ray ends (such as, to be really original, a yellow sphere). The rays are invoked like this...

Camera Cast Ray 1
hits reflective surface
     Cast Secondary Ray 2
     hits reflective surface
          Cast Secondary Ray 3
          hits reflective surface
               Cast Secondary Ray 4
               hits reflective surface
                    Cast Secondary Ray 5
                    hits reflective surface
                         Cast Secondary Ray 6
                         hits non-reflective surface
                         Surface:Illumination += Surface:Illumination of non-reflective surface

                    Traced Ray:Illumination = Surface:Illumination of previous ray (6)
                    Surface:Illumination += Traced Ray:Illumination * Surface:Reflection

               Traced Ray:Illumination = Surface:Illumination of previous ray (5)
               Surface:Illumination += Traced Ray:Illumination * Surface:Reflection

          Traced Ray:Illumination = Surface:Illumination of previous ray (4)
          Surface:Illumination += Traced Ray:Illumination * Surface:Reflection

     Traced Ray:Illumination = Surface:Illumination of previous ray (3)
     Surface:Illumination += Traced Ray:Illumination * Surface:Reflection

Traced Ray:Illumination = Surface:Illumination of previous ray (2)
Surface:Illumination += Traced Ray:Illumination * Surface:Reflection

Ray Termination

Now imagine these mirrors are very long, and you start to see that it could happen that the ray tracing process will get caught up tracing reflections of reflections of reflections. There even arise situations where the rays never meet a non-reflective surface, such as when tracing internal reflections in a transparent, reflective object. In such circumstances RealSoft3D would get caught in a never ending loop. The solution is to set a limit as to the number of recursions that will be allowed. This is the Recursion Depth setting of the current render settings. When the threshold is reached, no subsequent secondary ray shaders are executed. For example, if the recursion threshold for the above diagram were set at three, only the first three rays would be traced. When the third ray hit the mirrored surface, instead of calling the secondary ray shader and casting another ray, the shader ray termination is called. By default this shader does nothing and rays terminated because of recursion depth are black (no illumination), but ray termination can be used for adding to the illumination of the ray. I'll illustrate the results of recursion depth and ray termination with an example scene.

The scene is of two mirrored surfaces viewed along their lengths. At the end of the mirrors is a plane with a striped pattern. There are no light sources; the pattern is output to the Surface:Illumination channel. This pattern is reflected along the mirrors towards the camera. The mirrors are a slight-blue colour to show the different recursions.

This render shows the scene with a high enough recursion depth (depth = 7) to show all the recursive reflections.

With a recursion depth of three, secondary rays are not traced for higher levels of recursion. The result is dark areas where no surface illumination exists.

In the mirror material's ray termination shader I've placed the line Surface:Illumination = (1,1,1). Now when the ray tracing is terminated beyond 3 levels of recursion, the final surface illumination is white. This is then reflected in the mirrors. You can still see the mirrors are showing only a limited number of reflections but it does not look as bad as having no illumination during ray termination.

To show that reflection termination isn't limited to producing black or white illumination, here's the same scene with ray termination's Surface:Illumination as a yellow colour. One could just as easily have ray termination end with a texture map, procedural texture, or any other VSL effect.

In most scenes without transparent surfaces a recursion depth of three is adequate for convincing results. When using transparent materials, overlapping layers of material can quickly increase the recursion depth requirement. If for speed reasons you wish to keep recursion depth to a minimum, using the ray termination shader can help conceal the rendering inaccuracies and produce presentable images.

The other cause of premature ray termination is the render setting Recursion Threshold. The idea here is that the level of illumination from some reflections and refractions can be too low to make any noticable difference to the rendered scene. In such cases there's no point in calculating the low-intensity secondary rays as they won't be visible. If the result of a secondary ray's Illumination channel is below the user specified threshold, the ray termination shader is invoked and no subsequent recursions are entered into. This is of particular use in glass materials where internal reflections add heavily to recursion calculation requirements but often don't generate visible results. A suitable recursion threshold would prevent these recursions being calculated, thereby saving on render time.

The Finale

I'll conclude with a look at the recursions involved when tracing a glass like sphere. Glass includes both reflections and refractions and exhibits internal reflections. Each level of recursion is shown in a different colour. Reflected rays are shown in the darker colours, refractions are paler.

The End

This concludes the explanation of ray-trace recursion, and I guess that wraps up the RealSoft3D Rendering Pipeline. You should now be pretty clued up on samples, channels, shaders and recursion. What I haven't covered, how you use this information in creating custom materials, controlling reflections, and making use of RealSoft3D's phenominal post-process capabilities to generate unique images, is the subject of future tutorials and explanations.

The next topic I'll tackle will be VSL, it's understanding and usage. Without a good groundwork knowledge of the basics it's easy to get lost trying to figure out VSL code or create your own, which is why I've kept it to a minimum so far.

Until then, if you have any questions the RealSoft3D users mailing list is the place to ask them. There are plenty of tutorials available in the RenderDaemon pages and if there's enough need you'll often get a tutorial being created by the excellent user community to help you out.

Many thanks goes to David Coombs for investing so much time in writing these terrific articles - Bernie

Page updated on Monday, 28 April, 2003 . For feedback / model submissions or articles - please email us.
Site proudly sponsored by VR.grafix
Goto Sponsors Site (VRgrafix)