Conversation
The cascades were split by distance from the eye, half way to logarithmic, which is right through a perspective lens and wrong through an orthographic one: there every metre of depth gets the same texels on screen, and the eye is only where the camera was put, often tens of metres back. The near cascades covered air in front of the lens and every shadow came from the last, whole-level map. Under an orthographic camera the depths where the view box meets the casters' bounds, capped at ShadowSettings.viewDistance, are now cut into equal slabs, one per near cascade, each fitted to the corners of its own share of the box and the bounds. The last cascade is still the whole scene and the reach back towards the light is kept. ShadowFactor picks a cascade by depth along the view axis through that lens; the light shafts and the volumetric fog pick by the way along the ray from where depth is nought, which is the same distance as before through a perspective lens. The software backend mirrors all three. orthographic-shadow is in all four golden sets; the other ninety Impeller references still pass unchanged.
MeshNode.drawOrder had no word in the level format, so a stripe painted on a floor of the same stone fought the floor pixel by pixel and the only fix was to patch the node after loading. Brush.drawOrder is that word: optional, left out of the document at nought so every level keeps its bytes and its digest, and refused by the validator outside -128 to 127, the range the renderer's sort key holds, rather than clamped into a tie. Brush surfaces are batched by it, since a batch is drawn as one node with one place in the order, and LevelScene sets it on the node. A cut brush's pieces and a duplicated brush keep it. Nothing the simulation reads depends on it, so an edit of the order alone is look-only: LevelDiff.brushOrder names the brushes, from diffLevel and from a LevelPatch alike, and simulation stays empty. Any other change to the same brush still goes to simulation.
Their stages declared the fog block with two of its four members, the colour and the eye. They could not tell an orthographic camera from a perspective one, so they fogged in rings round the eye's point and faced a mesh particle towards it, and they could not read the height fog's falloff, so a puff of smoke fogged at the camera's density whatever its height. The block is now declared whole in lib/particle_fog.glsl, shared by every particle and splat stage: depth from the eye's plane through an orthographic lens, the view axis for a mesh particle's facing there, and the height fog integrated along the ray as ApplyFog does. Both particle contributors and the splat contributor bind the axis, the lens and the falloff, and the software stages mirror it. Through a perspective lens with a flat fog nothing moves: every particle and splat golden holds in all four sets. Splats under an orthographic camera are also sorted by depth along the view axis rather than by distance from the eye's point, and resorted when the axis turns.
The section 4.1 row still said orthography, alpha to coverage and the order were left. All three landed; this records the level format's draw order, the orthographic shadow cascades, the particles' and splats' fog and facing, and the splats' depth sort, with their tests and golden budgets. Left: a near plane at or behind the eye, the order in the editor's inspector, the example overlay's made-up perspective, the MCP tools, and goldens for particles and splats under an orthographic camera or in a height fog. P5 no longer lists height fog on particles and splats.
The near cascades under an orthographic camera were fitted to the corners of each slab of the view box and the casters' bounds, so their radii and slab ends moved with every pan and every caster that rose or fell. The shadow pass snaps each map to whole texels of its radius, so that grid rescaled every frame and shadow edges crawled, and a still tile was redrawn because its scale had changed instead of being scrolled. The slab ends and radii now round onto steps a sixteenth of their power of two; orthographic-shadow is re-recorded in all four sets (shadow outlines move by a texel). Tests: a centimetre's pan and a caster rising five centimetres leave the near radii and slab ends unchanged; the software shafts and volumetric fog at the edge of an orthographic frame read the near tile; a breach and an editor duplicate keep a brush's drawOrder. The shadow pass's aspect falls back to one for a viewport with no height.
The step was taken from end - start, which in doubles can come back a bit either side of the reach as start moves; at a reach that is a power of two that doubles the step and moves every slab end and near radius. The step now comes from min(far - start, reach) itself, and the power of two is found by doubling and halving instead of a logarithm, so it is exact by construction. Vector3's float corners keep the sum exact in practice, so no test reaches the old case through the engine.
Collaborator
Author
|
Re-review of 1b509d2: ok. One follow-up pushed: the rounding step now comes from the depth range's length rather than end - start, and the power of two is found exactly, so a power-of-two viewDistance cannot double the step from rounding noise. Known limit kept: there is no hysteresis, so a fit sitting on a step boundary can toggle one step; the far cascade's radius is not rounded (older than this PR). |
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.
The rest of P7 (§4.1), apart from the parts listed under "Left".
What changed
Shadow cascades under an orthographic camera. The cascades were split by distance from the eye. An orthographic camera often sits tens of metres back, so the near cascades covered empty air in front of the lens and every shadow came from the whole-level map. With an orthographic camera, the renderer now finds the depths where the view box meets the casters' bounds, caps that range at
viewDistance, and cuts it into equal slabs, one per near cascade. Each slab's sphere is fitted to the corners of that slab's part of the box and the bounds (orthographic_cascades.dart). The last cascade still covers the whole scene, and the reach back towards the light is kept. Through that lensShadowFactorpicks a cascade by depth along the view axis. The light shafts and the volumetric fog pick by distance travelled along the ray, which through a perspective lens is the same as before. The software backend mirrors all three. Adds theorthographic-shadowgolden to all four sets.Draw order in the level format. New field
Brush.drawOrder. It is optional and left out of the document when it is 0, so existing levels keep their bytes and their digest. The validator rejects values outside −128..127. Brush surfaces are batched by it andLevelScenesetsMeshNode.drawOrder. Breaches and duplicates keep it. An edit that only changes the order is look-only: it shows up inLevelDiff.brushOrder, both fromdiffLeveland from aLevelPatch.Particles' and splats' fog and facing (this also closes the P5 tail about height fog on particles). These stages now declare the whole
FogInfoblock, inlib/particle_fog.glsl. With an orthographic camera they fog by depth, and a mesh particle faces the view axis. Height fog is now integrated along the ray the same way as inApplyFog. Both particle contributors and the splat contributor bind the new members, and the CPU stages mirror them. The uniform tables and the web shader tables are regenerated.Splat sort by depth along the axis under an orthographic camera. The cloud is re-sorted when the axis turns.
How it was tested
orthographic_cascade_test.dartorthographic_cascade_pick_test.dartbrush_draw_order_test.dartlevel_loader_test.dart(draw order)particle_fog_test.dartsplat_fog_test.dart(orthographic)particle_mesh_facing_test.dartsplat_sort_test.dart(axis)orthographic-shadowagainst Impeller: WebGPU 0 pixels, WebGL 0.394%, software 1.043%. The differences are on edges, which Impeller multisamples and the others do not.tool/structure.dart: all 35 rules hold.tool/verify_plan.dartis clean.Left
MeshOverlay.lookFrom.