🔳 CosterGraphics.Systems.OutlineSystem
🧑🎨🧑🎨🧑🎨🧑🎨🧑🎨Outline3DRenderFeatureHyper

⬜ Simple-Msk-ColorTextureMask-Default.shadergraph
🧱 Simple-Msk-ColorTextureMaskDepthTested-Default.shadergraph
⬛ Basic-Msk-DepthTextureMask-Default.shadergraph
🟦 Basic-Msk-NormalsTextureMask-Default.shadergraph
🟩 Basic-Msk-UVTextureMask-Default.shadergraph
🟧 Basic-Msk-ObjSpacePositionTextureMask-Default.shadergraph
🪪 Adv-Msk-ObjectIDTextureMask-Default.shadergraph
🌱🏞️ Pro-Msk-JFA-UVSeedsTextureMask-Silhouette_Outside-Default.shadergraph
🌱🏠 Pro-Msk-JFA-UVSeedsTextureMask-Silhouette_Inside-Default.shadergraph
🔃 Intermediate Buffer Shaders:
🌱📸 Pro-Intermediate-JFA-UV-CopyPass-Default.shadergraph
🦘↔️ Pro-Intermediate-JFA-UV-JumpPassHorizontal-Default.shadergraph
🦘↕️ Pro-Intermediate-JFA-UV-JumpPassVertical-Default.shadergraph
🖼️ Final Composite Shader(s):
🖼️ Simple-Cmp-Silhouette-Outside-Default.shadergraph
(Or any other Hyper or lower tier Composite shader)
The 🌌Hyper Renderer Feature supports all of the Simple, Basic, Advanced and Pro 🖼️Composite shaders and also adds support for per-feature multiple 🖼️Composite passes.
With the 🌌Hyper Renderer Feature 🔳Outlines, 🔲Overlays and 🎦FullScreen effects can be stacked per-feature, making it much easier to create multi-composite-pass styles and by enabling the Require Camera Color Copy Pass toggle each 🖼️Composite pass can also request an extra 📸Camera Color Copy Pass to be executed right before it, which makes it possible to chain the effects of one 🖼️Composite pass with the next.
This ⛓️Chaining of effects can be used for instance to run multiple consecutive blur passes, where each pass further blurs the output of the previous pass, or for multiple dither passes where each pass uses a dither material with a different scale and threshold (like layering noise with octaves).
In the example image above four 🖼️Composite passes are added to the 🌌Hyper Renderer Feature to create a full retro dither style that first adds a tiny bit of 📺Noise to the image with a 3D noise filter material (noise can be added to the image by setting the Blending Mode to Additive on the noise material), then the second pass applies a 🩶Grayscale filter making the image black and white. The third 🖼️Composite pass then 🪇Posterizes (quantizes) the image into only a couple of tones/color bands and finally the dither filter dithers the noisy posterized grayscale image, which creates a really nice and fully 'quantized' retro look!
Because the 🌌Hyper feature can execute multiple 🖼️Composite passes per-feature, the 🎭Masks created for the 🖼️Composite shaders can also be reused within the same feature by multiple Composite pass shaders, which makes the 🌌Hyper feature very efficient for layered/stacked effects. For example when multiple 🔳Outlines are used that all require the 🟦Normals or ⬛Depth mask, then those masking passes only have to be executed once by the Renderer Feature.
Running multiple composite passes is not as efficient as merging multiple outlines and effects into one final 🖼️Composite shader but it gets very close and with the 🌌Hyper Renderer Feature multiple relatively simple 🖼️Composite shaders, that only have one responsibility each, can be combined into new hybrid effects of which the sum is greater than its parts.
📝 Notes :
- Because the first
🖼️Compositepass shader already gets a fresh camera color copy (if it uses the📸Texture2D_CameraOpaqueTextureproperty) theRequire Camera Color Copy Passbool gets ignored for the first🖼️Compositepass.
🏒 Render Pass Execution Order
The default Render Pass execution order of the 🧑🎨🧑🎨🧑🎨🧑🎨Outline3DRenderFeatureHyper is shown in the diagram below.
After the 🎭Mask Render Passes are done, the Outline3DRenderFeatureHyper executes all of the final full-screen 🖼️Composite passes, which render the final 🔳Outlines to the scene camera:
%%{init:{'flowchart':{'nodeSpacing': 16, 'rankSpacing': 32}}}%%
flowchart
direction LR
subgraph Outline3DRenderFeatureHyperRenderPasses[<div style="font-size:10px;">Render Pass Execution Order</div>]
direction TB
Outline3DRenderFeatureAdv(
🧑🎨🧑🎨🧑🎨🧑🎨🧑🎨Outline3DRenderFeatureHyper
)
OutlineColorMaskPass(
<div class="FlowChartNodeCard"><div class="Body"><div class="Header"><div class="Name"><b>OutlineColorMaskPass</b></div><div class="Icon">⬜</div></div><div class="Image"><img src='../../../../../images/articles/Systems/OutlineSystem/RenderPasses/OutlineColorMaskPass/CosterGraphics-Systems-OutlineSystem-OutlineColorTextureMask.jpg'/></div><div class="Description"><b>Requires Shader</b>:<br/><i>🎭 Outline3DSimple-Msk-ColorTextureMask-Default.shadergraph</i><br/><br/><b>Produces</b>:<br/>⬜Texture2D_OutlineColorTextureMask</div></div></div>
)
OutlineColorMaskDepthTestedPass(
<div class="FlowChartNodeCard"><div class="Body"><div class="Header"><div class="Name"><b>OutlineColorMaskDepthTestedPass</b></div><div class="Icon">🧱</div></div><div class="Image"><img src='../../../../../images/articles/Systems/OutlineSystem/RenderPasses/OutlineColorMaskDepthTestedPass/CosterGraphics-Systems-OutlineSystem-OutlineColorTextureMaskDepthTested.jpg'/></div><div class="Description"><b>Requires Shader</b>:<br/><i>🎭 Outline3DSimple-Msk-ColorTextureMaskDepthTested-Default.shadergraph</i><br/><br/><b>Produces</b>:<br/>🧱Texture2D_OutlineColorTextureMaskDepthTested</div></div></div>
)
OutlineCameraColorCopyPass(
<div class="FlowChartNodeCard"><div class="Body"><div class="Header"><div class="Name"><b>OutlineCameraColorCopyPass</b></div><div class="Icon">📸</div></div><div class="Image"><img src='../../../../../images/articles/Systems/OutlineSystem/RenderPasses/CameraColorCopyPass/CosterGraphics-Systems-OutlineSystem-CameraOpaqueTexture.jpg'/></div><div class="Description"><b>Requires Shader</b>:<br/><i>None</i><br/><br/><b>Produces</b>:<br/>📸Texture2D_CameraOpaqueTexture</div></div></div>
)
OutlineDepthMaskPass(
<div class="FlowChartNodeCard"><div class="Body"><div class="Header"><div class="Name"><b>OutlineDepthMaskPass</b></div><div class="Icon">⬛</div></div><div class="Image"><img src='../../../../../images/articles/Systems/OutlineSystem/RenderPasses/OutlineDepthMaskPass/CosterGraphics-Systems-OutlineSystem-OutlineDepthTextureMask.jpg'/></div><div class="Description"><b>Requires Shader</b>:<br/><i>🎭 Outline3DBasic-Msk-DepthTextureMask-Default.shadergraph</i><br/><br/><b>Produces</b>:<br/>⬛Texture2D_OutlineDepthTextureMask</div></div></div>
)
OutlineNormalsMaskPass(
<div class="FlowChartNodeCard"><div class="Body"><div class="Header"><div class="Name"><b>OutlineNormalsMaskPass</b></div><div class="Icon">🟦</div></div><div class="Image"><img src='../../../../../images/articles/Systems/OutlineSystem/RenderPasses/OutlineNormalsMaskPass/CosterGraphics-Systems-OutlineSystem-OutlineNormalsTextureMask.jpg'/></div><div class="Description"><b>Requires Shader</b>:<br/><i>🎭 Outline3DBasic-Msk-NormalsTextureMask-Default.shadergraph</i><br/><br/><b>Produces</b>:<br/>🟦Texture2D_OutlineNormalsTextureMask</div></div></div>
)
OutlineUVMaskPass(
<div class="FlowChartNodeCard"><div class="Body"><div class="Header"><div class="Name"><b>OutlineUVMaskPass</b></div><div class="Icon">🟩</div></div><div class="Image"><img src='../../../../../images/articles/Systems/OutlineSystem/RenderPasses/OutlineUVMaskPass/CosterGraphics-Systems-OutlineSystem-OutlineUVTextureMask.jpg'/></div><div class="Description"><b>Requires Shader</b>:<br/><i>🎭 Outline3DBasic-Msk-UVTextureMask-Default.shadergraph</i><br/><br/><b>Produces</b>:<br/>🟩Texture2D_OutlineUVTextureMask</div></div></div>
)
OutlineObjSpacePositionMaskPass(
<div class="FlowChartNodeCard"><div class="Body"><div class="Header"><div class="Name"><b>OutlineObjSpacePositionMaskPass</b></div><div class="Icon">🟧</div></div><div class="Image"><img src='../../../../../images/articles/Systems/OutlineSystem/RenderPasses/OutlineObjSpacePositionMaskPass/CosterGraphics-Systems-OutlineSystem-OutlineObjSpacePositionTextureMask.jpg'/></div><div class="Description"><b>Requires Shader</b>:<br/><i>🎭 Adv-Msk-ObjSpacePositionTextureMask-Default.shadergraph</i><br/><br/><b>Produces</b>:<br/>🟧Texture2D_OutlineObjSpacePositionTextureMask</div></div></div>
)
OutlineObjectIDMaskPass(
<div class="FlowChartNodeCard"><div class="Body"><div class="Header"><div class="Name"><b>OutlineObjectIDMaskPass</b></div><div class="Icon">🪪</div></div><div class="Image"><img src='../../../../../images/articles/Systems/OutlineSystem/RenderPasses/OutlineObjectIDMaskPass/CosterGraphics-Systems-OutlineSystem-OutlineObjectIDTextureMask.jpg'/></div><div class="Description"><b>Requires Shader</b>:<br/><i>🎭 Outline3DAdv-Msk-ObjectIDTextureMask-Default.shadergraph</i><br/><br/><b>Produces</b>:<br/>🪪Texture2D_OutlineObjectIDTextureMask</div></div></div>
)
OutlineJFAUVSeedsMaskPass_Outside(
<div class="FlowChartNodeCard"><div class="Body"><div class="Header"><div class="Name"><b>OutlineJFAUVSeedsMaskPass_Outside</b></div><div class="Icon">🌱🏞️</div></div><div class="Image"><img src='../../../../../images/articles/Systems/OutlineSystem/RenderPasses/OutlineJFAUVSeedsMaskPass_Outside/CosterGraphics-Systems-OutlineSystem-OutlineJFAUVSeedsTextureMask_Outside.jpg'/></div><div class="Image"><img src='../../../../../images/articles/Systems/OutlineSystem/RenderPasses/OutlineJFAUVSeedsMaskPass_Outside/CosterGraphics-Systems-OutlineSystem-OutlineJFAUVSeedsTextureMask_Outside-Depth.jpg'/></div><div class="Description"><b>Requires Shader</b>:<br/><i>🎭 Outline3DPro-Msk-JFA-UVSeedsTextureMask-Silhouette_Outside.shadergraph</i><br/><br/><b>Produces</b>:<br/>🌱🏞️Texture2D_OutlineJFAUVSeedsTextureMask_Outside</div></div></div>
)
OutlineJFAUVSeedsMaskCopyPass_Outside(
<div class="FlowChartNodeCard"><div class="Body"><div class="Header"><div class="Name"><b>OutlineJFAUVSeedsMaskCopyPass_Outside</b></div><div class="Icon">📋🌱🏞️</div></div><div class="Image"><img src='../../../../../images/articles/Systems/OutlineSystem/RenderPasses/OutlineJFAUVSeedsMaskPass_Outside/CosterGraphics-Systems-OutlineSystem-OutlineJFAUVSeedsTextureMask_Outside.jpg'/></div><div class="ImageCaption">The JFA UV seeds mask copy Render Pass creates a copy of the JFA UV seeds texture mask to be processed by the JFA loop Render Passes internally. Not used by the final Composite shaders directly. </div><div class="Description"><b>Requires Shader</b>:<br/><i>🔃 Outline3DPro-Intermediate-JFA-UV-CopyPass-Default.shadergraph</i><br/><br/><b>Produces</b>:<br/>📋🌱🏞️Texture2D_OutlineJFAUVPingTexture_Outside</div></div></div>
)
subgraph JFALoopOutside [🪣JFA Flood Fill Loop Outside]
OutlineJFAUVHorizontalJumpPass_Outside(
<div class="FlowChartNodeCard"><div class="Body"><div class="Header"><div class="Name"><b>OutlineJFAUVHorizontalJumpPass_Outside</b></div><div class="Icon">↔️🦘🏞️</div></div><div class="Image"><img src='../../../../../images/articles/Systems/OutlineSystem/RenderPasses/OutlineJFAUVHorizontalJumpPass_Outside/CosterGraphics-Systems-OutlineSystem-OutlineJFAUVJumpTextureMask_Outside.jpg'/></div><div class="Image"><img src='../../../../../images/articles/Systems/OutlineSystem/RenderPasses/OutlineJFAUVHorizontalJumpPass_Outside/CosterGraphics-Systems-OutlineSystem-OutlineJFAUVJumpTextureMask_Outside-Depth.jpg'/></div><div class="Description"><b>Requires Shader</b>:<br/><i>Outline3DPro-Intermediate-JFA-UV-JumpPassHorizontal-Default.shadergraph</i><br/><br/><b>Produces</b>:<br/>↔️🦘🏞️Texture2D_OutlineJFAUVJumpTextureMask_Outside</div></div></div>
)
OutlineJFAUVVerticalJumpPass_Outside(
<div class="FlowChartNodeCard"><div class="Body"><div class="Header"><div class="Name"><b>OutlineJFAUVVerticalJumpPass_Outside</b></div><div class="Icon">↕️🦘🏞️</div></div><div class="Image"><img src='../../../../../images/articles/Systems/OutlineSystem/RenderPasses/OutlineJFAUVVerticalJumpPass_Outside/CosterGraphics-Systems-OutlineSystem-OutlineJFAUVJumpTextureMask_Outside.jpg'/></div><div class="Image"><img src='../../../../../images/articles/Systems/OutlineSystem/RenderPasses/OutlineJFAUVHorizontalJumpPass_Outside/CosterGraphics-Systems-OutlineSystem-OutlineJFAUVJumpTextureMask_Outside-Depth.jpg'/></div><div class="Description"><b>Requires Shader</b>:<br/><i>Outline3DPro-Intermediate-JFA-UV-JumpPassVertical-Default.shadergraph</i><br/><br/><b>Produces</b>:<br/>↕️🦘🏞️Texture2D_OutlineJFAUVJumpTextureMask_Outside</div></div></div>
)
end
OutlineJFAUVSeedsMaskPass_Inside(
<div class="FlowChartNodeCard"><div class="Body"><div class="Header"><div class="Name"><b>OutlineJFAUVSeedsMaskPass_Inside</b></div><div class="Icon">🌱🏠</div></div><div class="Image"><img src='../../../../../images/articles/Systems/OutlineSystem/RenderPasses/OutlineJFAUVSeedsMaskPass_Inside/CosterGraphics-Systems-OutlineSystem-OutlineJFAUVSeedsTextureMask_Inside.jpg'/></div><div class="Description"><b>Requires Shader</b>:<br/><i>🎭 Outline3DPro-Msk-JFA-UVSeedsTextureMask-Silhouette_Inside.shadergraph</i><br/><br/><b>Produces</b>:<br/>🌱🏠Texture2D_OutlineJFAUVSeedsTextureMask_Inside</div></div></div>
)
OutlineJFAUVSeedsMaskCopyPass_Inside(
<div class="FlowChartNodeCard"><div class="Body"><div class="Header"><div class="Name"><b>OutlineJFAUVSeedsMaskCopyPass_Inside</b></div><div class="Icon">📋🌱🏠</div></div><div class="Image"><img src='../../../../../images/articles/Systems/OutlineSystem/RenderPasses/OutlineJFAUVSeedsMaskPass_Inside/CosterGraphics-Systems-OutlineSystem-OutlineJFAUVSeedsTextureMask_Inside.jpg'/></div><div class="ImageCaption">The JFA UV seeds mask copy Render Pass creates a copy of the JFA UV seeds texture mask to be processed by the JFA loop Render Passes internally. Not used by the final Composite shaders directly. </div><div class="Description"><b>Requires Shader</b>:<br/><i>🔃 Outline3DPro-Intermediate-JFA-UV-CopyPass-Default.shadergraph</i><br/><br/><b>Produces</b>:<br/>📋🌱🏠Texture2D_OutlineJFAPingTexture_Inside</div></div></div>
)
subgraph JFALoopInside[🪣JFA Flood Fill Loop Inside]
OutlineJFAUVHorizontalJumpPass_Inside(
<div class="FlowChartNodeCard"><div class="Body"><div class="Header"><div class="Name"><b>OutlineJFAUVHorizontalJumpPass_Inside</b></div><div class="Icon">↔️🦘🏠</div></div><div class="Image"><img src='../../../../../images/articles/Systems/OutlineSystem/RenderPasses/OutlineJFAUVHorizontalJumpPass_Inside/CosterGraphics-Systems-OutlineSystem-OutlineJFAUVJumpTextureMask_Inside.jpg'/></div><div class="Description"><b>Requires Shader</b>:<br/><i>Outline3DPro-Intermediate-JFA-UV-JumpPassHorizontal-Default.shadergraph</i><br/><br/><b>Produces</b>:<br/>↔️🦘🏠Texture2D_OutlineJFAUVJumpTextureMask_Inside</div></div></div>
)
OutlineJFAUVVerticalJumpPass_Inside(
<div class="FlowChartNodeCard"><div class="Body"><div class="Header"><div class="Name"><b>OutlineJFAUVVerticalJumpPass_Inside</b></div><div class="Icon">↕️🦘🏠</div></div><div class="Image"><img src='../../../../../images/articles/Systems/OutlineSystem/RenderPasses/OutlineJFAUVVerticalJumpPass_Inside/CosterGraphics-Systems-OutlineSystem-OutlineJFAUVJumpTextureMask_Inside.jpg'/></div><div class="Description"><b>Requires Shader</b>:<br/><i>Outline3DPro-Intermediate-JFA-UV-JumpPassVertical-Default.shadergraph</i><br/><br/><b>Produces</b>:<br/>↕️🦘🏠Texture2D_OutlineJFAUVJumpTextureMask_Inside</div></div></div>
)
end
OutlineCompositePass(
<div class="FlowChartNodeCard"><div class="Body"><div class="Header"><div class="Name"><b>OutlineCompositePass</b></div><div class="Icon">🖼️</div></div><div class="Image"><img src='../../../../../images/articles/Systems/OutlineSystem/RenderPasses/OutlineCompositePass/CosterGraphics-Systems-OutlineSystem-OutlineJFA-UVDistanceField_Outside&Inside.jpg'/></div><div class="ImageCaption">Signed Distance Field generated from the JFA UV Voronoi Field</div><div class="Image"><img src='../../../../../images/articles/Systems/OutlineSystem/RenderPasses/OutlineCompositePass/CosterGraphics-Systems-OutlineSystem-Outline3DPro-Cmp-Slhtt-JFA-UVSignedDistanceField-Default-1.jpg'/></div><div class="ImageCaption">Outlines generated from the Signed Distance Field colored red on the inside and green on the outside with a black background.</div><div class="Description"><b>Requires Shader</b>:<br/><i>Outline3DPro-Cmp-Silhouette-JFA-UVSignedDistanceField-Default.shadergraph</i><br/>(Or any other Pro or lower tier <em>Composite</em> shader)<br/><br/><b>Produces</b>:<br/>🖼️The final composite image</div></div></div>
)
end
subgraph Output[Output]
Out(
<div class="FlowChartNodeCard"><div class="Body"><div class="Header"><div class="Name"><b>Camera Color Buffer</b></div><div class="Icon">🎥</div></div><div class="Image"><img src='../../../../../images/articles/Systems/OutlineSystem/RenderPasses/OutlineCompositePass/CosterGraphics-Systems-OutlineSystem-Outline3DPro-Cmp-Slhtt-JFA-UVSignedDistanceField-Default-2.jpg'/></div><br/><div class="ImageCaption">The final Signed Distance Field outlines generated by the Outline3DRenderFeaturePro's Jump Flood Algorithm composited to the screen, with a sharp thick white outline on the outside of the Outline3Ds and a soft black outline in the inside.</div></div></div>
)
end
Outline3DRenderFeatureAdv
-->
OutlineColorMaskPass
-->
OutlineColorMaskDepthTestedPass
-->
OutlineCameraColorCopyPass
-->
OutlineDepthMaskPass
-->
OutlineNormalsMaskPass
-->
OutlineUVMaskPass
-->
OutlineObjSpacePositionMaskPass
-->
OutlineObjectIDMaskPass
--->
OutlineJFAUVSeedsMaskPass_Outside
-->
OutlineJFAUVSeedsMaskCopyPass_Outside
OutlineJFAUVSeedsMaskCopyPass_Outside
-->
JFALoopOutside
OutlineJFAUVHorizontalJumpPass_Outside
-->
OutlineJFAUVVerticalJumpPass_Outside
OutlineJFAUVVerticalJumpPass_Outside
-->
OutlineJFAUVHorizontalJumpPass_Outside
JFALoopOutside
-->
OutlineJFAUVSeedsMaskPass_Inside
OutlineJFAUVSeedsMaskPass_Inside
-->
OutlineJFAUVSeedsMaskCopyPass_Inside
OutlineJFAUVSeedsMaskCopyPass_Inside
-->
JFALoopInside
OutlineJFAUVHorizontalJumpPass_Inside
-->
OutlineJFAUVVerticalJumpPass_Inside
OutlineJFAUVVerticalJumpPass_Inside
-->
OutlineJFAUVHorizontalJumpPass_Inside
JFALoopInside
-->
OutlineCompositePass
OutlineCompositePass
===>
Out
style Outline3DRenderFeatureHyperRenderPasses stroke-dasharray: 10 10, stroke-width: 2px;
classDef default padding:0, margin:0, font-size:8px;
style JFALoopOutside font-size: 10px;
style JFALoopInside font-size: 10px;
style Outline3DRenderFeatureAdv fill:#109999
style OutlineColorMaskPass
style OutlineColorMaskDepthTestedPass
style OutlineCameraColorCopyPass
style OutlineCompositePass fill:#501099
style Output stroke-dasharray: 10 10, stroke-width:2px;
style Out fill:#109999;