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:
{