using Sandbox.Rendering;
namespace Sandbox;
///
/// This should be added to a camera that you want to outline stuff
///
[Title( "Highlight" )]
[Category( "Post Processing" )]
[Icon( "lightbulb_outline" )]
public sealed class Highlight : BasePostProcess
{
CommandList commands = new();
public override void Render()
{
var outlines = Scene.GetAll();
if ( !outlines.Any() ) return;
commands.Reset();
// Copy the depth buffer once
commands.Attributes.GrabFrameTexture( "ColorTexture" );
// Generate a temporary render target to draw the stencil to, also so we don't clash with the main depth buffer
var rt = commands.GetRenderTarget( "Highlight", 1, ImageFormat.None, ImageFormat.D24S8, msaa: MultisampleAmount.MultisampleScreen );
commands.SetRenderTarget( rt );
commands.Clear( Color.Black, false, true, true );
// Draw the stencil first before drawing the outside outline
foreach ( var glow in outlines ) { DrawGlow( commands, glow, OutlinePass.Inside ); }
foreach ( var glow in outlines ) { DrawGlow( commands, glow, OutlinePass.Outside ); }
commands.ClearRenderTarget();
InsertCommandList( commands, Stage.AfterTransparent, 1000, "Highlight" );
}
enum OutlinePass
{
Inside,
Outside,
}
private void DrawGlow( CommandList commands, HighlightOutline glow, OutlinePass pass )
{
var attributes = commands.Attributes;
foreach ( var model in glow.GetOutlineTargets() )
{
var shapeMat = glow.Material ?? Material.FromShader( "postprocess/objecthighlight/objecthighlight.shader" );
// Inside glow and stencil
if ( pass == OutlinePass.Inside )
{
attributes.SetCombo( "D_OUTLINE_PASS", (int)OutlinePass.Inside );
attributes.Set( "Color", glow.InsideColor );
attributes.Set( "ObscuredColor", glow.InsideObscuredColor );
commands.DrawRenderer( model, new RendererSetup { Material = shapeMat } );
}
// Outside glow
if ( glow.Width > 0.0f && pass == OutlinePass.Outside && (glow.Color != Color.Transparent || glow.ObscuredColor != Color.Transparent) )
{
attributes.SetCombo( "D_OUTLINE_PASS", (int)OutlinePass.Outside );
attributes.Set( "Color", glow.Color );
attributes.Set( "ObscuredColor", glow.ObscuredColor );
attributes.Set( "LineWidth", glow.Width );
commands.DrawRenderer( model, new RendererSetup { Material = shapeMat } );
}
}
}
}