Skip to content

Shadow System ​

In 3D space, shadows are a key element in determining an object's three-dimensionality and its spatial relationship with other objects. RedGPU provides a physically based shadow system, allowing you to express realistic shadows with simple configuration.

1. 3 Elements of Shadow Generation ​

For shadows to appear on the screen, the following three elements must be configured properly:

  1. Light: The light source that will create the shadow. Currently, DirectionalLight supports shadow generation.
  2. Caster: The object that creates the shadow. (e.g., character, building) -> mesh.castShadow = true
  3. Receiver: The object that receives the shadow. (e.g., floor, wall) -> mesh.receiveShadow = true

[Performance Note]

Shadow calculations consume significant GPU resources. Therefore, rather than applying them to all objects, it is better for performance optimization to selectively apply them to visually important objects and surfaces.

2. Object Configuration (Cast & Receive) ​

Every Mesh object in RedGPU has independent properties that determine whether it creates or receives shadows.

javascript
// 1. Object creating the shadow (Caster)
const box = new RedGPU.Display.Mesh(redGPUContext, boxGeometry, boxMaterial);
box.castShadow = true;

// 2. Object receiving the shadow (Receiver)
const floor = new RedGPU.Display.Mesh(redGPUContext, floorGeometry, floorMaterial);
floor.receiveShadow = true;

3. Shadow Quality Management (ShadowManager) ​

The Scene owns a ShadowManager and DirectionalShadowManager internally, allowing you to globally configure Cascaded Shadow Maps (CSM) and soft shadow (PCSS) quality.

javascript
const directionalShadowManager = scene.shadowManager.directionalShadowManager;

// 1. Set shadow map resolution (Default: 2048)
directionalShadowManager.shadowDepthTextureSize = 2048;

// 2. Cascade (CSM) split count and maximum shadow distance
directionalShadowManager.cascadeCount = 4;        // Split count (1 ~ 4, Default: 4)
directionalShadowManager.maxShadowDistance = 200; // Maximum shadow distance (Default: 200)

// 3. Shadow strength and soft shadow (PCSS) control
directionalShadowManager.strength = 0.9;      // Shadow darkness (0.0 ~ 1.0, Default: 0.9)
directionalShadowManager.pcssLightSize = 1.0; // Virtual light size (larger values soften edges, Default: 1.0)
directionalShadowManager.bias = 0.00015;      // Shadow bias to prevent shadow acne (Default: 0.00015)

4. Practical Example: Configuring a Scene with Shadows ​

An example of casting a rotating box's shadow onto the floor using a DirectionalLight.

javascript
import * as RedGPU from "https://redcamel.github.io/RedGPU/dist/index.js";

const canvas = document.getElementById('redgpu-canvas');

RedGPU.init(canvas, (redGPUContext) => {
    const scene = new RedGPU.Display.Scene();
    
    // 1. Setup directional light (specify light direction vector)
    const light = new RedGPU.Light.DirectionalLight([-1, -1, -1]);
    scene.lightManager.addDirectionalLight(light);

    // 2. Create floor (Receiver)
    const floor = new RedGPU.Display.Mesh(
        redGPUContext,
        new RedGPU.Primitive.Ground(redGPUContext, 20, 20),
        new RedGPU.Material.PhongMaterial(redGPUContext, '#cccccc')
    );
    floor.receiveShadow = true; 
    scene.addChild(floor);

    // 3. Create box (Caster)
    const box = new RedGPU.Display.Mesh(
        redGPUContext,
        new RedGPU.Primitive.Box(redGPUContext),
        new RedGPU.Material.PhongMaterial(redGPUContext, '#ff0000')
    );
    box.y = 2;
    box.castShadow = true; 
    scene.addChild(box);

    const controller = new RedGPU.Camera.OrbitController(redGPUContext);
    const view = new RedGPU.Display.View3D(redGPUContext, scene, controller);
    redGPUContext.addView(view);

    const renderer = new RedGPU.Renderer();
    renderer.start(redGPUContext, () => {
        box.rotationX += 1;
        box.rotationY += 1;
    });
});

Live Demo ​



Next Steps ​

Learn how to add infinite backgrounds and photorealistic environment light to spaces where three-dimensionality has been brought to life with shadows.