mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-04-19 13:59:22 -04:00
* Shadows Rewrite: C#, bindless, flexible, quality options, less VRAM... Introduces a new shadow mapper written entirely in C#, as well as rewritten shader code for sampling shadow maps. This fully removes and replaces Source 2's native shadow mapping giving us greater flexibility and allowing us to open-source it all. The main goal for the new shadow mapper is greater flexibility whilst reducing complexity. Older shaders are incompatible with the new lighting buffers, and will need to be recompiled to receive lighting properly. What's new: - Bindless per-light shadow maps instead of a shared shadow atlas — this means games can avoid the shadow atlas cost if not using many shadows, but also allows games with many shadows to not be limited by atlas space. - Directional lights have developer configurable cascade count (1-4) and control over split ratio (logarithmic/uniform blend via lambda parameter), useful for games where you may not need multiple cascades. User quality settings define a maximum cascade count which always overrides developer settings, allowing low end hardware to use fewer. - Directional lights have a dedicated cbuffer and uniform fast path in rendering code, and are no longer binned and looped over with local lights. Every pixel on screen is always affected by a directional light. - CSM cascade selection uses bounding spheres instead of depth comparison, with per-cascade texel snapping to eliminate sub-texel shimmer. - Point lights use a TextureCube for cube shadows for much simpler rendering and mapping, along with hardware PCF filtering. - Local light shadow resolution is derived from each light's screen-space size. Shadows below a configurable threshold are not rendered at all. Lights are sorted by screen size, and r.shadows.max caps the total count, culling least important lights first. - User settings have been added for shadow quality (Low/Medium/High) controlling max resolution, max cascades, and PCF filter quality. - Local light shadow maps use D16 depth format, halving memory compared to D32. CSMs remain D32 for precision at large distances. (Although this could be a TODO, I bet we could make it work in D16) - ShadowHardness: New per-light property controlling shadow sharpness. Defaults to soft (0.0) and scales up to 4x sharper. For directional lights, hardness is automatically scaled per cascade proportional to texel density (wider cascades get softer shadows), and clamped so the filter never exceeds a full texel — ensuring consistent softness across cascade transitions. - Shadow debug overlay showing all information about allocated shadow maps, their textures, cascades and more. - Many new convars to control - r.shadows.max: Maximum number of shadow-casting local lights, sorted by screen size, least important culled first - r.shadows.maxresolution: Max texture size for a projected light shadow map (128–4096) - r.shadows.quality: Shadow filter quality (0=Off, 1=Low, 2=Med, 3=High, 4=Experimental Penumbra) - r.shadows.csm.maxcascades: Maximum number of cascades for directional light shadows (1–4) - r.shadows.csm.maxresolution: Maximum resolution for each cascade shadow map (512–8192) - r.shadows.csm.distance: Maximum distance from camera that directional light shadows render (500–50000) - r.shadows.debug: Show shadow debug overlay with CSM textures, cascade bounds, and memory budget - r.shadows.csm.enabled: Enable or disable directional light (CSM) shadows - r.shadows.local.enabled: Enable or disable local light (spot/point) shadows - r.shadows.depthbias: Rasterizer constant depth bias during shadow map rendering - r.shadows.slopescale: Rasterizer slope-scaled depth bias during shadow map rendering - r.shadows.size_cull_threshold: Screen size percentage below which local light shadows are culled - SceneLight refactored into a base class with ScenePointLight, SceneSpotLight, SceneDirectionalLight. SceneOrthoLight removed. - Simplified Light.hlsl: Light is now a class, DynamicLight merged into Light, ProbeLight and LightmappedLight no longer inherit from DynamicLight. - GPULight/BinnedLight struct reorganized and trimmed: explicit typed fields instead of packed uint4 Params, shadow data replaced with a shadow index into a separate StructuredBuffer, removed embedded shadow matrices and atlas bounds. - ViewLightingConfig cleaned up: removed ViewLightingFlags, Shadow3x3PCFConstants, EnvironmentMapSizeConstants, LegacyAmbientLightColor. - Baked light mode flags fixed: BAKED lights (lightmaps only) no longer create shadow maps. MIXED_SHADOWS gated to Stationary lights only (was unconditionally applied). RENDER_ALL_GEOMETRY flag removed. DirectLightMode enum documented across Hammer entity definitions. - Removed light cookie sheets; cookie UV derived from light transform (LightToWorld transpose). Cookie sampling simplified to a single bindless texture lookup.
207 lines
7.6 KiB
Modula-2
207 lines
7.6 KiB
Modula-2
|
|
#include "scenesystem/iscenesystem.h"
|
|
|
|
native enum SceneSystemRenderTargetSize_t as NativeEngine.SceneSystemRenderTargetSize;
|
|
native enum SceneSystemWellKnownMaterialObjectID_t as NativeEngine.SceneSystemWellKnownMaterialObjectID;
|
|
native enum SceneSystemWellKnownTextureObjectID_t as NativeEngine.SceneSystemWellKnownTextureObjectID;
|
|
|
|
native struct SceneVolumetricFogVolume_t is NativeEngine.SceneVolumetricFogVolume;
|
|
|
|
native enum SceneSystemGPUProfilerMode_t as NativeEngine.SceneSystemGPUProfilerMode;
|
|
|
|
native class SceneSystemPerFrameStats_t
|
|
{
|
|
uint m_nTrianglesRendered;
|
|
uint m_nArtistTrianglesRendered;
|
|
uint m_nRenderBatchDraws;
|
|
uint m_nDrawCalls;
|
|
uint m_nDrawPrimitives;
|
|
uint m_nBaseSceneObjectPrimDraws;
|
|
uint m_nAnimatableObjectPrimDraws;
|
|
uint m_nAggregateSceneObjectPrimDraws;
|
|
uint m_nAggregateSceneObjectsFullyCulled;
|
|
uint m_nAggregateSceneObjectDrawCalls;
|
|
uint m_nNumMaterialCompute;
|
|
uint m_nNumMaterialSet;
|
|
uint m_nNumSimilarMaterialSet;
|
|
uint m_nNumTextureOnlyMaterialSet;
|
|
uint m_nNumVfxEval;
|
|
uint m_nNumVfxRule;
|
|
uint m_nNumConstantBufferUpdates;
|
|
uint m_nNumConstantBufferBytes;
|
|
uint m_nMaterialChangesNonShadow;
|
|
uint m_nMaterialChangesNonShadowInitial;
|
|
uint m_nMaterialChangesShadow;
|
|
uint m_nMaterialChangesShadowInitial;
|
|
uint m_nMaterialChangesShadowAlphaTested;
|
|
uint m_nCopyMaterialChangesNonShadow;
|
|
uint m_nMaxTransformRow;
|
|
uint m_nNumRowsUsed;
|
|
uint m_nNumObjectsTested;
|
|
uint m_nNumObjectsPreCullCheck;
|
|
uint m_nNumObjectsPassingCullCheck;
|
|
uint m_nNumVerticesReferenced;
|
|
uint m_nNumPrimaryContexts;
|
|
uint m_nNumSecondaryContexts;
|
|
uint m_nNumDisplayListsSubmitted;
|
|
int m_nNumViewsRendered;
|
|
uint m_nNumResolves;
|
|
uint m_nNumCullBoxes;
|
|
ulong m_nCullingBoxCycleCount;
|
|
uint m_nNumObjectsTestedAgainstCullingBoxes;
|
|
uint m_nNumObjectsRejectedByBoundsIndex;
|
|
uint m_nNumObjectsRejectedByCullBoxes;
|
|
uint m_nNumObjectsRejectedByVis;
|
|
uint m_nNumObjectsRejectedByBackfaceCulling;
|
|
uint m_nNumObjectsRejectedByScreenSizeCulling;
|
|
uint m_nNumObjectsRejectedByFading;
|
|
uint m_nNumFadingObjects;
|
|
uint m_nNumUniqueMaterialsSeen;
|
|
uint m_nNumUnshadowedLightsInView;
|
|
uint m_nNumShadowedLightsInView;
|
|
uint m_nNumShadowMaps;
|
|
uint m_nNumRenderTargetBinds;
|
|
uint m_nPushConstantSets;
|
|
}
|
|
|
|
native accessor g_pSceneSystem as NativeEngine.CSceneSystem
|
|
{
|
|
void DeleteSceneObject( CSceneObject pObj );
|
|
void DeleteSceneObjectAtFrameEnd( CSceneObject pObj );
|
|
|
|
CSceneSkyBoxObject CreateSkyBox( IMaterial skyMaterial, ISceneWorld world );
|
|
CDecalSceneObject CreateDecal( ISceneWorld world );
|
|
|
|
void BeginRenderingDynamicView( ISceneView pView );
|
|
//ISceneView AddDynamicView( string pszDebugName, ISceneView pParentView, CFrustum frustum, void* hSwapChain, ISceneWorld pWorld, RenderViewport mainViewport, void* pVis, int nPriority, int nViewProducerIndex );
|
|
|
|
ISceneView AddShadowView( string debugName, ISceneView pParentView, CFrustum frustum, RenderViewport_t mainViewport, ITexture rt, int rtIdx, ESceneObjectFlags requiredFlags, ESceneObjectFlags excludedFlags, int depthBias, float slopeScaledDepthBias );
|
|
ITexture GetWellKnownTexture( SceneSystemWellKnownTextureObjectID a );
|
|
IMaterial GetWellKnownMaterialHandle( SceneSystemWellKnownMaterialObjectID a );
|
|
|
|
inline SceneSystemPerFrameStats_t GetPerFrameStats()
|
|
{
|
|
return &(g_pSceneSystem->GetPerFrameStats());
|
|
}
|
|
|
|
ISceneWorld CreateWorld( string debugName );
|
|
void DestroyWorld( ISceneWorld world );
|
|
|
|
void PerformEndOfFrameDeletes();
|
|
|
|
inline void SetupPerObjectLighting( CRenderAttributes renderAttributes, CSceneObject pSceneObject, ISceneLayer pSceneLayerInterface )
|
|
{
|
|
g_pSceneSystem->SetupPerObjectLighting( *renderAttributes, pSceneObject, pSceneLayerInterface );
|
|
}
|
|
|
|
inline CSceneLightObject CreatePointLight( ISceneWorld pWorld )
|
|
{
|
|
LightDesc_t desc;
|
|
desc.Clear();
|
|
desc.InitPoint( vec3_origin, Vector( 100, 0, 100 ) );
|
|
desc.m_Attenuation0 = 0; // if this is 1 then the light has no falloff
|
|
return g_pSceneSystem->CreateLight( desc, pWorld, false );
|
|
}
|
|
|
|
inline CSceneLightObject CreateSpotLight( ISceneWorld pWorld )
|
|
{
|
|
LightDesc_t desc;
|
|
desc.Clear();
|
|
desc.InitSpot( vec3_origin, Vector( 100, 0, 100 ), Vector( 10, 0, 0 ), 15, 30 );
|
|
desc.m_Attenuation0 = 0; // if this is 1 then the light has no falloff
|
|
return g_pSceneSystem->CreateLight( desc, pWorld, false );
|
|
}
|
|
|
|
inline CSceneLightObject CreateOrthoLight( ISceneWorld pWorld )
|
|
{
|
|
LightDesc_t desc;
|
|
desc.Clear();
|
|
desc.m_Type = MATERIAL_LIGHT_ORTHO;
|
|
desc.RecalculateDerivedValues();
|
|
return g_pSceneSystem->CreateLight( desc, pWorld, false );
|
|
}
|
|
|
|
inline CSceneLightObject CreateDirectionalLight( ISceneWorld pWorld, Vector3 direction )
|
|
{
|
|
LightDesc_t desc;
|
|
desc.Clear();
|
|
desc.InitDirectional( direction, Vector( 100, 0, 100 ) );
|
|
desc.m_nShadowCascadeCount = 3;
|
|
|
|
return g_pSceneSystem->CreateLight( desc, pWorld, false );
|
|
}
|
|
|
|
inline CSceneLightObject CreateEnvMap( ISceneWorld pWorld, int nProjectionMode )
|
|
{
|
|
LightDesc_t desc;
|
|
desc.InitEnvironmentProbe( vec3_origin, 512 );
|
|
desc.m_nEnvProbeId = 0;
|
|
desc.RecalculateDerivedValues();
|
|
CEnvMapSceneObject* pSceneObject = ( CEnvMapSceneObject* )g_pSceneSystem->CreateLight( desc, pWorld, false );
|
|
pSceneObject->m_nProjectionMode = ( CubemapProjectionMode_t )nProjectionMode;
|
|
return pSceneObject;
|
|
}
|
|
|
|
CSceneLightProbeVolumeObject CreateLightProbeVolume( ISceneWorld pWorld );
|
|
|
|
void MarkEnvironmentMapObjectUpdated( CEnvMapSceneObject pEnvMap );
|
|
void MarkLightProbeVolumeObjectUpdated( CSceneLightProbeVolumeObject pLightProbe );
|
|
|
|
inline uint AddCullingBox( ISceneWorld pWorld, bool nCullMode, Vector3 vOrigin, Angles vAngles, Vector3 vExtents )
|
|
{
|
|
return g_pSceneSystem->AddCullingBox( pWorld, nCullMode ? SCENESYSTEM_BOX_CULL_INSIDE : SCENESYSTEM_BOX_CULL_OUTSIDE, vOrigin, vAngles, vExtents );
|
|
}
|
|
|
|
void RemoveCullingBox( ISceneWorld pWorld, uint nBoxId );
|
|
|
|
uint AddVolumetricFogVolume( ISceneWorld pWorld, SceneVolumetricFogVolume_t volume );
|
|
void RemoveVolumetricFogVolume( ISceneWorld pWorld, uint nId );
|
|
|
|
inline void DownsampleTexture( IRenderContext ctx, ITexture src, byte nDownsampleType )
|
|
{
|
|
return g_pSceneSystem->DownsampleTexture( ctx, src, nullptr, nDownsampleType );
|
|
}
|
|
|
|
void BindTransformSlot( IRenderContext pCtx, int nVBSlot, int nTransformSlotIndex );
|
|
|
|
// Ray Tracing
|
|
IRayTraceSceneWorld CreateRayTraceWorld( string pWorldDebugName, int nMaxRayTypes );
|
|
void DestroyRayTraceWorld( IRayTraceSceneWorld pRayTraceSceneWorld );
|
|
|
|
// GPU Profiler
|
|
void SetGPUProfilerMode( SceneSystemGPUProfilerMode_t eProfilerMode );
|
|
SceneSystemGPUProfilerMode_t GetGPUProfilerMode();
|
|
|
|
inline int GetGpuTimestampCount()
|
|
{
|
|
CUtlVector< SceneSystemTimestampFrameData_t > timestamps;
|
|
g_pSceneSystem->GetMostRecentTimestampFrameSummary( SWAP_CHAIN_HANDLE_INVALID, timestamps );
|
|
return timestamps.Count();
|
|
}
|
|
|
|
inline float GetGpuTimestampDuration( int index )
|
|
{
|
|
CUtlVector< SceneSystemTimestampFrameData_t > timestamps;
|
|
g_pSceneSystem->GetMostRecentTimestampFrameSummary( SWAP_CHAIN_HANDLE_INVALID, timestamps );
|
|
if ( index >= 0 && index < timestamps.Count() )
|
|
{
|
|
return timestamps[index].m_flDurationInMilliseconds;
|
|
}
|
|
return 0.0f;
|
|
}
|
|
|
|
inline string GetGpuTimestampName( int index )
|
|
{
|
|
CUtlVector< SceneSystemTimestampFrameData_t > timestamps;
|
|
g_pSceneSystem->GetMostRecentTimestampFrameSummary( SWAP_CHAIN_HANDLE_INVALID, timestamps );
|
|
if ( index >= 0 && index < timestamps.Count() )
|
|
{
|
|
return timestamps[index].m_sGroupName.Get();
|
|
}
|
|
return "";
|
|
}
|
|
|
|
// Managed timestamp support for CommandList etc.
|
|
bool SetManagedPerfMarker( IRenderContext ctx, string markerName );
|
|
}
|