Skip to content

Latest commit

 

History

History
361 lines (299 loc) · 27.8 KB

File metadata and controls

361 lines (299 loc) · 27.8 KB

Shadow Mapping and Transparency Shadowing Guide

This guide covers openQ4's user-facing shadow-map settings, including projected-light shadow maps, experimental point-light shadow maps, cascaded shadow maps (CSM), alpha-tested transparency shadows, and the current experimental translucent-shadow path.

Quick Start

Recommended starting point:

seta r_shadows 1
seta r_useShadowMap 1
seta r_shadowMapCSM 1
seta r_shadowMapHashedAlpha 1
vid_restart

Optional experimental translucent-shadow overlay:

seta r_shadowMapTranslucentMoments 1
seta r_shadowMapTranslucentDensity 1.0
seta r_shadowMapTranslucentMinAlpha 0.02
vid_restart

Notes:

  • r_shadows must stay enabled for any shadow path to render.
  • If the shadow-map path is unavailable or fails for a light, openQ4 falls back to the legacy shadow path instead of leaving the light unshadowed.
  • Point lights shadow-map by default (r_shadowMapPointLights 1); they are the dominant light class in Quake 4 content. Set r_shadowMapPointLights 0 to fall back to stencil shadows for point lights only.
  • Lights touching animated, deformed, or packed character receivers can also fall back to the legacy stencil path so stock character lighting, mirrored seams, and eye materials retain retail-style interaction behavior.
  • Modern renderer diagnostics keep lighting visible when shadow-map receiver sampling is not ready, but full modern visible-frame replacement stays fail-closed so the legacy path continues to provide the actual shadowed frame.
  • Most shadow cvars can be changed live, but vid_restart is the safest way to apply large changes such as map resolution, cascade layout, or switching the shadow pipeline on/off.

What the System Does

openQ4 currently supports:

  • Projected-light shadow maps for regular projected lights.
  • Point-light cubemap shadow maps for omni/point lights (the dominant Quake 4 light class), on by default.
  • Optional projected-light cascaded shadow maps (CSM).
  • Alpha-tested transparency shadows for cutout materials such as fences, grates, and foliage cards.
  • Optional experimental translucent-shadow accumulation for some blended materials.

High-level behavior:

  • Opaque materials cast normal solid shadows.
  • Alpha-tested or perforated materials cast cutout shadows in the shadow-map pass.
  • Blended/translucent materials do not cast translucent shadowing unless r_shadowMapTranslucentMoments 1 is enabled.
  • The translucent-shadow path is experimental and intentionally conservative.

Recommended Presets

Balanced Quality

seta r_shadows 1
seta r_useShadowMap 1
seta r_shadowMapCSM 1
seta r_shadowMapSize 1024
seta r_shadowMapFilterRadius 2.0
seta r_shadowMapFilterTaps 13
seta r_shadowMapPointFilterRadius 2.5
seta r_shadowMapPointFilterTaps 13
seta r_shadowMapHashedAlpha 1
seta r_shadowMapCascadeStabilize 1
vid_restart

Higher Quality

seta r_shadows 1
seta r_useShadowMap 1
seta r_shadowMapCSM 1
seta r_shadowMapSize 2048
seta r_shadowMapCascadeCount 4
seta r_shadowMapFilterRadius 2.5
seta r_shadowMapFilterTaps 13
seta r_shadowMapPointFilterRadius 3.0
seta r_shadowMapPointFilterTaps 13
seta r_shadowMapHashedAlpha 1
seta r_shadowMapCascadeStabilize 1
vid_restart

Optional Modern Filtering

seta r_shadowMapFilterMode 1
seta r_shadowMapPointFilterMode 1
seta r_shadowMapStaticCache 1
vid_restart

For projected lights, r_shadowMapFilterMode 2 enables the experimental PCSS-lite path. Hardware depth-compare sampling cannot run the blocker search needed for PCSS-lite, so selecting filter mode 2 automatically switches the renderer to the manual raw-depth path even while r_shadowMapDepthCompare 1 is set.

Performance-Focused

seta r_shadows 1
seta r_useShadowMap 1
seta r_shadowMapCSM 0
seta r_shadowMapSize 512
seta r_shadowMapFilterRadius 1.5
seta r_shadowMapFilterTaps 5
seta r_shadowMapPointFilterRadius 2.0
seta r_shadowMapPointFilterTaps 5
seta r_shadowMapHashedAlpha 1
vid_restart

Experimental Blended Transparency

seta r_shadows 1
seta r_useShadowMap 1
seta r_shadowMapCSM 1
seta r_shadowMapHashedAlpha 1
seta r_shadowMapTranslucentMoments 1
seta r_shadowMapTranslucentDensity 1.0
seta r_shadowMapTranslucentMinAlpha 0.02
vid_restart

Core Shadow Settings

Setting Default Range What it does
r_shadows 1 0..1 Master shadow toggle.
r_useShadowMap 0 0..1 Enables the shadow-map pipeline for supported lights.
r_shadowMapCSM 0 0..1 Enables cascaded shadow maps for projected lights.
r_shadowMapProjectedCSM 1 0..1 Allows ordinary projected lights to use CSM when r_shadowMapCSM is enabled; parallel/global lights keep their dedicated large-coverage policy.
r_shadowMapConservativeCasters 1 0..1 Keeps shadow-map caster submission separate from visible receiver scissors, so off-screen blockers can still shadow visible receivers.
r_shadowMapSkipStencilShadows 1 0..1 Skips stencil shadow volume generation and linking for lights that will render shadow maps, removing the duplicate CPU shadow work. A light that fails a shadow-map pass automatically restores its stencil volumes on the next frame.
r_shadowMapCasterCulling 2 0..2 Caster face culling: 0 renders casters two-sided, 1 stores light-facing faces, 2 stores back faces (fewer acne artifacts, slight detachment on thin geometry). Materials declared twoSided/backSided are always honored, so grates, foliage, and curtains cast correctly in every mode.
r_shadowMapSize 1024 128..4096 Base shadow-map resolution. Higher values cost more VRAM and GPU time.
r_shadowMapAtlasSize 4096 2048..8192 Edge size of the shared projected-light shadow atlas. Cached projected lights occupy r_shadowMapSize-sized cells inside it (CSM lights use a 2x2 cell block), so all cached lights stay resident in one texture.
r_shadowMapFilterRadius 2.0 0..8 Projected-light PCF filter radius in texels.
r_shadowMapFilterTaps 13 1..13 Projected-light PCF tap budget. Values up to 1, 5, 9, and 13 select progressively wider sample sets.
r_shadowMapFilterMode 0 0..2 Projected-light filter mode: fixed PCF, stable rotated Poisson, or experimental PCSS-lite with raw depth sampling.
r_shadowMapDistantFilterScale 0.35 0..1 Scales projected PCF and PCSS radii for parallel/global distant sources such as sky or sun lights. Their texels cover much more world space than local projectors, so a tighter kernel preserves caster silhouettes instead of over-blurring them. Set 1 to use the ordinary projected-light radii unchanged.
r_shadowMapPCSSLightRadius 4.0 0..16 Projected PCSS-lite blocker search radius in shadow texels.
r_shadowMapPCSSMaxRadius 8.0 0..16 Maximum projected PCSS-lite filter radius in shadow texels.
r_shadowMapPointFilterRadius 2.5 0..8 Point-light PCF filter radius in texels.
r_shadowMapPointFilterTaps 13 1..13 Point-light PCF tap budget. Values up to 1, 5, 9, and 13 select progressively wider sample sets.
r_shadowMapPointFilterMode 0 0..1 Point-light filter mode: fixed PCF or stable rotated Poisson.
r_shadowMapDepthCompare 1 0..1 Uses hardware comparison sampling (with hardware-filtered PCF taps) for projected depth maps. Selecting PCSS-lite (r_shadowMapFilterMode 2) automatically uses the manual raw-depth path instead. Set 0 if a driver has trouble with GLSL shadow samplers.
r_shadowMapPointDepthCompare 1 0..1 Uses hardware comparison sampling for point-light depth cubemaps when GLSL 1.30 support is available.
r_shadowMapPointHighPrecision 0 0..1 Stores point-light shadow depth in an fp16 color cubemap instead of packed RGBA8. The packed path quantizes finer at half the memory, and the default hardware-compare path samples the depth cubemap directly, so this only affects the manual fallback.
r_shadowMapPointLights 1 0..1 Shadow-maps point lights when r_useShadowMap 1 is enabled. Point lights are the dominant light class in Quake 4 content, so disabling this makes shadow mapping nearly a no-op; set 0 to fall back to stencil shadows for point lights only.
r_shadowMapPointSize 512 128..2048 Point-light cube face resolution, separate from r_shadowMapSize: each cached point light stores six faces of color and depth, so cube resolution dominates shadow VRAM.
r_shadowMapHashedAlpha 1 0..1 Uses hashed alpha testing for perforated/alpha-tested casters when supported.
r_shadowMapStableAlphaHash 1 0..1 Seeds hashed alpha from world-space caster coordinates to reduce atlas/camera-space dither drift.
r_shadowMapProjectionPad 0.15 0..1 Padding around projected-light shadow coverage.
r_shadowMapPointFarScale 1.25 1..4 Padding multiplier for point-light shadow range.
r_shadowMapCascadeCount 4 1..4 Number of projected-light cascades when CSM is enabled.
r_shadowMapCascadeDistance 1536 64..8192 Camera-space distance covered by projected-light cascades.
r_shadowMapCascadeLambda 0.75 0..1 Mix between uniform and logarithmic cascade split placement.
r_shadowMapCascadeBlend 0.15 0..0.5 Crossfade width between projected-light cascades.
r_shadowMapCascadeStabilize 1 0..1 Snaps cascade bounds to texels to reduce shimmering.

Residency and Update Budgeting

openQ4 can keep static-only shadow maps resident and reuse them across backend views. This is enabled by default for regular projected and point lights. Dynamic casters, translucent caster passes, and view-fitted CSM/global passes are conservative by default and continue to update normally unless explicitly opted in.

Setting Default Range What it does
r_shadowMapStaticCache 1 0..1 Reuses resident shadow maps for static-only projected and point lights.
r_shadowMapStaticHysteresisFrames 2 0..120 Frames to wait after dynamic casters disappear before a point light becomes cacheable again. Projected lights stay cached while dynamic casters move: their static tiles persist in the atlas and the moving casters are composed on top each frame.
r_shadowMapResidentFrames 120 1..3600 Frames an unused static shadow map can stay resident before its slot may be expired.
r_shadowMapProjectedCacheSize 8 0..16 Static projected-light cache slots inside the shared atlas.
r_shadowMapPointCacheSize 12 0..16 Static point-light cubemap cache slots.
r_shadowMapCacheCSM 0 0..1 Allows static-cache reuse for CSM/global shadow-map passes. Leave off unless you are testing a fixed-view or otherwise stable scene.
r_shadowMapSubviewPolicy 1 0..2 Shadow maps in mirror/remote-camera subviews: 0 renders them like main views, 1 reuses cached maps or falls back to stencil, 2 prefers stencil in subviews. When the target has no usable stencil attachment or an ownership contains map-only casters, Vulkan still renders the required fresh map rather than dropping its shadow.
r_shadowMapTranslucentReceivers 1 0..1 Lets translucent surfaces sample the shadow map like opaque receivers, matching the stencil path's r_stencilTranslucentShadows behavior.

r_shadowMapMaxUpdatesPerView still limits discretionary dynamic shadow-map work. Resident cache hits do not consume that update budget, so static light reuse can reduce update pressure without starving moving lights. When the budget constrains a frame, updates go to the most important stale lights first (screen coverage, staleness, and view proximity ordered), and starved lights age up the priority list so every light is eventually refreshed; denied lights reuse their last cached map when one exists. On Vulkan, a receiver ownership containing a map-only caster can exceed the nominal budget because no equivalent complete stencil result exists, and those correctness-required maps are admitted before optional maps can consume bounded resources. Cache signatures include caster materials, alpha/hash settings, caster offset settings, point-light range/depth mode, and view-fitted CSM state, so changing those inputs forces a fresh shadow map instead of reusing stale resident data.

Projected lights with moving casters no longer pay full re-renders: the light's static geometry stays cached in the shared atlas, and each frame the cached tiles are copied and only the moving casters are drawn on top. A walking character in a cached light costs one small copy plus its own triangles.

Transparency Shadowing

Cutout / Alpha-Tested Materials

These are materials with holes cut by alpha test, such as:

  • Chain-link fences
  • Grates
  • Leaf cards
  • Other perforated or masked surfaces

Behavior:

  • They cast cutout shadows in both projected and point shadow-map paths.
  • r_shadowMapHashedAlpha 1 is the recommended mode and is enabled by default.
  • If a perforated stage uses explicit texture coordinates, openQ4 can render it with either hashed alpha or hard alpha-test shadowing; unsupported animated texgen cutouts cast conservative solid depth instead of dropping the shadow.
  • Translucent shadow coverage stages preserve the same material alpha-test mode, so blended foliage/glass masks stay consistent with opaque cutouts.

Hashed alpha notes:

  • Usually gives more stable distant foliage/fence shadows than hard binary alpha test.
  • Can look slightly noisy on some surfaces.
  • If you prefer harder but cleaner cutout edges, set r_shadowMapHashedAlpha 0.

Blended / Translucent Materials

These are materials with real blending instead of alpha-test cutouts, such as:

  • Some glass-like surfaces
  • Certain layered blended materials
  • Some effect-style soft transparency

Behavior:

  • Off by default.
  • Optional with r_shadowMapTranslucentMoments 1.
  • Implemented as an additional experimental translucent shadow overlay on top of the main shadow map.

Current limits:

  • Supported stages currently include old-style alpha and premultiplied-alpha stages with explicit ST texture coordinates, plus common additive blend add / GL_ONE, GL_ONE stages.
  • When a translucent shell/tint stage is layered on top of a separate explicit-ST coverage stage, openQ4 now reuses that coverage stage, including its alpha-test threshold when present, so layered pickup-orb and similar materials can cast shaped transmitted shadows instead of only uniform blobs.
  • Supported translucent casters now derive colored transmission from the material inputs available to that stage: texture alpha, sampled texture RGB, stage color, and applicable vertex color.
  • View-dependent reflection cubemaps are treated as tinted transmissive shells instead of using the reflected sample directly, so pickup orbs can tint transmitted light without camera-dependent shadow color shifts.
  • The current high-quality path stores separate translucent shadow moments for red, green, and blue, so each channel resolves blocker depth independently instead of sharing one grayscale depth distribution.
  • GUI/subview materials are skipped.
  • BSE/FX particles, unusual custom stage setups, and many effect-style materials are intentionally not forced into the translucent shadow pass.
  • Colored transmission is still approximate rather than a full deep-shadow solution, but it is materially closer to real tinted transmission than the earlier scalar/grayscale model.
  • This path adds extra GPU work because eligible lights render an additional translucent caster pass.
  • The feature now expects enough hardware for 3 translucent MRT attachments and 3 extra texture samplers in the receiver path; if that is unavailable, openQ4 disables this experimental translucent-shadow feature.

Controls:

Setting Default Range What it does
r_shadowMapTranslucentMoments 0 0..1 Enables the experimental blended/translucent shadow overlay.
r_shadowMapTranslucentDensity 1.0 0..8 Scales resolved translucent-shadow strength.
r_shadowMapTranslucentMinAlpha 0.02 0..1 Ignores very faint translucent stages below this alpha.
r_shadowMapTranslucentFilterRadius -1.0 -1..8 Translucent moment filter radius in texels. -1 inherits the opaque shadow filter radius.
r_shadowMapTranslucentMinVariance 0.00001 0.000001..0.01 Minimum variance used when resolving translucent shadow moments.
r_shadowMapTranslucentBleedReduction 0.0 0..0.95 Reduces light bleed in the translucent moment resolve. Higher values can make translucent shadows harsher.

Suggested use:

  • Start with r_shadowMapTranslucentMoments 1, r_shadowMapTranslucentDensity 1.0, r_shadowMapTranslucentMinAlpha 0.02.
  • Raise r_shadowMapTranslucentDensity if the effect looks too weak.
  • Raise r_shadowMapTranslucentMinAlpha if very faint blended surfaces create more shadowing than you want.
  • Use r_shadowMapTranslucentFilterRadius when translucent shadows need a different softness than opaque shadows.
  • Increase r_shadowMapTranslucentBleedReduction only when moment light bleed is visibly worse than the added hardness.
  • Turn the feature back off if you want the most predictable performance and compatibility.

Bias and Artifact Tuning

Shadow artifacts are usually one of two classes:

  • Shadow acne or speckling: bias is too low.
  • Peter Panning or detached shadows: bias is too high.

Projected-light tuning:

Projected shadow maps store Quake 4's authored light falloff depth directly, so the projected defaults are intentionally small. Raise them only when you see acne or speckling.

Setting Default Range What it does
r_shadowMapBias 0.00016 0..0.05 Constant receiver depth bias for projected lights.
r_shadowMapNormalBias 0.00075 0..0.05 Extra projected-light bias on sloped receivers.
r_shadowMapTexelBiasScale 0.45 0..8 Uses texel-aware receiver bias based on fitted cascade/light footprint. Constant bias acts as a compatibility floor.
r_shadowMapNormalOffsetScale 1.0 0..8 Normal-offset bias in shadow texels: pushes the receiver sample point along the surface normal on sloped surfaces, fixing acne without detaching contact shadows. The preferred first knob for slope acne.
r_shadowMapReceiverPlaneBias 0 0..1 Allows derivative receiver-plane bias for wider projected-light filters.
r_shadowMapPolygonFactor 0.75 0..16 Slope-scale caster depth offset applied by the caster shaders while rendering shadow maps (shadow casters write shader depth, which glPolygonOffset cannot bias).
r_shadowMapPolygonOffset 0.5 0..64 Constant caster depth offset in resolvable depth-buffer steps, applied by the caster shaders alongside the slope-scale term.

Point-light tuning:

Setting Default Range What it does
r_shadowMapPointBias 0.00010 0..0.05 Constant receiver depth bias for point lights.
r_shadowMapPointNormalBias 0.0010 0..0.05 Extra point-light bias on sloped receivers.

Point-light constant and texel-aware receiver bias also use the larger value rather than stacking both terms, so tuning one path does not automatically over-bias the other. The slope-amplified texel-aware term is capped internally so grazing receivers do not create detached shadows.

Practical advice:

  • Raise bias values slowly in very small steps.
  • If shadows detach from contact points, lower the relevant bias before changing many other settings.
  • Existing configs may keep older archived bias values. If detached shadows persist after updating, compare your local cvars against the defaults above.
  • If CSM shimmers while moving the camera, keep r_shadowMapCascadeStabilize 1.
  • Wider filter radii usually need more careful bias tuning.

Debugging and Diagnostics

Setting / Command Default What it does
r_shadowMapDebugMode 0 Projected-light shadow debug mode.
r_shadowMapDebugOverlay 0 Draws a top-left mini-map of the selected shadow map plus frame counters.
r_shadowMapReport 0 Shadow-map diagnostics: 0 off, 1 summary, 2 per-light decisions, 3 verbose receiver-submit decisions.
r_shadowMapReportInterval 30 Frames between report prints when r_shadowMapReport is enabled.
r_shadowMapMaxUpdatesPerView 0 Optional per-view shadow-map update budget. 0 means unlimited. Lights over budget reuse their last cached map when one exists (shadows lag briefly instead of flickering to stencil); lights with no cached map fall back to stencil when that receiver ownership has a complete stencil result. Vulkan may exceed the nominal budget for an ownership containing map-only casters so it does not become falsely unshadowed.
r_shadowMapGpuTimerQueries 1 Uses non-blocking GL timer queries for shadow-map GPU timing when the driver supports them.
r_shadowMapGpuSyncTimings 0 Diagnostic-only GPU-synchronized pass timing using glFinish; leave off during normal play.
reportShaderPrograms n/a Prints current ARB/GLSL shader validity, including shadow programs.

r_shadowMapDebugMode values:

  • 0: Off
  • 1: Projected shadow atlas/depth
  • 2: Cascade index
  • 3: Projected UV
  • 4: Projected depth
  • 5: Projected W
  • 6: Invalid mask
  • 7: Bias heatmap
  • 8: Bias off
  • 9: PCF off
  • 10: Caster polygon offset off
  • 11: Receiver-plane/normal bias off
  • 12: Compare-depth delta
  • 13: Receiver eligibility
  • 14: Receiver fallback reason

Useful workflow:

  1. Enable r_useShadowMap 1.
  2. Set r_shadowMapDebugMode 1 to inspect projected atlas/depth content.
  3. Set r_shadowMapDebugOverlay 1 to keep a live mini-map in the top-left corner while you play.
  4. Use r_singleLight to lock the overlay to one light; otherwise it follows the last successfully rendered mapped light that frame.
  5. The overlay stats are: POINT / PROJ = light type, L / G = local/global interaction pass, F / C = point faces or projected cascades, MAP / FB = whether the selected pass stayed on shadow maps or fell back. The extra caster row reports alpha, translucent, rejected, and expanded off-screen caster counts.
  6. Point-light overlay tiles are face indices 0..5 in a 3x2 layout: 0 = +X, 1 = -X, 2 = +Y, 3 = -Y, 4 = +Z, 5 = -Z.
  7. Use reportShaderPrograms if the scene looks unlit or obviously wrong.
  8. Use r_shadowMapReport 1, 2, or 3 for live diagnostic logging. Summary lines include point depth-compare usage as pointCmp, timer-query totals as gpuQuery, and the SM cache: line reports cache hits, misses, resident reuse, budget reuse, evictions, active projected/point cache slots, and resident shadow VRAM. The SM metrics: line reports per-frame updates, composed static/dynamic layer passes (composed), subview reuse/fallback activity, translucent receiver chains drawn with shadow sampling, and importance-budget denials. The SM modern: line summarizes the modern path's consumption of the persistent atlas (live atlas slots, mapped/cache-reuse lights, and per-light blocking counts). Verbose projected CSM bias lines include per-cascade near/far range, fitted depth range, world texel size, and clip-space depth extent. Level 3 adds receiver-submit diagnostics for mapped-light cases that had visible receivers but no GLSL interaction submissions. Per-light lines separate semantic light class from backing shadow-map resource shape. For example, a stock authored parallel light may report class=parallel type=point when it uses the point-resource path.
  9. When rejected casters are present, the SM caster-reject: line breaks them down by reason, such as view-only entities, depth-hack models, disconnected portal areas, GUI/subview surfaces, non-shadowing materials, or disabled/unsupported translucent casters.

Troubleshooting

  • If shadows do not appear at all, check r_shadows 1 and r_useShadowMap 1, then run vid_restart.
  • If projected-light shadows shimmer while moving, keep r_shadowMapCSM 1 and r_shadowMapCascadeStabilize 1.
  • Parallel/global sky shadows automatically use the tighter r_shadowMapDistantFilterScale 0.35 policy. If a particular outdoor scene still looks too soft, lower it toward 0; if you want the old shared projected-light softness, set it to 1.
  • If cutout materials cast solid-looking shadows, make sure r_shadowMapHashedAlpha 1 is enabled and the material is actually alpha-tested with explicit texture coordinates. Unusual animated texgen cutouts may cast conservative solid depth until that stage type is supported.
  • If translucent shadows are too strong or too noisy, lower r_shadowMapTranslucentDensity or disable r_shadowMapTranslucentMoments.
  • If blended materials still do not cast translucent shadows, that material may be outside the currently supported stage set. Common additive pickup orbs are supported, but many particle/effect materials still are not.
  • If point-light shadows look too detached, reduce r_shadowMapPointBias or r_shadowMapPointNormalBias.
  • If projected-light shadows look detached, reduce r_shadowMapBias, r_shadowMapNormalBias, r_shadowMapTexelBiasScale, r_shadowMapPolygonFactor, or r_shadowMapPolygonOffset in small steps.
  • If projected-light acne appears only with large filter radii, try r_shadowMapReceiverPlaneBias 1 before greatly increasing constant bias.
  • If PCSS-lite seems unchanged, confirm r_shadowMapFilterMode 2 is active; the renderer selects the manual raw-depth path for that mode automatically.
  • If point-light depth compare causes shader trouble on a driver, leave r_shadowMapPointDepthCompare 0; the renderer falls back to the high-precision color-depth cubemap path.
  • If static-cache reuse hides expected updates while testing unusual content, set r_shadowMapStaticCache 0 or reduce r_shadowMapResidentFrames.
  • If performance drops sharply after enabling translucent shadowing, turn off r_shadowMapTranslucentMoments first; it adds an extra pass for eligible lights.

Platform Support Matrix

Platform Shadow maps Notes
Windows (GL3.3+) Supported Primary development and validation platform; the bit-exact regression net runs here.
Linux (GL3.3+) Supported Same GL feature path as Windows.
Steam Deck Supported Recommended: r_shadowMapSize 1024, r_shadowMapPointSize 512, r_shadowMapMaxUpdatesPerView 2, r_shadowMapCSM 1 with r_shadowMapCascadeCount 3. The importance-ordered update budget keeps per-frame shadow cost bounded.
macOS (Apple legacy GL2.1 tier) Stencil only The Apple compatibility corridor lacks the GLSL/FBO feature set the shadow-map receiver and caster programs require. Lights fall back to the retail stencil path automatically; this is expected and documented behavior, not an error.
macOS (opt-in Vulkan through MoltenVK) Implemented, untested on Apple hardware Requires r_renderApi vulkan and a full engine restart. MoltenVK is a Vulkan-on-Metal translation layer bundled in both macOS packages, not a Metal renderer. This path uses the same Vulkan shadow implementation as Windows and Linux — projected, point, parallel, and global lights, cascades, PCF/PCSS-lite, and static caching — but no real-Mac evidence exists yet, so treat it as experimental and expect problems. The default macOS renderer is still OpenGL, which uses the row above.

The shadow-map pipeline fails closed per light: any light that cannot complete the map path (missing capability, failed framebuffer, unsupported receiver) renders with the retail stencil path for that light instead of losing its shadows.

Summary

Recommended default user setup:

  • r_shadows 1
  • r_useShadowMap 1
  • r_shadowMapCSM 1
  • r_shadowMapHashedAlpha 1
  • r_shadowMapCascadeStabilize 1
  • r_shadowMapStaticCache 1

Only enable r_shadowMapTranslucentMoments 1 if you specifically want experimental blended transparency shadows and accept the extra cost and current material-support limits.