mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-08-01 00:08:05 -04:00
* Screen space shadows * Pass screenspace shadow to directional light * Simplify screenspaceshadows * cleanup, format * Guard against compositing screenspace shadows to translucent or compute * Add validity check for ShadowMaskTextureIndex getter and setter * Add Screen Space Shadows to dependency index * Remove debug shader for screen space shadows * No need for this, access directly from scenecamera * Dont heap alloc Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Dont heap alloc here either Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * move stackalloc out of the loop * Rename license file * Implicitly add screen space shadows component to directional light, make SSS component hidden until supported in local lights * Update shaders * Move ScreenSpaceShadows from a component to just a class driven by directionallight * ScreenSpaceShadows class internal, we don't want to expose any of this to the public. --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
248 lines
5.7 KiB
C#
248 lines
5.7 KiB
C#
using NativeEngine;
|
|
|
|
namespace Sandbox;
|
|
|
|
/// <summary>
|
|
/// Base class for light scene objects for use with a <see cref="SceneWorld"/>.
|
|
/// </summary>
|
|
[Expose]
|
|
public class SceneLight : SceneObject
|
|
{
|
|
internal CSceneLightObject lightNative;
|
|
|
|
internal SceneLight() { }
|
|
internal SceneLight( HandleCreationData _ ) { }
|
|
|
|
/// <summary>
|
|
/// Color and brightness of the light
|
|
/// </summary>
|
|
public Color LightColor
|
|
{
|
|
get { return lightNative.GetColor(); }
|
|
set { lightNative.SetColor( value ); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Radius of the light in units
|
|
/// </summary>
|
|
public float Radius
|
|
{
|
|
get { return lightNative.GetRadius(); }
|
|
set
|
|
{
|
|
if ( Radius == value ) return;
|
|
lightNative.SetRadius( value );
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The light attenuation constant term
|
|
/// </summary>
|
|
public float ConstantAttenuation
|
|
{
|
|
get { return lightNative.GetConstantAttn(); }
|
|
set { lightNative.SetConstantAttn( value ); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The light attenuation linear term
|
|
/// </summary>
|
|
public float LinearAttenuation
|
|
{
|
|
get { return lightNative.GetLinearAttn(); }
|
|
set { lightNative.SetLinearAttn( value ); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The light attenuation quadratic term
|
|
/// </summary>
|
|
public float QuadraticAttenuation
|
|
{
|
|
// Note: to make these numbers sane I'm doing some calculation here
|
|
get { return lightNative.GetQuadraticAttn() * 10000.0f; }
|
|
set { lightNative.SetQuadraticAttn( value / 10000.0f ); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get or set the resolution of the shadow map. If this is zero the engine will decide what it should use.
|
|
/// </summary>
|
|
public int ShadowTextureResolution
|
|
{
|
|
get { return lightNative.GetShadowTextureResolution(); }
|
|
set { lightNative.SetShadowTextureResolution( value ); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enable or disable shadow rendering
|
|
/// </summary>
|
|
public bool ShadowsEnabled
|
|
{
|
|
get { return lightNative.GetShadows(); }
|
|
set { lightNative.SetShadows( value ); }
|
|
}
|
|
|
|
private Texture _lightCookie;
|
|
|
|
/// <summary>
|
|
/// Access the LightCookie - which is a texture that gets drawn over the light
|
|
/// </summary>
|
|
public Texture LightCookie
|
|
{
|
|
get => _lightCookie ??= Texture.FromNative( lightNative.GetLightCookie() );
|
|
set
|
|
{
|
|
_lightCookie = value;
|
|
lightNative.SetLightCookie( value == null ? default : value.native );
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Should this light contribute diffuse lighting?
|
|
/// </summary>
|
|
public bool RenderDiffuse
|
|
{
|
|
get => _renderDiffuse;
|
|
set
|
|
{
|
|
_renderDiffuse = value;
|
|
lightNative.SetRenderDiffuse( value );
|
|
}
|
|
}
|
|
private bool _renderDiffuse = true;
|
|
|
|
/// <summary>
|
|
/// Should this light contribute specular highlights?
|
|
/// </summary>
|
|
public bool RenderSpecular
|
|
{
|
|
get => _renderSpecular;
|
|
set
|
|
{
|
|
_renderSpecular = value;
|
|
lightNative.SetRenderSpecular( value );
|
|
}
|
|
}
|
|
private bool _renderSpecular = true;
|
|
|
|
/// <summary>
|
|
/// Should this light contribute transmissive lighting (light passing through surfaces)?
|
|
/// </summary>
|
|
public bool RenderTransmissive
|
|
{
|
|
get => _renderTransmissive;
|
|
set
|
|
{
|
|
_renderTransmissive = value;
|
|
lightNative.SetRenderTransmissive( value );
|
|
}
|
|
}
|
|
private bool _renderTransmissive = true;
|
|
|
|
public enum FogLightingMode
|
|
{
|
|
None,
|
|
Baked,
|
|
Dynamic,
|
|
DynamicNoShadows
|
|
}
|
|
|
|
public enum LightShape
|
|
{
|
|
Sphere,
|
|
Capsule,
|
|
Rectangle
|
|
}
|
|
|
|
public LightShape Shape
|
|
{
|
|
get => (LightShape)lightNative.GetLightShape();
|
|
set => lightNative.SetLightShape( (LightSourceShape_t)value );
|
|
}
|
|
|
|
public Vector2 ShapeSize
|
|
{
|
|
set
|
|
{
|
|
lightNative.SetLightSourceDim0( value.x );
|
|
lightNative.SetLightSourceDim1( value.y );
|
|
}
|
|
}
|
|
|
|
public FogLightingMode FogLighting
|
|
{
|
|
get => (FogLightingMode)lightNative.GetFogLightingMode();
|
|
set => lightNative.SetFogLightingMode( (int)value );
|
|
}
|
|
|
|
public float FogStrength
|
|
{
|
|
get => lightNative.GetFogContributionStength();
|
|
set => lightNative.SetFogContributionStength( value );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stupid fucking shit
|
|
/// </summary>
|
|
internal Vector3 WorldDirection => lightNative.GetWorldDirection();
|
|
|
|
public float ShadowBias { get; set; } = 0.0005f;
|
|
|
|
public float ShadowHardness { get; set; } = 0.0f;
|
|
|
|
/// <summary>
|
|
/// Bindless indices of the screen-space shadow masks for this light, keyed by managed camera id
|
|
/// (masks are generated per rendering view). Written from threaded procedural-layer jobs while
|
|
/// other views' light binning reads it, hence the concurrent dictionary.
|
|
/// </summary>
|
|
internal readonly System.Collections.Concurrent.ConcurrentDictionary<int, uint> ShadowMaskTextureIndices = new();
|
|
|
|
internal override void OnTransformChanged( in Transform tx )
|
|
{
|
|
base.OnTransformChanged( tx );
|
|
|
|
lightNative.SetWorldDirection( tx.Rotation );
|
|
lightNative.SetWorldPosition( tx.Position );
|
|
}
|
|
|
|
[Obsolete( "Use ScenePointLight (or stop fucking using SceneObjects at all)" )]
|
|
public SceneLight( SceneWorld sceneWorld, Vector3 position, float radius, Color color )
|
|
{
|
|
Assert.IsValid( sceneWorld );
|
|
|
|
using ( var h = IHandle.MakeNextHandle( this ) )
|
|
{
|
|
CSceneSystem.CreatePointLight( sceneWorld );
|
|
}
|
|
|
|
Position = position;
|
|
Radius = radius;
|
|
LightColor = color;
|
|
QuadraticAttenuation = 1.0f;
|
|
}
|
|
|
|
[Obsolete( "Use ScenePointLight (or stop fucking using SceneObjects at all)" )]
|
|
public SceneLight( SceneWorld sceneWorld ) : this( sceneWorld, Vector3.Zero, 100, Color.White * 10.0f )
|
|
{
|
|
|
|
}
|
|
|
|
internal override void OnNativeInit( CSceneObject ptr )
|
|
{
|
|
base.OnNativeInit( ptr );
|
|
|
|
lightNative = (CSceneLightObject)ptr;
|
|
}
|
|
|
|
internal override void OnNativeDestroy()
|
|
{
|
|
// Return any cached shadow map to the pool before this object becomes
|
|
// eligible for GC. Without this the ConditionalWeakTable silently drops
|
|
// the entry on collection and the shadow texture is orphaned.
|
|
Rendering.ShadowMapper.OnLightRemoved( this );
|
|
|
|
lightNative = IntPtr.Zero;
|
|
|
|
base.OnNativeDestroy();
|
|
}
|
|
}
|