From 4c98e0a335843ffc6610d0ae47d7126ddba173c8 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Mon, 4 Apr 2022 17:11:01 +0200 Subject: [PATCH] Add `IsSingleFrame` to `RenderView` for thumbnails/pre-render views drawing without temporal effects and LOD transitions --- Source/Editor/Content/Proxy/AssetProxy.cs | 4 ++++ Source/Engine/Content/Assets/Model.cpp | 9 ++++++--- Source/Engine/Content/Assets/SkinnedModel.cpp | 15 +++++++-------- Source/Engine/Graphics/RenderView.h | 5 +++++ Source/Engine/Renderer/DrawCall.h | 4 ++-- 5 files changed, 24 insertions(+), 13 deletions(-) diff --git a/Source/Editor/Content/Proxy/AssetProxy.cs b/Source/Editor/Content/Proxy/AssetProxy.cs index 67a0704c0..6516dbc37 100644 --- a/Source/Editor/Content/Proxy/AssetProxy.cs +++ b/Source/Editor/Content/Proxy/AssetProxy.cs @@ -108,6 +108,10 @@ namespace FlaxEditor.Content var task = preview.Task; task.Enabled = false; + var view = task.View; + view.IsSingleFrame = true; // Disable LOD transitions + task.View = view; + var eyeAdaptation = preview.PostFxVolume.EyeAdaptation; eyeAdaptation.Mode = EyeAdaptationMode.None; eyeAdaptation.OverrideFlags |= EyeAdaptationSettingsOverride.Mode; diff --git a/Source/Engine/Content/Assets/Model.cpp b/Source/Engine/Content/Assets/Model.cpp index 5b7ebac9b..e96592043 100644 --- a/Source/Engine/Content/Assets/Model.cpp +++ b/Source/Engine/Content/Assets/Model.cpp @@ -194,7 +194,7 @@ void Model::Draw(const RenderContext& renderContext, const Mesh::DrawInfo& info) if (lodIndex == -1) { // Handling model fade-out transition - if (modelFrame == frame && info.DrawState->PrevLOD != -1) + if (modelFrame == frame && info.DrawState->PrevLOD != -1 && !renderContext.View.IsSingleFrame) { // Check if start transition if (info.DrawState->LODTransition == 255) @@ -223,8 +223,11 @@ void Model::Draw(const RenderContext& renderContext, const Mesh::DrawInfo& info) lodIndex += info.LODBias + renderContext.View.ModelLODBias; lodIndex = ClampLODIndex(lodIndex); + if (renderContext.View.IsSingleFrame) + { + } // Check if it's the new frame and could update the drawing state (note: model instance could be rendered many times per frame to different viewports) - if (modelFrame == frame) + else if (modelFrame == frame) { // Check if start transition if (info.DrawState->PrevLOD != lodIndex && info.DrawState->LODTransition == 255) @@ -249,7 +252,7 @@ void Model::Draw(const RenderContext& renderContext, const Mesh::DrawInfo& info) } // Draw - if (info.DrawState->PrevLOD == lodIndex) + if (info.DrawState->PrevLOD == lodIndex || renderContext.View.IsSingleFrame) { LODs[lodIndex].Draw(renderContext, info, 0.0f); } diff --git a/Source/Engine/Content/Assets/SkinnedModel.cpp b/Source/Engine/Content/Assets/SkinnedModel.cpp index 12e940382..e3e1339a1 100644 --- a/Source/Engine/Content/Assets/SkinnedModel.cpp +++ b/Source/Engine/Content/Assets/SkinnedModel.cpp @@ -30,13 +30,11 @@ class StreamSkinnedModelLODTask : public ThreadPoolTask { private: - WeakAssetReference _asset; int32 _lodIndex; FlaxStorage::LockData _dataLock; public: - /// /// Init /// @@ -50,7 +48,6 @@ public: } public: - // [ThreadPoolTask] bool HasReference(Object* resource) const override { @@ -58,7 +55,6 @@ public: } protected: - // [ThreadPoolTask] bool Run() override { @@ -191,7 +187,7 @@ void SkinnedModel::Draw(RenderContext& renderContext, const SkinnedMesh::DrawInf if (lodIndex == -1) { // Handling model fade-out transition - if (modelFrame == frame && info.DrawState->PrevLOD != -1) + if (modelFrame == frame && info.DrawState->PrevLOD != -1 && !renderContext.View.IsSingleFrame) { // Check if start transition if (info.DrawState->LODTransition == 255) @@ -220,8 +216,11 @@ void SkinnedModel::Draw(RenderContext& renderContext, const SkinnedMesh::DrawInf lodIndex += info.LODBias + renderContext.View.ModelLODBias; lodIndex = ClampLODIndex(lodIndex); + if (renderContext.View.IsSingleFrame) + { + } // Check if it's the new frame and could update the drawing state (note: model instance could be rendered many times per frame to different viewports) - if (modelFrame == frame) + else if (modelFrame == frame) { // Check if start transition if (info.DrawState->PrevLOD != lodIndex && info.DrawState->LODTransition == 255) @@ -237,7 +236,7 @@ void SkinnedModel::Draw(RenderContext& renderContext, const SkinnedMesh::DrawInf info.DrawState->PrevLOD = lodIndex; } } - // Check if there was a gap between frames in drawing this model instance + // Check if there was a gap between frames in drawing this model instance else if (modelFrame < frame || info.DrawState->PrevLOD == -1) { // Reset state @@ -246,7 +245,7 @@ void SkinnedModel::Draw(RenderContext& renderContext, const SkinnedMesh::DrawInf } // Draw - if (info.DrawState->PrevLOD == lodIndex) + if (info.DrawState->PrevLOD == lodIndex || renderContext.View.IsSingleFrame) { LODs[lodIndex].Draw(renderContext, info, 0.0f); } diff --git a/Source/Engine/Graphics/RenderView.h b/Source/Engine/Graphics/RenderView.h index 5a4825a3d..597e436a3 100644 --- a/Source/Engine/Graphics/RenderView.h +++ b/Source/Engine/Graphics/RenderView.h @@ -97,6 +97,11 @@ public: /// API_FIELD() bool IsOfflinePass = false; + /// + /// Flag used by single-frame rendering passes (eg. thumbnail rendering, model view caching) to reject LOD transitions animations and other temporal draw effects. + /// + API_FIELD() bool IsSingleFrame = false; + /// /// The static flags mask used to hide objects that don't have a given static flags. Eg. use StaticFlags::Lightmap to render only objects that can use lightmap. /// diff --git a/Source/Engine/Renderer/DrawCall.h b/Source/Engine/Renderer/DrawCall.h index e3b49b41f..16f2dd590 100644 --- a/Source/Engine/Renderer/DrawCall.h +++ b/Source/Engine/Renderer/DrawCall.h @@ -322,13 +322,13 @@ struct TIsPODType #define GEOMETRY_DRAW_STATE_EVENT_BEGIN(drawState, worldMatrix) \ const auto frame = Engine::FrameCount; \ - if (drawState.PrevFrame + 1 < frame) \ + if (drawState.PrevFrame + 1 < frame && !renderContext.View.IsSingleFrame) \ { \ drawState.PrevWorld = worldMatrix; \ } #define GEOMETRY_DRAW_STATE_EVENT_END(drawState, worldMatrix) \ - if (drawState.PrevFrame != frame) \ + if (drawState.PrevFrame != frame && !renderContext.View.IsSingleFrame) \ { \ drawState.PrevWorld = worldMatrix; \ drawState.PrevFrame = frame; \