public sealed class TerrainSceneRendererThe compositor node that draws the world's terrains: the surface, and each terrain's grass.
Remarks
What !Terrain builds to — the runtime reachability the whole stack was missing. TerrainRenderer, GrassDispatch and GrassDrawPass are complete and tested and had no caller outside the editor; this is the caller. It reads the frame's terrains from a TerrainSceneSource the extraction system fills, owns one draw set per heightfield, and declares two passes: an attachment-less pass for the uploads and the scatter dispatch — a render graph pass with no attachments runs outside a render pass, which is where a transfer and a compute dispatch are legal — and a raster pass that loads the frame's colour and depth and draws.
⚠ The depth is the scene's, loaded and written. Terrain is opaque geometry that happens to be drawn after the Main pass, so it must occlude and be occluded — reverse-Z, CompareFunction.Greater, which is DepthStencilState.Default and what every pipeline in this stack already builds. A read-only depth here would draw the ground over every wall that should hide it.
⚠ Preview-grade shading, stated rather than discovered. Terrain.rvn lights with its own hard-coded sun and the default permutation covers four weight-blended layers; frame-lit shading rides TerrainLit when the frame provides its half, and shadow casting is TerrainCasterRenderer's — a sibling node, because a caster must run before the passes this node runs after. Motion vectors are TerrainVelocityRenderer's, a sibling for the mirrored reason: the frame's velocity pass clears the motion plane after this node's own passes have run, so the reprojection is staged here and recorded there. What this node settles is placement and reachability, which is the part a document can say.
⚠ A heightfield placed twice draws once. The renderer's constants are per frame and per placement, so a second entity naming the same terrain would overwrite the first's placement before either draws. The editor shares the atlas and accepts the same limit; SharedPlacements is where the second placement is counted rather than silently lost.
Fields and properties (30)
public const float GrassCellSizeThe cell grid every grass field scatters over, in metres.
public const float DefaultGrassRangeHow far grass cells stay resident when neither component nor document says.
public const float DefaultFoliageRangeHow far foliage cells stay uploaded when neither component nor document says.
public required string OutputThe colour target the ground draws into.
public required string DepthThe depth target it tests and writes.
public string AlbedoThe frame's split albedo plane, bound beside Output when it exists.
public string NormalsAnd its normal plane, on the same terms.
public string ShadowAtlasThe frame's cascade atlas — half of what makes the ground frame-lit at all.
public string ScenePassWhich pass's names the frame's lighting is published under.
public SceneConstants? FrameThe frame's set-0 state, whose parameters and scene lighting the lit path reads.
public RenderView? ViewThe view whose camera places, culls and streams the ground.
public TerrainSceneSource? SceneWhere the frame's terrains come from, or null while nothing supplies them.
public TerrainVegetationQuality VegetationThe resolved vegetation numbers this node runs at.
public bool GrassWhether grass fields scatter and draw at all.
public IGraphicsDevice? DeviceThe device, or null for a node that declines to draw.
public EffectPipelineDescriber? ModulesWhere shader modules come from.
public int TerrainsDrawnHow many terrains the last frame drew.
public int GrassFieldsDrawnHow many grass fields the last frame dispatched.
public int SharedPlacementsHow many placements were dropped because their heightfield was already placed.
public int RefusedTerrainsHow many terrains the renderer refused — a shape problem, not a frame problem.
public int GrassLayersMissingHow many grass fields named a weight layer their terrain does not have.
public bool VegetationUnsupportedWhether the device cannot run GPU-scattered vegetation at all, which is why there is none.
public int FoliageVolumesDrawnHow many foliage volumes the last frame culled and drew.
public int FoliageMeshesMissingHow many palette types drew nothing because their mesh has not resolved.
public bool WaitingForShadersWhether the last build was still waiting for a shader to resolve.
public bool LitWhether the last build chose the frame-lit shaders over the preview.
public bool SplitWhether the ground wrote the frame's split planes as well as its colour.
public bool MotionVectorsWhether the ground stack reprojected into the frame's motion target this frame.
public int VelocityDrawsHow many reprojection draws the sibling recorded last frame — terrains, grass fields' indirect commands and foliage batches' together.
public bool ClusteredLightsWhether the lit shaders read the frame's culled cluster lists.
Methods (3)
protected override void Build(GraphicsCompositor compositor, CompositorFrame frame)Declares this node's render-graph passes.
public void Dispose()Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
public override string ToString()Returns a string that represents the current object.
Used by (10)
- ArenaThirdPersonShooter
- FrameDocumentTestsThirdPersonShooter.Frame.Tests
- FrameDocumentTestsPbrShowcase.Frame.Tests
- PbrShowcaseGamePbrShowcase
- TerrainCasterRendererVixen.Rendering.Terrain
- TerrainCasterTestsVixen.Rendering.Terrain.Tests
- TerrainFactoryVixen.Rendering.Terrain
- TerrainNodeTestsVixen.Rendering.Terrain.Tests
- TerrainVelocityRendererVixen.Rendering.Terrain
- TerrainVelocityTestsVixen.Rendering.Terrain.Tests