GOAL/Endresult#
- Apply Material with MD=Arena to Objects in Scene
- Expected result: they get culled out through a hardcoded stencil sphere
Two cases:
- Normal gameboard arena
- Half-dome portal gameboard
StencilMaskVal: 1 =>#
arena: allowed to write: stencil_val == 1 && depth_near
stadium: allowed to write: && depth_near
StencilMaskVal: 2 =>#
arena: allowed to write: stencil_val == 2 && depth_near
stadium: allowed to write: stencil_val != 2 && depth_near
Steps#
Sphere write out stencil_val = 1
Draw Arena:
StencilOp = < 3
DepthOp = depth_near
Draw Stadium:
StencilOp != 2
DepthOp = depth_near
Highlevel implementation tasks#
-
Hardcode render two spheres as the stencil geo into stencil buffer (just piggy back on custom depth)
Case: Normal gameboard
Case: Portal gameboard
Case: Special (space tear)
- Sphere one writes stencil value that masks arena geo
- Sphere two writes stencil value that masks stadium geo- Nongoal: Exact stencil operations/mask bits unimportant; figure them out later. Just need to make sure it doesn't get stomped
- Goal: See how this affects translucent/masked materials whether in the arena or stadium and others that may not be thinking of (like decals/particles/etc)
-
Modify prepass :
- Prepass arena geo with stencil ops: Depth Test, Depth Write, Stencil=Keep (do not write), Stencil Test
Stencil Compare = Equal & Stencil Op = Keep, Depth Write, Depth Compare = Greater
- Prepass everything else as normal -
Modify the basepass:
- Render arena geo first
- Render everything else as normal
- Possible Issues: Filtering out arena geo from the normal execution flow
Approaches#
- MaterialDomain + ViewRelevance as the extension point
GameThread:
- CreateSceneProxies/Renderstate
- Sometimes dirty it/recreate it for dynamic stuff
RenderThread:
SceneProxies implements:
- (Everyframe for dynamic/mebbe not for static)GetDynamicMeshElements/GetStaticElements
-
ComputeViewRelevance =>
-
Mark which passes to mark this component to be included in that pass
-
This also more complicated than just what is being returned here bc we also have to take into account the material (e.g. if the material is translucent=>viewrelevance for translucency)
NOTE: Look at how custom depth property in the component is percolated all the way to the RT and how it gets added to custom depth primset -
Extend SetPrimitiveViewRelevance(FPrimitiveViewRelevance& OutViewRelevance) const
- If MaterialDomain == MD_BBArena, outviewrelevance.arenarelevance = 1
Render Side:
-
Gather all viewrelevance.arena into a drawlist/primset
-
REFERENCES: custom depth, StaticMeshBatchVisibility, VisibleDynamicPrimitives, TranslucentPrimSet, CustomDepthSet
DynamicMeshElements
To add to custom primsets (e.g. customdepthprimset/translucent), it's in this function:
FRelevancePacket::ComputeRelevance() is where it updatees them (in parallel way)
FRelevancePacket::RenderThreadFinalize() is where it writes them back out to FSceneView/FScene -
REFERENCES: PositionOnlyDepthDrawList, DepthDrawList, BasePassUniformLightMapPolicyDrawList
Here's where we create the drawlists:
void FStaticMesh::AddToDrawLists(FRHICommandListImmediate& RHICmdList, FScene* Scene)
-
Depth: Prepass Render Arena
-
Prepass arena geo with stencil ops: Depth Test, Depth Write, Stencil=Keep (do not write), Stencil Test - This is done in FDeferredShadingSceneRenderer::RenderPrePassView
-
Base Pass:
- Custom Function to render our arnea-> ?????
- Make sure it doesn't get rendered in normal pass -> ????
UPrimitiveComponent.bRenderinmainpass
ShouldUseAsOccluder()
ShouldRenderInMainPass()
- Looks like it's used alongside ShouldIncludeDomainInMeshPass
GetMaterialRelevance
ShouldIncludeDomainInMeshPass()
FMeshBatch.UseDynamicData
FMeshBatch.ReverseCulling
FMeshBatch.CastShadow
FMeshBatch.bUseAsOccluder
-
Create separate primsets like custom depth and add our arena components to that
Advnatages: Might be simpler
Disadvantage: Might be rigid and inflexible with lots of edge cases
Ex: What happens when we need to draw things that are in both stadium & arena? viewrelevance bitmask sounds better -
Just take a look at decals/mesh decals
Helpful bits#
SetDepthStencilStateForBasePass()
TStaticDepthStencilState<...>::GetStaticState() for the class defining all the stencil op state
TStaticStencilState<>::GetRHI() for getting the default stencil (iirc, stencil expects to be set back to the default but not sure)
RHICommandSetStencilRef() for setting stencil
Custom depth primset
Decals
Decals:PostProcessing
FTranslucentPrimSet
FCustomDepthPrimSet
StencilDithering for LOD transitoins
Visiblity Culling Interesting things#
virtual bool CanBeOccluded() const override
-Gets Called in FPrimitiveSceneInfo::AddToScene() & setting FScene.PrimitiveOcclusionFlags
FrustumCull<true, true>(Scene, View);
FViewInfo
FSceneBitArray PrimitiveVisibilityMap;
ICustomVisibilityQuery* CustomVisibilityQuery
There's a separation between PrimitiveBounds & PrimitiveOcclusionBounds