diff --git a/Content/Editor/MaterialTemplates/Surface.shader b/Content/Editor/MaterialTemplates/Surface.shader index ff88f1b40..461aa714d 100644 --- a/Content/Editor/MaterialTemplates/Surface.shader +++ b/Content/Editor/MaterialTemplates/Surface.shader @@ -14,6 +14,8 @@ float4x4 WorldMatrix; float4x4 ViewMatrix; float4x4 PrevViewProjectionMatrix; float4x4 PrevWorldMatrix; +float4x4 MainViewProjectionMatrix; +float4 MainScreenSize; float3 ViewPos; float ViewFar; float3 ViewDir; diff --git a/Source/Editor/Surface/Archetypes/Material.cs b/Source/Editor/Surface/Archetypes/Material.cs index 38a3eb3dd..fa8ff4ef9 100644 --- a/Source/Editor/Surface/Archetypes/Material.cs +++ b/Source/Editor/Surface/Archetypes/Material.cs @@ -357,11 +357,14 @@ namespace FlaxEditor.Surface.Archetypes Title = "Screen Position", Description = "Gathers screen position or texcoord", Flags = NodeFlags.MaterialGraph, - Size = new Float2(150, 40), + Size = new Float2(160, 40), + DefaultValues = new object[] { false }, Elements = new[] { NodeElementArchetype.Factory.Output(0, "Position", typeof(Float2), 0), NodeElementArchetype.Factory.Output(1, "Texcoord", typeof(Float2), 1), + NodeElementArchetype.Factory.Bool(0, 0, 0), + NodeElementArchetype.Factory.Text(20, 0, "Main View"), } }, new NodeArchetype @@ -370,11 +373,14 @@ namespace FlaxEditor.Surface.Archetypes Title = "Screen Size", Description = "Gathers screen size", Flags = NodeFlags.MaterialGraph, - Size = new Float2(150, 40), + Size = new Float2(160, 40), + DefaultValues = new object[] { false }, Elements = new[] { NodeElementArchetype.Factory.Output(0, "Size", typeof(Float2), 0), NodeElementArchetype.Factory.Output(1, "Inv Size", typeof(Float2), 1), + NodeElementArchetype.Factory.Bool(0, 0, 0), + NodeElementArchetype.Factory.Text(20, 0, "Main View"), } }, new NodeArchetype diff --git a/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp b/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp index 77df97f9d..7e7e6c562 100644 --- a/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp @@ -22,6 +22,8 @@ PACK_STRUCT(struct DeferredMaterialShaderData { Matrix ViewMatrix; Matrix PrevViewProjectionMatrix; Matrix PrevWorldMatrix; + Matrix MainViewProjectionMatrix; + Float4 MainScreenSize; Float3 ViewPos; float ViewFar; Float3 ViewDir; @@ -86,6 +88,8 @@ void DeferredMaterialShader::Bind(BindParameters& params) Matrix::Transpose(view.View, materialData->ViewMatrix); Matrix::Transpose(drawCall.Surface.PrevWorld, materialData->PrevWorldMatrix); Matrix::Transpose(view.PrevViewProjection, materialData->PrevViewProjectionMatrix); + Matrix::Transpose(view.MainViewProjection, materialData->MainViewProjectionMatrix); + materialData->MainScreenSize = view.MainScreenSize; materialData->ViewPos = view.Position; materialData->ViewFar = view.Far; materialData->ViewDir = view.Direction; diff --git a/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp b/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp index 67f0914a1..6c28fa096 100644 --- a/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp @@ -24,6 +24,8 @@ PACK_STRUCT(struct ForwardMaterialShaderData { Matrix ViewMatrix; Matrix PrevViewProjectionMatrix; Matrix PrevWorldMatrix; + Matrix MainViewProjectionMatrix; + Float4 MainScreenSize; Float3 ViewPos; float ViewFar; Float3 ViewDir; @@ -94,6 +96,8 @@ void ForwardMaterialShader::Bind(BindParameters& params) Matrix::Transpose(view.View, materialData->ViewMatrix); Matrix::Transpose(drawCall.Surface.PrevWorld, materialData->PrevWorldMatrix); Matrix::Transpose(view.PrevViewProjection, materialData->PrevViewProjectionMatrix); + Matrix::Transpose(view.MainViewProjection, materialData->MainViewProjectionMatrix); + materialData->MainScreenSize = view.MainScreenSize; materialData->ViewPos = view.Position; materialData->ViewFar = view.Far; materialData->ViewDir = view.Direction; diff --git a/Source/Engine/Graphics/Materials/MaterialShader.h b/Source/Engine/Graphics/Materials/MaterialShader.h index 8499dff80..fae152681 100644 --- a/Source/Engine/Graphics/Materials/MaterialShader.h +++ b/Source/Engine/Graphics/Materials/MaterialShader.h @@ -10,7 +10,7 @@ /// /// Current materials shader version. /// -#define MATERIAL_GRAPH_VERSION 154 +#define MATERIAL_GRAPH_VERSION 155 class Material; class GPUShader; diff --git a/Source/Engine/Graphics/RenderView.cpp b/Source/Engine/Graphics/RenderView.cpp index 78e3757bd..125897ea7 100644 --- a/Source/Engine/Graphics/RenderView.cpp +++ b/Source/Engine/Graphics/RenderView.cpp @@ -60,7 +60,7 @@ void RenderView::Prepare(RenderContext& renderContext) PrepareCache(renderContext, width, height, taaJitter); } -void RenderView::PrepareCache(RenderContext& renderContext, float width, float height, const Float2& temporalAAJitter) +void RenderView::PrepareCache(RenderContext& renderContext, float width, float height, const Float2& temporalAAJitter, RenderView* mainView) { // The same format used by the Flax common shaders and postFx materials ViewInfo = Float4(1.0f / Projection.M11, 1.0f / Projection.M22, Far / (Far - Near), (-Far * Near) / (Far - Near) / Far); @@ -76,6 +76,12 @@ void RenderView::PrepareCache(RenderContext& renderContext, float width, float h // Ortho views have issues with screen size LOD culling const float modelLODDistanceFactor = (renderContext.LodProxyView ? renderContext.LodProxyView->IsOrthographicProjection() : IsOrthographicProjection()) ? 100.0f : ModelLODDistanceFactor; ModelLODDistanceFactorSqrt = modelLODDistanceFactor * modelLODDistanceFactor; + + // Setup main view render info + if (!mainView) + mainView = this; + MainViewProjection = mainView->ViewProjection(); + MainScreenSize = mainView->ScreenSize; } void RenderView::SetUp(const Matrix& view, const Matrix& projection) diff --git a/Source/Engine/Graphics/RenderView.h b/Source/Engine/Graphics/RenderView.h index 3f5d13088..dd974761e 100644 --- a/Source/Engine/Graphics/RenderView.h +++ b/Source/Engine/Graphics/RenderView.h @@ -202,6 +202,16 @@ public: /// API_FIELD() Matrix PrevViewProjection; + /// + /// The main viewport view * projection matrix. + /// + API_FIELD() Matrix MainViewProjection; + + /// + /// The main viewport screen size packed (x - width, y - height, zw - inv width, w - inv height). + /// + API_FIELD() Float4 MainScreenSize; + /// /// Square of . Cached by rendering backend. /// @@ -220,7 +230,8 @@ public: /// The rendering width. /// The rendering height. /// The temporal jitter for this frame. - void PrepareCache(RenderContext& renderContext, float width, float height, const Float2& temporalAAJitter); + /// The main rendering viewport. Use null if it's top level view; pass pointer to main view for sub-passes like shadow depths. + void PrepareCache(RenderContext& renderContext, float width, float height, const Float2& temporalAAJitter, RenderView* mainView = nullptr); /// /// Determines whether view is perspective projection or orthographic. diff --git a/Source/Engine/Renderer/ShadowsPass.cpp b/Source/Engine/Renderer/ShadowsPass.cpp index 9b4444021..1a7024d24 100644 --- a/Source/Engine/Renderer/ShadowsPass.cpp +++ b/Source/Engine/Renderer/ShadowsPass.cpp @@ -289,7 +289,7 @@ void ShadowsPass::RenderShadow(RenderContext& renderContext, RendererPointLightD const auto shadowMapsSizeCube = (float)_shadowMapsSizeCube; context->SetViewportAndScissors(shadowMapsSizeCube, shadowMapsSizeCube); _shadowContext.View.SetUpCube(PointLight_NearPlane, lightRadius, lightPosition); - _shadowContext.View.PrepareCache(_shadowContext, shadowMapsSizeCube, shadowMapsSizeCube, Float2::Zero); + _shadowContext.View.PrepareCache(_shadowContext, shadowMapsSizeCube, shadowMapsSizeCube, Float2::Zero, &view); // Render depth to all 6 faces of the cube map for (int32 faceIndex = 0; faceIndex < 6; faceIndex++) @@ -392,7 +392,7 @@ void ShadowsPass::RenderShadow(RenderContext& renderContext, RendererSpotLightDa const auto shadowMapsSizeCube = (float)_shadowMapsSizeCube; context->SetViewportAndScissors(shadowMapsSizeCube, shadowMapsSizeCube); _shadowContext.View.SetProjector(SpotLight_NearPlane, lightRadius, lightPosition, lightDirection, light.UpVector, light.OuterConeAngle * 2.0f); - _shadowContext.View.PrepareCache(_shadowContext, shadowMapsSizeCube, shadowMapsSizeCube, Float2::Zero); + _shadowContext.View.PrepareCache(_shadowContext, shadowMapsSizeCube, shadowMapsSizeCube, Float2::Zero, &view); // Render depth to all 1 face of the cube map const int32 cubeFaceIndex = 0; @@ -588,7 +588,7 @@ void ShadowsPass::RenderShadow(RenderContext& renderContext, RendererDirectional // Set up GPU context and render view const auto shadowMapsSizeCSM = (float)_shadowMapsSizeCSM; context->SetViewportAndScissors(shadowMapsSizeCSM, shadowMapsSizeCSM); - _shadowContext.View.PrepareCache(_shadowContext, shadowMapsSizeCSM, shadowMapsSizeCSM, Float2::Zero); + _shadowContext.View.PrepareCache(_shadowContext, shadowMapsSizeCSM, shadowMapsSizeCSM, Float2::Zero, &view); // Create the different view and projection matrices for each split float splitMinRatio = 0; diff --git a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Material.cpp b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Material.cpp index 7923a24d7..9790ad86d 100644 --- a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Material.cpp +++ b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Material.cpp @@ -45,19 +45,43 @@ void MaterialGenerator::ProcessGroupMaterial(Box* box, Node* node, Value& value) // Screen Position case 6: { - // Position - if (box->ID == 0) - value = Value(VariantType::Float2, TEXT("input.SvPosition.xy")); - // Texcoord - else if (box->ID == 1) - value = writeLocal(VariantType::Float2, TEXT("input.SvPosition.xy * ScreenSize.zw"), node); + // Check if use main view position + const auto layer = GetRootLayer(); + if (layer && layer->Domain == MaterialDomain::Surface && node->Values.Count() > 0 && node->Values[0].AsBool) + { + // Transform world position into main viewport texcoord space + Value clipPosition = writeLocal(VariantType::Float4, TEXT("mul(float4(input.WorldPosition.xyz, 1), MainViewProjectionMatrix)"), node); + Value uvPos = writeLocal(VariantType::Float2, String::Format(TEXT("(({0}.xy / {0}.w) * float2(0.5, -0.5) + float2(0.5, 0.5))"), clipPosition.Value), node); + // Position + if (box->ID == 0) + value = writeLocal(VariantType::Float2, String::Format(TEXT("{0} * MainScreenSize.xy"), uvPos.Value), node); + // Texcoord + else if (box->ID == 1) + value = uvPos; + } + else + { + // Position + if (box->ID == 0) + value = Value(VariantType::Float2, TEXT("input.SvPosition.xy")); + // Texcoord + else if (box->ID == 1) + value = writeLocal(VariantType::Float2, TEXT("input.SvPosition.xy * ScreenSize.zw"), node); + } break; } // Screen Size case 7: - value = Value(VariantType::Float2, box->ID == 0 ? TEXT("ScreenSize.xy") : TEXT("ScreenSize.zw")); + { + // Check if use main view position + const auto layer = GetRootLayer(); + if (layer && layer->Domain == MaterialDomain::Surface && node->Values.Count() > 0 && node->Values[0].AsBool) + value = Value(VariantType::Float2, box->ID == 0 ? TEXT("MainScreenSize.xy") : TEXT("MainScreenSize.zw")); + else + value = Value(VariantType::Float2, box->ID == 0 ? TEXT("ScreenSize.xy") : TEXT("ScreenSize.zw")); break; + } // Custom code case 8: {