Conversation
The cascades were split by distance from the eye, mostly logarithmically, which is what a perspective camera wants. Through an orthographic lens the eye is only where the camera was put along its axis, often tens of metres short of anything, so the near cascades covered air in front of the board and every shadow fell to the last cascade, the whole level. When isOrthographic reads the camera's matrix, the near cascades now share evenly the depth the camera's box and the casters' bounds have in common, since a pixel needs the same texel at every depth. The shading still picks a cascade by distance from the eye, so the thresholds are distances and each sphere is fitted to the slab of the box its threshold can send to it. Radii are rounded up an eighth of an octave at a time. The last cascade stays the whole scene and the caster reach-back is kept. The shadow node is handed the first view's aspect to build the box. Renderer.debugCascadeSplits exposes the thresholds for tests. orthographic_test.dart: the first split lies inside the casters' depth in the box, near and far posts land in near cascades of similar radius, and the eye's place along the axis moves a radius by one step at most.
A strategy board through an isometric orthographic camera: a floor far larger than the box the camera sees, blocks for buildings and thin posts for units from the near edge of the view to the far one. With the cascades split from the eye the posts cast no shadow that could be seen; split through the box they are as sharp at the top of the frame as at the bottom. WebGPU lands at 0 pixels from Impeller, WebGL at 0.433% and the software set at 1.117%, all on edges; the budgets are set just above. The golden scene and test counts in the documents follow.
What was done and how it was tested, and what stays left: the shading still picks a cascade by distance from the eye rather than by depth along the view axis, which costs an eye close to the board up to one rounding step of the second cascade's radius.
Collaborator
Author
|
Closed in favour of #77, which makes the same orthographic cascade change and also covers the cascade pick in the fog and shafts, the level's draw order, and fog for particles and splats. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Under an orthographic camera the directional shadow cascades were split by distance from the eye, mostly logarithmically, the way a perspective camera wants them. Through an orthographic lens the eye is just wherever the camera was put along its axis, usually tens of metres short of anything. So the near cascades covered empty air in front of the board, and every shadow ended up in the last cascade, which spans the whole level. On a big isometric board that means thin casters throw no shadow you can see.
What changed
_renderShadowMap(flutter3d_core) checksisOrthographicon the camera's matrix. When it's orthographic, the near cascades split evenly the depth that the camera's box and the casters' bounds have in common. An orthographic pixel needs the same texel size at every depth, so the split is even, not logarithmic. The common depth range comes from clipping each shape's edges against the other's half-spaces. On an isometric board that range runs from where the box's long edges hit the ground, not from the near and far planes.Renderer.debugCascadeSplitsexposes the thresholds for tests.ShadowSettings.cascadeSplitandviewDistancedocument how they behave under an orthographic camera.orthographic-shadow: a strategy board seen through an isometric orthographic camera from 60 m back. The floor is 120 m, far larger than the box. Blocks stand in for buildings and 12 cm posts stand in for units. Before this change the posts cast no visible shadow. With it they're as sharp at the top of the frame as at the bottom.orthographic-metalhas shadows off and didn't move.How it was tested
flutter3d_cpu/test/orthographic_test.dart, three new tests:orthographic-shadowis recorded in all four sets (tool/golden.sh,tool/golden.sh --cpu,tool/golden_web.sh,tool/golden_web.sh --backend=webgpu). Distance from Impeller: WebGPU 0 pixels, WebGL 0.433%, software 1.117%, all on edges (the posts are almost all edge). Budgets are set just above those numbers.tool/structure.dart: 35 rules, all held. Golden-scene and test counts in the docs are updated (91 scenes).What is left
ViewDepthunder an orthographic camera inshadow.glsl, the volumetric fog, the light shafts and the reflections (and their CPU mirrors) would remove that cost. That's a shader change on all four backends and isn't in this PR.--platform chrome) suites of flutter3d_webgl and flutter3d_webgpu weren't run here. Neither package's code changed, only the count wording in one test comment and in the golden script.lookFrom.