Files
sbox-public/engine/Sandbox.Engine/Systems/Render/RenderPipeline/RenderLayer.cs
s&box team 71f266059a Open source release
This commit imports the C# engine code and game files, excluding C++ source code.

[Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
2025-11-24 09:05:18 +00:00

108 lines
3.2 KiB
C#

using NativeEngine;
using System.Collections.Concurrent;
using System.Runtime.InteropServices;
namespace Sandbox.Rendering;
/// <summary>
/// ISceneLayer which is basically a render pass
/// </summary>
/// <remarks>Maybe we just call this RenderPass like every other engine.</remarks>
internal abstract class RenderLayer
{
public string Name { get; set; }
public LayerFlags Flags { get; set; }
public SceneLayerType LayerType { get; set; }
public ClearFlags ClearFlags { get; set; }
public Color ClearColor { get; set; }
/// <summary>
/// Renders all matching scene objects with this shader mode if applicable
/// </summary>
public StringToken ShaderMode { get; set; }
/// <summary>
/// Scene objects must have these flags to be included in the layer
/// </summary>
public SceneObjectFlags ObjectFlagsRequired { get; set; }
/// <summary>
/// Scene objects with these flags will be excluded from the layer
/// </summary>
public SceneObjectFlags ObjectFlagsExcluded { get; set; }
public SceneViewRenderTargetHandle ColorAttachment { get; set; } = -1;
public SceneViewRenderTargetHandle DepthAttachment { get; set; } = -1;
public RenderAttributes Attributes { get; set; } = new();
/// <summary>
/// Deferred render target attributes
/// </summary>
public Dictionary<StringToken, SceneViewRenderTargetHandle> RenderTargetAttributes { get; set; } = new();
/// <summary>
/// Add to view
/// </summary>
/// <remarks>Passing viewport here might not be what we want</remarks>
public ISceneLayer AddToView( ISceneView view, RenderViewport viewport )
{
ISceneLayer nativeLayer;
if ( this is ProceduralRenderLayer proceduralRenderLayer )
{
proceduralRenderLayer.ProceduralCallback = DelegateFunctionPointer.Get<ProceduralRenderLayer.OnRenderCallback>( proceduralRenderLayer.Internal_OnRender );
nativeLayer = view.AddManagedProceduralLayer( Name, viewport, proceduralRenderLayer.ProceduralCallback, IntPtr.Zero, true );
}
else
{
nativeLayer = view.AddRenderLayer( Name, viewport, ShaderMode, IntPtr.Zero );
}
nativeLayer.LayerEnum = LayerType;
nativeLayer.m_nLayerFlags = Flags;
nativeLayer.SetOutput( ColorAttachment, DepthAttachment );
nativeLayer.AddObjectFlagsRequiredMask( ObjectFlagsRequired );
nativeLayer.AddObjectFlagsExcludedMask( ObjectFlagsExcluded );
nativeLayer.SetClearColor( new Vector4( ClearColor ), 0 );
nativeLayer.m_nClearFlags = (int)ClearFlags;
Attributes.Get().MergeToPtr( nativeLayer.GetRenderAttributesPtr() );
foreach ( var attr in RenderTargetAttributes )
{
nativeLayer.SetAttr( attr.Key, attr.Value, SceneLayerMSAAMode_t.On, 1 /* SL_RENDER_TARGET_INPUT */ );
}
return nativeLayer;
}
}
/// <summary>
/// A render layer with a callback
/// </summary>
internal abstract class ProceduralRenderLayer : RenderLayer
{
[UnmanagedFunctionPointer( CallingConvention.StdCall )]
internal delegate void OnRenderCallback( ManagedRenderSetup_t setup );
// If we're a procedural layer, keep the delegate callback so GC doesn't eat us
internal DelegateFunctionPointer ProceduralCallback;
internal void Internal_OnRender( ManagedRenderSetup_t setup )
{
using var _ = new Graphics.Scope( in setup );
OnRender();
}
internal virtual void OnRender()
{
}
}