engine: support up to 4 additional shadowless directional lights - #10248
engine: support up to 4 additional shadowless directional lights#10248yuvaltassa wants to merge 2 commits into
Conversation
pixelflinger
left a comment
There was a problem hiding this comment.
LGTM. I'd like @show50726 to review the spec constant stuff.
| // Sort the directional lights by decreasing intensity. The most intense one is the | ||
| // dominant directional light (stored at index 0 of the LightSoa); it is the only one | ||
| // that casts shadows and can be a sun. Up to CONFIG_MAX_EXTRA_DIRECTIONAL_LIGHTS | ||
| // additional directional lights are evaluated without shadows; the rest are ignored. |
There was a problem hiding this comment.
I think this will do for now, but I'm starting to think we should have a setDominantLight() on scene or view, or something.
| return; | ||
| } | ||
| for (int i = 0; i < CONFIG_MAX_EXTRA_DIRECTIONAL_LIGHTS; i++) { | ||
| if (i < frameUniforms.extraLightCount) { |
There was a problem hiding this comment.
What's the reason of not breaking the loop earlier?
There was a problem hiding this comment.
Feature level 0, mostly. This loop also compiles and, with several directional lights in the scene, runs at ES2, where the constant is emulated via the injected SPIRV_CROSS_CONSTANT_ID define rather than a real spec constant. Strict GLSL ES 1.00 front-ends only guarantee constant-bounded loops, so I didn't want to rely on a data-dependent break being accepted there. Happy to change it if you'd rather special-case FL0.
|
We might want to update the material precompile api as well: filament/filament/src/details/Engine.cpp Lines 1837 to 1848 in 50aa368 You will have to update |
|
@show50726 baseKey.setExtraDirectionalLights(isMaterialLit && view->hasExtraDirectionalLights()); |
Allow a scene to contain up to CONFIG_MAX_EXTRA_DIRECTIONAL_LIGHTS (4) directional lights in addition to the dominant one; the additional lights are evaluated without shadows. The dominant directional light (highest intensity) behaves as before: it owns slot 0 of the light SoA, cascaded shadow maps and the sun disc. Directional lights beyond the cap are ignored, preserving the previous dominant-light selection semantics as the degenerate case. The feature is automatic and adds no cost to the common single-light case: a new dynamic specialization constant (RUNTIME_CONFIG_HAS_EXTRA_DIRECTIONAL_LIGHTS, following the RUNTIME_CONFIG_HAS_DYNAMIC_LIGHTING pattern) is set per view when the scene contains more than one directional light, so the extra lights loop compiles away entirely in programs specialized for single-light scenes. - Scene: FScene::prepare collects all directional lights and partial-sorts them by intensity; the extras are kept in SceneCacheData and never enter the froxelizer or ShadowMapManager. - Uniforms: new extraLightDirection[4], extraLightColorIntensity[4] and extraLightCount fields in PerViewUib, carved out of the existing reserved slack (the struct remains exactly 2 KiB). Light channels are packed into extraLightDirection[i].w. - Shaders: new evaluateExtraDirectionalLights() loop in surface_light_directional.fs, gated by the dynamic specialization constant, under the existing VARIANT_HAS_DIRECTIONAL_LIGHTING variant, so no new variants are introduced. - DynamicSpecConstKey gets an EXTRA_DIRECTIONAL_LIGHTS bit, set from FView::hasExtraDirectionalLights() when building render passes. - MATERIAL_VERSION bumped to 75 (new PerViewUib layout and dynamic specialization constant). - LightManager.h documentation and release notes updated. Tested by FilamentTest.MultipleDirectionalLights (dominant selection, extras ordering, direction transforms, truncation past the cap) and RenderingTest.MultipleDirectionalLights (headless render of a quad first lit by a single green directional light, verifying no red contribution, then adding a weaker red directional light and verifying the red contribution appears, which also exercises the automatic program re-specialization).
7be3727 to
31c2431
Compare
|
Rebased onto main to resolve a release-notes conflict from the 1.74.1 branch. While at it, |
| s.extraLightColorIntensity[i] = float4{ | ||
| lcm.getColor(li), lcm.getIntensity(li) * exposure }; | ||
| } | ||
| s.extraLightCount = int32_t(count); |
There was a problem hiding this comment.
nit: use static_cast<int32_t>
show50726
left a comment
There was a problem hiding this comment.
The spec const part looks good to me!
Allow a scene to contain up to
CONFIG_MAX_EXTRA_DIRECTIONAL_LIGHTS(4) directional lights in addition to the dominant one; the additional lights are evaluated without shadows. The dominant directional light (highest intensity) behaves exactly as before — it owns slot 0 of the light SoA, cascaded shadow maps, and the sun disc — and directional lights beyond the cap are ignored, preserving the previous dominant-light selection semantics as the degenerate case.The feature is automatic and free for the common single-directional-light case: a new dynamic specialization constant (
RUNTIME_CONFIG_HAS_EXTRA_DIRECTIONAL_LIGHTS, following theRUNTIME_CONFIG_HAS_DYNAMIC_LIGHTINGpattern from #10095) is set per view when the scene contains more than one directional light, so the extra-lights loop compiles away entirely in programs specialized for single-light scenes.Core changes:
FScene::preparecollects all directional lights and partial-sorts them by intensity; the dominant one is stored at slot 0 as before, the next 4 are kept inSceneCacheDataside arrays (direction +LightManagerinstance). They never enter the froxelizer orShadowMapManager.extraLightDirection[4],extraLightColorIntensity[4]andextraLightCountfields inPerViewUib, carved out of the existingreservedslack (the struct remains exactly 2 KiB). Light channels are packed intoextraLightDirection[i].w.evaluateExtraDirectionalLights()loop insurface_light_directional.fsunder the existingVARIANT_HAS_DIRECTIONAL_LIGHTING— no new variants. The loop is gated by the dynamic specialization constant; extras skip shadowing and the sun disc.DynamicSpecConstKeygets anEXTRA_DIRECTIONAL_LIGHTSbit, set fromFView::hasExtraDirectionalLights()when building render passes;canSupportExtraDirectionalLightslimits it to lit surface variants with directional lighting, bounding the program-key growth.MATERIAL_VERSIONbumped to 75 (newPerViewUiblayout and dynamic specialization constant).LightManager.hdocumentation and release notes updated.Tests:
FilamentTest.MultipleDirectionalLights: dominant selection, extras ordering by intensity, direction transforms, truncation past the cap, and the single-light case.RenderingTest.MultipleDirectionalLights: headless render of a quad first lit by a single green directional light (verifying no red contribution), then with a weaker red directional light added (verifying red appears) — which also exercises the automatic program re-specialization.