From 9331f2bffaf34a8de5365613b17117b37b461209 Mon Sep 17 00:00:00 2001 From: Antoine Pilote Date: Mon, 22 Dec 2025 16:29:31 -0800 Subject: [PATCH] Fixed opaque & non-opaque sprite sorting (#3660) --- .../Scene/GameObjectSystems/SceneSpriteSystem.cs | 9 ++++++++- .../Systems/SceneSystem/SpriteBatchSceneObject.cs | 2 ++ .../addons/base/Assets/shaders/sprite/sprite_ps.shader | 10 +++++----- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/engine/Sandbox.Engine/Scene/GameObjectSystems/SceneSpriteSystem.cs b/engine/Sandbox.Engine/Scene/GameObjectSystems/SceneSpriteSystem.cs index 41af2121..a7f01fa1 100644 --- a/engine/Sandbox.Engine/Scene/GameObjectSystems/SceneSpriteSystem.cs +++ b/engine/Sandbox.Engine/Scene/GameObjectSystems/SceneSpriteSystem.cs @@ -231,6 +231,11 @@ public sealed class SceneSpriteSystem : GameObjectSystem flags |= InstanceGroupFlags.Additive; } + if ( component.Opaque ) + { + flags |= InstanceGroupFlags.Opaque; + } + RenderGroupKey renderGroupKey = new() { GroupFlags = flags, @@ -281,6 +286,7 @@ public sealed class SceneSpriteSystem : GameObjectSystem renderGroupObject.Flags.ExcludeGameLayer = (renderGroupKey.GroupFlags & InstanceGroupFlags.CastOnlyShadow) != 0; renderGroupObject.Sorted = (renderGroupKey.GroupFlags & InstanceGroupFlags.Transparent) != 0; renderGroupObject.Additive = (renderGroupKey.GroupFlags & InstanceGroupFlags.Additive) != 0; + renderGroupObject.Opaque = (renderGroupKey.GroupFlags & InstanceGroupFlags.Opaque) != 0; renderGroupObject.Tags.SetFrom( new TagSet( renderGroupKey.Tags ) ); renderGroupKey.RenderLayer.Apply( renderGroupObject ); @@ -362,6 +368,7 @@ public sealed class SceneSpriteSystem : GameObjectSystem CastShadow = 1 << 0, CastOnlyShadow = 1 << 1, Transparent = 1 << 2, - Additive = 1 << 3 + Additive = 1 << 3, + Opaque = 1 << 4 } } diff --git a/engine/Sandbox.Engine/Systems/SceneSystem/SpriteBatchSceneObject.cs b/engine/Sandbox.Engine/Systems/SceneSystem/SpriteBatchSceneObject.cs index 75cab2d3..5ca89c54 100644 --- a/engine/Sandbox.Engine/Systems/SceneSystem/SpriteBatchSceneObject.cs +++ b/engine/Sandbox.Engine/Systems/SceneSystem/SpriteBatchSceneObject.cs @@ -13,6 +13,7 @@ internal sealed class SpriteBatchSceneObject : SceneCustomObject public bool Sorted { get; set; } = false; public bool Filtered { get; set; } = false; public bool Additive { get; set; } = false; + public bool Opaque { get; set; } = false; internal Dictionary Components = new(); @@ -512,6 +513,7 @@ internal sealed class SpriteBatchSceneObject : SceneCustomObject Graphics.ResourceBarrierTransition( SpriteBufferOut, ResourceState.Common ); Graphics.Attributes.SetCombo( "D_BLEND", Additive ? 1 : 0 ); + Graphics.Attributes.SetCombo( "D_OPAQUE", Opaque ? 1 : 0 ); // Sort if ( Sorted ) diff --git a/game/addons/base/Assets/shaders/sprite/sprite_ps.shader b/game/addons/base/Assets/shaders/sprite/sprite_ps.shader index c62ac331..f04fb289 100644 --- a/game/addons/base/Assets/shaders/sprite/sprite_ps.shader +++ b/game/addons/base/Assets/shaders/sprite/sprite_ps.shader @@ -230,16 +230,15 @@ PS RenderState( SrcBlend, SRC_ALPHA ); RenderState( DstBlend, ONE ); RenderState( DepthWriteEnable, false ); - #else - RenderState( BlendEnable, true); - RenderState( DepthWriteEnable, S_MODE_DEPTH == 1 ); + #else + RenderState( BlendEnable, true ); RenderState( SrcBlend, SRC_ALPHA ); RenderState( DstBlend, INV_SRC_ALPHA ); RenderState( BlendOp, ADD ); RenderState( SrcBlendAlpha, ONE ); RenderState( DstBlendAlpha, INV_SRC_ALPHA ); - RenderState( AlphaToCoverageEnable, S_MODE_DEPTH == 1); - + RenderState( DepthWriteEnable, D_OPAQUE || S_MODE_DEPTH == 1 ); + RenderState( AlphaToCoverageEnable, S_MODE_DEPTH == 1 ); #endif RenderState( CullMode, NONE ); @@ -290,6 +289,7 @@ PS int CurrentBufferSize < Attribute("SpriteCount"); >; DynamicCombo( D_BLEND, 0..1, Sys( ALL ) ); + DynamicCombo( D_OPAQUE, 0..1, Sys( ALL ) ); float g_FogStrength < Attribute( "g_FogStrength" ); >;