Skip to content
This repository has been archived by the owner on Nov 22, 2022. It is now read-only.

User Guide

Lucas Crane edited this page Jan 29, 2020 · 2 revisions

Ray Tracing Renderer is designed to serve as a drop-in replacement for WebGLRenderer. However, Ray Tracing Renderer differs in several ways, and this guide explains the differences and additions introduced by this renderer.

Animation Loop

Ray Tracing Renderer is designed to be called in a loop using requestAnimationFrame. This functionality differs from WebGLRenderer. With WebGLRenderer, a single call to render() will render the entire scene, but this is not true with RayTracingRenderer. The renderer draws the scene progressively, meaning that the more time that is spent rendering, the higher quality the resulting image looks. Thus render() should be called continuously using an animation loop.

Your loop should resemble the following form:

const renderer = new THREE.RayTracingRenderer();

// ... create scene and camera

function tick() {
  renderer.render(scene, camera);
  requestAnimationFrame(tick);
}

tick();

Lighting

As of now, DirectionalLight is the only supported native light source, but we are in the process of adding support for other lights.

Environment Light

Ray Tracing Renderer's most useful light source is the newly added Environment Light. By providing the Environment Light with an HDR environment map, the scene can be illuminated and shadowed entirely by the provided image. This method is the most realistic way of lighting a scene.

The easiest way to use the Environment Light is to obtain an image in the .hdr format, and loading the image with Three's RGBELoader.

In your HTML, load the RGBELoader script after Three.js:

<script src="three.js"></script>
<script src="RGBELoader.js"></script>

Then the loader can be used:

const scene = new THREE.Scene();
const envMap = new THREE.RGBELoader().load('envmap.hdr'); // load the hdr texture
const envLight = new THREE.EnvironmentLight(envMap); // create an Environment Light from the hdr texture
scene.add(envLight);

The environment light will also be visible in the background of your scene. To use a solid color for a background instead, set the scene.background property to a THREE.Color. Alternatively, scene.background can also be set to a separate EnvironmentLight to use as a dedicated background.

  • For a free source of environment maps, check out HDRI Haven.

Soft Directional Light

Soft Directional Light is a new light source extending the Directional Light. It functions the same with the addition of a softness parameter which controls the softness of its shadows. A value of 1.0 will cast a hard shadow, while a value of 0.0 will cast a very soft shadow.

const scene = new THREE.Scene();

const dirLight = new THREE.SoftDirectionalLight(0xffffff, 0.5, 0.3); // color, intensity, softness
dirLight.softness = 0.6; // change softness to 0.6 for a softer shadow

scene.add(envLight);

Texture loading

Ray Tracing Renderer does not support asynchronous loading of textures. Thus you should only call render() when the textures have fully loaded. This can easily be done using the LoadingManager's onLoad listener.

const renderer = new THREE.RayTracingRenderer();
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera();

function tick() {
  renderer.render(scene, camera);
  requestAnimationFrame(tick);
}

const material = new THREE.MeshStandardMaterial();
material.map = new THREE.TextureLoader().load('diffuse.jpg');
const geometry = new THREE.BoxBufferGeometry();
const mesh = new Three.Mesh(geometry, material);
scene.add(mesh);

// start render loop only when all textures have been downloaded
THREE.DefaultLoadingManager.onLoad = tick;

Materials

Ray Tracing Renderer supports MeshStandardMaterial. In addition, the renderer adds a new RayTracingMaterial class which inherets from MeshStandardMaterial, while adding some new properties.

Transparency

If the transparent property of your material to true, the resulting material will be transparent and will reflect light at grazing angles. When enabled, the metalness and roughness properties of your material are ignored.

const material = new THREE.MeshStandardMaterial();
material.transparent = true; // material will behave like glass

By default, the transparent material is modeled as a thin surface which means it does not refract light. In order to render thick glass, bodies of water, or other solid transparent objects, set the solid property to true on the RayTracingMaterial. This enables refraction. Note that for this effect to work correctly, the geometry of your mesh should be closed and it should have an inside surface.

const material = new THREE.RayTracingMaterial();
material.transparent = true; // material will behave like glass;
material.solid = true; // material will refract light as it enters the transparent medium

Shadow Catcher

The Ray Tracing Renderer is able to seamlessly blend your scene with the environment lighting. To do this, set the shadowCatcher property to true on the RayTracingMaterial. A material with this property ignores the color property, and instead takes its color from the environment light behind it. Any other mesh now casts shadows onto the shadow catcher, and it will appear as though the shadows are being cast onto the environment itself! For the effect to look the best, the geometry of this shadow catcher should match the geometry of the underlying environment.

const material = new THREE.RayTracingMaterial();
material.shadowCatcher = true; // material will catch shadows and blend with the environment map;

const geometry = new THREE.PlaneBufferGeometry(1000, 1000); // create ground plane
const mesh = new THREE.Mesh(geometry, material);
mesh.rotateX(Math.PI / 2); // rotate plane so it rests on the ground, pointing upward

// Place box on top of ground plane
// The box will now appear to naturally sit on the environment light's floor
const boxGeometry = new THREE.BoxBufferGeometry(10, 10, 10);
const boxMaterial = new THREE.MeshStandardMaterial();
const boxMesh = new THREE.Mesh(boxGeometry, boxMaterial);
mesh.position.set(0, 5, 0);

Depth of field

This feature does not work in the latest version!

To improve realism, you may opt to use a camera model that simulates a camera lens. To do this, use the provided LensCamera instead of PerspectiveCamera. This camera introduces depth of field which increases fidelity of the image.

const camera = new THREE.LensCamera();
camera.aperture = 0.01; // specifies the depth of field
camera.focus = 10; // specifies the distance to the focal point

Tone mapping

Ray Tracing Renderer simulates realistic light propagation and records the resulting lighting of the scene in HDR. This light must be must be compressed, or tone mapped, to a smaller range in order to be displayed on your monitor. Both WebGLRenderer and RayTracingRenderer provide properties which allow you to configure how this tone mapping is done.

There are several operators which map HDR to your monitor. By default, the renderer uses THREE.LinearToneMapping. This operator provides a reasonable default but can sometimes result in clipping of very bright or very dim lights. In these cases, another operator is better suited.

  • For less lighting contrast, try THREE.ReinhardToneMapping or THREE.Uncharted2ToneMapping.
  • For more lighting contrast, try THREE.CineonToneMapping or THREE.ACESFilmicToneMapping

Three.js provides a helpful example which previews how these tone mapping properties affect the renderer.

const renderer = new THREE.RayTracingRenderer();
renderer.toneMapping = THREE.Uncharted2ToneMapping; // a low contrast operator
renderer.toneMappingExposure = 2; // the higher the number, the brighter the scene

// Only affects THREE.Uncharted2ToneMapping.
// The higher the number, the less contrast in the scene
renderer.toneMappingWhitePoint = 8;