ScreenEffects/ScreenFogEffect.cs

A post-process effect component that applies depth-based screen-space fog. It sets shader parameters (color, min/max distance, opacity), grabs the current frame and depth textures, and issues a command list to run the shaders after transparent geometry.

Native Interop
using Sandbox;
using Sandbox.Rendering;

namespace BrickJam;

/// <summary>
/// Depth-based screen-space fog. Scene-System port of the legacy <c>ScreenFogEffect : RenderHook</c>.
/// Uses the same unchanged <c>shaders/screenfog_postprocess.shader</c> and its
/// <c>Color</c>/<c>MinDistance</c>/<c>MaxDistance</c>/<c>Opacity</c> attributes plus the grabbed
/// <c>"FrameTexture"</c>/<c>"DepthTexture"</c>. The legacy ran <c>Graphics.Grab*Texture + Graphics.Blit</c>
/// at <c>Stage.AfterTransparent</c>; here we build the same command list and insert it.
/// </summary>
[Title( "Screen Fog" )]
[Category( "Post Processing" )]
[Icon( "foggy" )]
public sealed class ScreenFogEffect : BasePostProcess<ScreenFogEffect>
{
	[Property] public Color Color { get; set; } = new Color( 0.5f, 0.5f, 0.5f, 1f );
	[Property] public float MinimumDistance { get; set; } = 80f;
	[Property] public float MaximumDistance { get; set; } = 7000f;
	[Property, Range( 0, 1 )] public float MaxOpacity { get; set; } = 0.6f;

	private static readonly Material Shader = Material.FromShader( "shaders/screenfog_postprocess.shader" );

	public override void Render()
	{
		if ( !Shader.IsValid() )
			return;

		var cl = new CommandList( "ScreenFog" );

		// Custom shader parameters go on the material attributes...
		Attributes.Set( "Color", GetWeighted( x => x.Color, Color ) );
		Attributes.Set( "MinDistance", GetWeighted( x => x.MinimumDistance, MinimumDistance ) );
		Attributes.Set( "MaxDistance", GetWeighted( x => x.MaximumDistance, MaximumDistance ) );
		Attributes.Set( "Opacity", GetWeighted( x => x.MaxOpacity, MaxOpacity ) );

		// ...the grabbed frame/depth textures go on the command list.
		cl.Attributes.GrabFrameTexture( "FrameTexture" );
		cl.Attributes.GrabDepthTexture( "DepthTexture" );
		cl.Blit( Shader, Attributes );

		InsertCommandList( cl, Stage.AfterTransparent, 100, "ScreenFog" );
	}
}