From 2f1f3800622f989039e62b690a09161beaff5074 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 7 Oct 2025 18:10:14 +0200 Subject: [PATCH] Add new scene textures `SceneStencil` and `ObjectLayer` to sample Stencil buffer --- Source/Engine/Graphics/Materials/MaterialInfo.h | 10 ++++++++++ .../Graphics/Materials/MaterialParams.cpp | 4 ++++ .../GPU/ParticleEmitterGraph.GPU.Textures.cpp | 2 ++ .../MaterialGenerator.Textures.cpp | 17 +++++++++++++++++ Source/Engine/Visject/ShaderGraphUtilities.cpp | 5 ++++- 5 files changed, 37 insertions(+), 1 deletion(-) diff --git a/Source/Engine/Graphics/Materials/MaterialInfo.h b/Source/Engine/Graphics/Materials/MaterialInfo.h index 69a9bd0a6..84771fed8 100644 --- a/Source/Engine/Graphics/Materials/MaterialInfo.h +++ b/Source/Engine/Graphics/Materials/MaterialInfo.h @@ -444,6 +444,16 @@ API_ENUM() enum class MaterialSceneTextures /// The scene world-space position (relative to the render view origin). /// WorldPosition = 11, + + /// + /// The scene stencil. + /// + SceneStencil = 12, + + /// + /// The object layer index. + /// + ObjectLayer = 13, }; /// diff --git a/Source/Engine/Graphics/Materials/MaterialParams.cpp b/Source/Engine/Graphics/Materials/MaterialParams.cpp index 2fa5a8e5f..05bb29c4a 100644 --- a/Source/Engine/Graphics/Materials/MaterialParams.cpp +++ b/Source/Engine/Graphics/Materials/MaterialParams.cpp @@ -393,6 +393,10 @@ void MaterialParameter::Bind(BindMeta& meta) const case MaterialSceneTextures::Specular: view = meta.CanSampleGBuffer ? meta.Buffers->GBuffer2->View() : nullptr; break; + case MaterialSceneTextures::SceneStencil: + case MaterialSceneTextures::ObjectLayer: + view = meta.CanSampleDepth ? meta.Buffers->DepthBuffer->ViewStencil() : nullptr; + break; default: ; } } diff --git a/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.Textures.cpp b/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.Textures.cpp index 820f8da3d..ed4f5f0e3 100644 --- a/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.Textures.cpp +++ b/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.Textures.cpp @@ -246,6 +246,8 @@ void ParticleEmitterGPUGenerator::ProcessGroupTextures(Box* box, Node* node, Val break; } case MaterialSceneTextures::WorldPosition: + case MaterialSceneTextures::SceneStencil: + case MaterialSceneTextures::ObjectLayer: value = Value::Zero; // Not implemented break; default: diff --git a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp index 6bd88f2ae..c48a4c569 100644 --- a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp +++ b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp @@ -474,6 +474,23 @@ void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value) value = writeLocal(VariantType::Float3, String::Format(TEXT("GetWorldPos({1}, {0}.rgb)"), depthSample->Value, uv), node); break; } + case MaterialSceneTextures::SceneStencil: + case MaterialSceneTextures::ObjectLayer: + { + auto stencilParam = findOrAddSceneTexture(MaterialSceneTextures::SceneStencil); + const auto parent = box->GetParent>(); + MaterialGraphBox* uvBox = parent->GetBox(0); + bool useCustomUVs = uvBox->HasConnection(); + String uv; + if (useCustomUVs) + uv = MaterialValue::Cast(tryGetValue(uvBox, getUVs), VariantType::Float2).Value; + else + uv = TEXT("input.TexCoord.xy"); + const Char* func = type == MaterialSceneTextures::ObjectLayer ? TEXT("STENCIL_BUFFER_OBJECT_LAYER") : TEXT(""); + value = writeLocal(VariantType::Int, String::Format(TEXT("{2}(STENCIL_BUFFER_LOAD({0}, {1} * ScreenSize.xy))"), stencilParam.ShaderName, uv, func), node); + _includes.Add(TEXT("./Flax/Stencil.hlsl")); + break; + } default: { // Sample single texture diff --git a/Source/Engine/Visject/ShaderGraphUtilities.cpp b/Source/Engine/Visject/ShaderGraphUtilities.cpp index 83db4590a..bdcb55c05 100644 --- a/Source/Engine/Visject/ShaderGraphUtilities.cpp +++ b/Source/Engine/Visject/ShaderGraphUtilities.cpp @@ -157,7 +157,10 @@ const Char* ShaderGraphUtilities::GenerateShaderResources(TextWriterUnicode& wri case MaterialParameterType::GPUTexture: case MaterialParameterType::SceneTexture: case MaterialParameterType::Texture: - format = TEXT("Texture2D {0} : register(t{1});"); + if (param.AsInteger == (int32)MaterialSceneTextures::SceneStencil) + format = TEXT("Texture2D {0} : register(t{1});"); + else + format = TEXT("Texture2D {0} : register(t{1});"); break; case MaterialParameterType::GPUTextureCube: case MaterialParameterType::CubeTexture: