diff --git a/Source/Engine/Graphics/RenderTask.h b/Source/Engine/Graphics/RenderTask.h index 8efa198be..92a48cf76 100644 --- a/Source/Engine/Graphics/RenderTask.h +++ b/Source/Engine/Graphics/RenderTask.h @@ -426,6 +426,11 @@ API_STRUCT(NoDefault) struct RenderContext /// API_FIELD() SceneRenderTask* Task = nullptr; + /// + /// The proxy render view used to synchronize objects level of detail during rendering (eg. during shadow maps rendering passes). It's optional. + /// + API_FIELD() RenderView* LodProxyView = nullptr; + /// /// The render view. /// diff --git a/Source/Engine/Graphics/RenderTools.cpp b/Source/Engine/Graphics/RenderTools.cpp index 370bc71d3..912b0ed48 100644 --- a/Source/Engine/Graphics/RenderTools.cpp +++ b/Source/Engine/Graphics/RenderTools.cpp @@ -441,7 +441,8 @@ float RenderTools::ComputeBoundsScreenRadiusSquared(const Float3& origin, float int32 RenderTools::ComputeModelLOD(const Model* model, const Float3& origin, float radius, const RenderContext& renderContext) { - const float screenRadiusSquared = ComputeBoundsScreenRadiusSquared(origin, radius, renderContext.View) * renderContext.View.ModelLODDistanceFactorSqrt; + const auto lodView = (renderContext.LodProxyView ? renderContext.LodProxyView : &renderContext.View); + const float screenRadiusSquared = ComputeBoundsScreenRadiusSquared(origin, radius, *lodView) * renderContext.View.ModelLODDistanceFactorSqrt; // Check if model is being culled if (Math::Square(model->MinScreenSize * 0.5f) > screenRadiusSquared) @@ -465,7 +466,8 @@ int32 RenderTools::ComputeModelLOD(const Model* model, const Float3& origin, flo int32 RenderTools::ComputeSkinnedModelLOD(const SkinnedModel* model, const Float3& origin, float radius, const RenderContext& renderContext) { - const float screenRadiusSquared = ComputeBoundsScreenRadiusSquared(origin, radius, renderContext.View) * renderContext.View.ModelLODDistanceFactorSqrt; + const auto lodView = (renderContext.LodProxyView ? renderContext.LodProxyView : &renderContext.View); + const float screenRadiusSquared = ComputeBoundsScreenRadiusSquared(origin, radius, *lodView) * renderContext.View.ModelLODDistanceFactorSqrt; // Check if model is being culled if (Math::Square(model->MinScreenSize * 0.5f) > screenRadiusSquared) diff --git a/Source/Engine/Graphics/RenderView.cpp b/Source/Engine/Graphics/RenderView.cpp index efd8464b0..777b7595d 100644 --- a/Source/Engine/Graphics/RenderView.cpp +++ b/Source/Engine/Graphics/RenderView.cpp @@ -55,6 +55,7 @@ void RenderView::Prepare(RenderContext& renderContext) } renderContext.List->Init(renderContext); + renderContext.LodProxyView = nullptr; PrepareCache(renderContext, width, height, taaJitter); } @@ -73,7 +74,7 @@ void RenderView::PrepareCache(const RenderContext& renderContext, float width, f WorldPosition = Origin + Position; // Ortho views have issues with screen size LOD culling - const float modelLODDistanceFactor = IsOrthographicProjection() ? 100.0f : ModelLODDistanceFactor; + const float modelLODDistanceFactor = (renderContext.LodProxyView ? renderContext.LodProxyView->IsOrthographicProjection() : IsOrthographicProjection()) ? 100.0f : ModelLODDistanceFactor; ModelLODDistanceFactorSqrt = modelLODDistanceFactor * modelLODDistanceFactor; // Setup main view render info diff --git a/Source/Engine/Level/Actors/Decal.cpp b/Source/Engine/Level/Actors/Decal.cpp index 2331a943f..97a61c5ed 100644 --- a/Source/Engine/Level/Actors/Decal.cpp +++ b/Source/Engine/Level/Actors/Decal.cpp @@ -75,7 +75,8 @@ void Decal::Draw(RenderContext& renderContext) Material->IsLoaded() && Material->IsDecal()) { - const float screenRadiusSquared = RenderTools::ComputeBoundsScreenRadiusSquared(_sphere.Center - renderContext.View.Origin, (float)_sphere.Radius, renderContext.View) * renderContext.View.ModelLODDistanceFactorSqrt; + const auto lodView = (renderContext.LodProxyView ? renderContext.LodProxyView : &renderContext.View); + const float screenRadiusSquared = RenderTools::ComputeBoundsScreenRadiusSquared(_sphere.Center - renderContext.View.Origin, (float)_sphere.Radius, *lodView) * renderContext.View.ModelLODDistanceFactorSqrt; // Check if decal is being culled if (Math::Square(DrawMinScreenSize * 0.5f) > screenRadiusSquared) diff --git a/Source/Engine/Renderer/ShadowsPass.cpp b/Source/Engine/Renderer/ShadowsPass.cpp index 20352a2f8..9449c2290 100644 --- a/Source/Engine/Renderer/ShadowsPass.cpp +++ b/Source/Engine/Renderer/ShadowsPass.cpp @@ -193,6 +193,9 @@ void ShadowsPass::SetupRenderContext(RenderContext& renderContext, RenderContext { const auto& view = renderContext.View; + // Use the current render view to sync model LODs with the shadow maps rendering stage + shadowContext.LodProxyView = &renderContext.View; + // Prepare properties auto& shadowView = shadowContext.View; shadowView.Flags = view.Flags; diff --git a/Source/Engine/Terrain/TerrainChunk.cpp b/Source/Engine/Terrain/TerrainChunk.cpp index 70551fe67..bc0456e12 100644 --- a/Source/Engine/Terrain/TerrainChunk.cpp +++ b/Source/Engine/Terrain/TerrainChunk.cpp @@ -44,7 +44,8 @@ bool TerrainChunk::PrepareDraw(const RenderContext& renderContext) const float chunkEdgeSize = (_patch->_terrain->_chunkSize * TERRAIN_UNITS_PER_VERTEX); // Calculate chunk distance to view - const float distance = Float3::Distance(_boundsCenter - renderContext.View.Origin, renderContext.View.Position); + const auto lodView = (renderContext.LodProxyView ? renderContext.LodProxyView : &renderContext.View); + const float distance = Float3::Distance(_boundsCenter - lodView->Origin, lodView->Position); lod = (int32)Math::Pow(distance / chunkEdgeSize, lodDistribution); lod += lodBias;