Vixen
dd8b0a81
csharp
public sealed class CameraExtractionSystem

Turns the scene's Camera entity into the frame's RenderView.

No guide page documents this yet — the page shows what the code says about itself.

As a system

Phase
PreRender

Remarks

The last unwired half of "a world is drawn". Camera was a component a scene could place, CameraMath built the two matrices it implies, and RenderView was what every pass culls and draws against — and nothing anywhere read the first and wrote the last. A level with a camera in it rendered from wherever the host had last poked the view by hand, which is why every sample steers its own.

One view, not one per camera. The view is handed in rather than created here, because a view's name is what a compositor document binds a node to (view: Camera) and its stage mask is the host's — a document with two cameras in it is a document with two named views, and two of these. What this decides is only which entity fills the one it was given.

Lowest Order wins, ties going to the first the world walks. That is Order's documented meaning — "which camera renders first" — read as a priority, and it is the same rule the editor's scene list sorts by. A scene with no camera at all leaves the view exactly as it was and says so through Found: a frame drawn from a stale matrix is a picture, and a frame drawn from a zeroed one is a black screen that looks like the renderer is broken.

It also carries the sub-pixel offset temporal antialiasing needs — see JitterTarget. That makes this the one place a frame's projection is decided, and the audit of who is allowed to see the offset is worth writing down, because the dangerous half of applying it is not applying it:

Immune, because they read scalars and not a matrix. The shadow cascade fit (ShadowCascades.Split, Sphere, Fit take position, forward, field of view, aspect and the planes), the froxel grid (ClusterGrid.Apply writes tanHalfFov and the planes, deliberately not the matrix), the volumetric fog's own froxel volume, and ScreenHeightScale for LOD. Safe because they invert this frame's matrix to unproject this frame's depth, so the offset cancels: the deferred world-position reconstruction, SSAO (which inverts Projection — hence the offset living there too), SSR, the screen-probe gather's placement and its host readback of depth and normals, the distance-field AO, the sky's per-pixel ray, the water and underwater passes, and the virtual-shadow page marking. Safe because both matrices carry their own frame's offset: motion vectors, and the terrain, grass and foliage velocity passes. The vector between a jittered current and a jittered previous is exactly where the history texel is, which is what the resolve samples — so no separate un-jittering is needed anywhere. Moved by half a pixel and judged acceptable: the culling frustum, which ViewProjection re-derives (a jittered camera really does see a half-pixel-shifted volume); the Hi-Z occlusion test, which uses the previous frame's matrix against the previous frame's depth and so is self-consistent; and the fog's temporal reprojection, whose previous matrix is jittered and whose froxels are two orders of magnitude wider than the offset. ⚠ The one consumer that would rather not have it: MotionBlurRenderer. A still camera now produces a velocity of up to one pixel — the difference between two consecutive offsets — where the truth is zero. Its MinimumRadius of half a pixel is what keeps that a copy rather than a smear, since the shutter fraction halves it again; a frame that lowers that threshold would be buying a permanent sub-pixel blur.

In PreRender, ordered by its declared access — the placement LightExtractionSystem explains: TransformSystem writes WorldTransform in the same phase and this reads it, so a camera moved this frame is rendered from where it now is rather than from where it was.

Fields and properties (10)

  • public Camera Chosen

    The camera extracted last, or a zeroed one when there was none.

  • public RenderView View

    The view this fills.

  • public float AspectRatio

    Width over height of what is being rendered into, for a camera whose own is zero.

  • public Int2 JitterTarget

    The size of what the frame is drawn into, in pixels, or zero for no sub-pixel jitter.

  • public int JitterPeriod

    How many offsets the sequence uses before it repeats. Eight is the usual.

  • public Vector2 Jitter

    The offset the last extraction applied, in pixels.

  • public bool Found

    Whether the last pass found a camera to render from.

  • public int CameraCount

    How many cameras the last pass saw, of which one was used.

  • public int Rank

    Which camera this fills its view from, counting up from the lowest Order. Zero is that lowest one.

  • public SystemAccess Access

Methods (3)

  • public CameraExtractionSystem(RenderView view)

    Turns the scene's Camera entity into the frame's RenderView.

  • public override JobHandle Update(in SystemContext context, JobHandle dependency)

    Runs the system.

  • public void Extract(World world)

    Points the view at the scene's camera.

Used by (4)

  • AppGraphicsVixen.App.Hosting
  • CameraExtractionTestsVixen.Rendering.Tests
  • SplitScreenExtractionTestsVixen.Rendering.Tests
  • HostedRendererTestsVixen.App.Tests