Shadows

  Edit on GitHub

These docs are for 0.12.0-SNAPSHOT, an unreleased SNAPSHOT. See the latest release.

A DirectionalShadowMap lets the directional light of a PBREnvironment cast shadows. The shadow casters are rendered into the shadow map first and then the scene is rendered as usual.

Shadow Map

Creates a DirectionalShadowMap and passes it to the environment. More cascades keep shadows sharp over a longer shadowDistance. cascadeBlend blends the far end of each cascade into the next to hide the seam, 0 disables it.

val shadowMap = DirectionalShadowMap(device, cascadeCount = 3)
shadowMap.shadowDistance = 40f
shadowMap.cascadeBlend = 0.1f

val lightDirection = MutableVec3f(0.5f, 0.8f, 0.3f).norm()
val environment =
    PBREnvironment(device, shadowMap = shadowMap).apply {
        setDirectionalLight(DirectionalLight(direction = lightDirection, intensity = 2.5f))
    }

Shadow Batch

A second ModelBatch renders the shadow casters using a ShadowMaterialPipelineProvider.

val shadowBatch =
    ModelBatch(device).apply {
        defaultPipelineProvider = ShadowMaterialPipelineProvider()
        depthFormat = shadowMap.format
    }

Rendering

Update and render the shadow map before the main render pass.

onUpdate { dt ->
    camera.update()
    shadowMap.update(lightDirection, camera)

    renderFrame { frame, commandEncoder ->
        shadowMap.render(commandEncoder, shadowBatch, models, dt)

        val renderPass = ... // main render pass
        models.forEach { modelBatch.render(it, camera, environment) }
        modelBatch.flush(renderPass, camera, dt)
        renderPass.end()
    }
}

onRelease {
    shadowBatch.release()
    shadowMap.release()
}

Shadow Casters

Only materials with castShadows enabled are rendered into the shadow map. Materials with an alphaCutoff cast cut out shadows.

val floorMaterial = PBRMaterial(device, baseColorTexture = checkered, castShadows = false)

val fox =
    resourcesVfs["models/Fox.glb"].readGltfModel(
        config = GltfLoaderPbrConfig(GltfModelConfig(castShadows = true, skinned = true))
    )