Advanced shader authoring · Command reference

Multiple-light shadows

In Extended mode on Direct3D 12, Metal (macOS/iOS) or WebGPU, ShadowLightLimit 4 requests up to four simultaneous shadow sources. The default remains one. Built-in Classic, Standard, lit materials and volumetric fog apply each source's visibility to that light's direct contribution; ambient and emission are unaffected.

Only the first eight submitted lights participate. Higher LightShadows priority wins; directional lights win equal-priority ties, followed by submitted order. Point shadows require High or Ultra. The 512 MiB renderer shadow budget includes queued and retiring source maps. A source can receive lower resolution or be omitted; all its cascades or point faces are admitted together. An omitted light still illuminates.

Custom shaders

Existing compiled shaders retain their unchanged constants and primary map at t8. To receive all sources, use a format-3 layout-4 manifest and recompile:

blitz3d_shader 3
layout 4
mode surface
multi-light-shadows 1

The compiler defines B3D_MULTI_LIGHT_SHADOWS_VERSION=1. The shared surface helper already handles per-light factors. Raw shader authors include blitz3d_multi_light_shadows.hlsli after the ordinary shader interface and use the original submitted light index:

float3 radiance = lightRadiance * cookieRGB;
if (B3DMultiShadowsEnabled()) {
    radiance *= B3DMultiShadowFactor(lightIndex, worldPosition, worldNormal, cameraViewZ);
}
// Evaluate this light's diffuse and specular lobes with radiance, then accumulate.

When the extension is enabled, skip any legacy final-colour shadow correction. The RGB factor is 1 - (1 - tint) * strength * (1 - visibility). For fog, B3DMultiShadowVisibility supplies scalar visibility; retain the existing fog strength and filtering rules.

The extension binds eight depth texture arrays at t0 through t7 in space5 and a 7312-byte constant buffer at b0 in space5. It shares comparison sampler s8. The one appended descriptor table leaves old registers, buffers, instance strides and root indices unchanged. Unused entries are neutral. Shadow coverage passes also receive neutral bindings. On Metal, the shader compiler maps these registers into each stage's binding table and uses argument buffers for texture-heavy materials. Recompile source shaders with the updated compiler to use the extension. WebGPU stages retain the same register identities in their binding headers and select individual depth arrays explicitly in WGSL.

WebGPU's plain Classic path supports the baseline 16 sampled textures per stage. Cookies need 17, and the Standard material needs 30. The browser requests the adapter's available limits; unsupported materials use Classic with a diagnostic, and devices below 17 textures omit cookies. WebGPU counts logical depth texel bytes against the 512 MiB budget because browsers do not expose driver allocation sizes.

Behaviour and diagnostics

Extended mode evaluates default-material direct lighting per pixel with shadows off, with one source or with multiple sources. Changing the shadow limit does not change the lighting model. Original mode retains per-vertex lighting. Entity cast/receive flags and camera shadow gates apply to every source. Legacy Mirror views still skip shadow gathering, and GPU particles do not cast shadows.

Use DrawRenderStats with shadow statistics enabled to see admitted sources, map resolutions and allocated bytes. The multi-light sample demonstrates two lamps, movable casters, quality/priority changes, cookies and fog.