From 545e59aba50e7b3af5d7f6103383a821b2e76734 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 9 Sep 2024 05:59:17 +0200 Subject: [PATCH] Fix lightmap uvs density view to handle `scale in lightmap` and outline non-static objects #2080 --- .../Shaders/Editor/LightmapUVsDensity.flax | 4 +- Source/Engine/Foliage/Foliage.cpp | 4 + Source/Engine/Graphics/Models/Mesh.cpp | 4 + Source/Engine/Graphics/Models/MeshBase.h | 4 + .../Graphics/Textures/StreamingTexture.cpp | 6 +- Source/Engine/Level/Actors/StaticModel.cpp | 8 ++ .../Renderer/Editor/LightmapUVsDensity.cpp | 74 +------------------ Source/Engine/Terrain/TerrainChunk.cpp | 8 ++ .../Shaders/Editor/LightmapUVsDensity.shader | 6 +- 9 files changed, 42 insertions(+), 76 deletions(-) diff --git a/Content/Shaders/Editor/LightmapUVsDensity.flax b/Content/Shaders/Editor/LightmapUVsDensity.flax index 2aa2cc60f..d7f265055 100644 --- a/Content/Shaders/Editor/LightmapUVsDensity.flax +++ b/Content/Shaders/Editor/LightmapUVsDensity.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a58cc65b8291c10e4fafa81df67dc30e9e1b80fd903ae2e4d173f3c586faf59f -size 4391 +oid sha256:a0ed25e40158253b2fdd565e7ad0e745308eadc5091a89502cbc1fa22288039f +size 4515 diff --git a/Source/Engine/Foliage/Foliage.cpp b/Source/Engine/Foliage/Foliage.cpp index bb9459677..83a89aba1 100644 --- a/Source/Engine/Foliage/Foliage.cpp +++ b/Source/Engine/Foliage/Foliage.cpp @@ -494,6 +494,10 @@ void Foliage::DrawType(RenderContext& renderContext, const FoliageType& type, Dr batch.DrawCall.Surface.GeometrySize = mesh.GetBox().GetSize(); batch.DrawCall.Surface.Skinning = nullptr; batch.DrawCall.WorldDeterminantSign = 1; +#if USE_EDITOR + if (renderContext.View.Mode == ViewMode::LightmapUVsDensity) + batch.DrawCall.Surface.LODDitherFactor = type.ScaleInLightmap; // See LightmapUVsDensityMaterialShader +#endif if (EnumHasAnyFlags(drawModes, DrawPass::Forward)) { diff --git a/Source/Engine/Graphics/Models/Mesh.cpp b/Source/Engine/Graphics/Models/Mesh.cpp index 39439af5c..a890da21d 100644 --- a/Source/Engine/Graphics/Models/Mesh.cpp +++ b/Source/Engine/Graphics/Models/Mesh.cpp @@ -485,6 +485,8 @@ void Mesh::Draw(const RenderContext& renderContext, const DrawInfo& info, float const ViewMode viewMode = renderContext.View.Mode; if (viewMode == ViewMode::LightmapUVsDensity || viewMode == ViewMode::LODPreview) GBufferPass::AddIndexBufferToModelLOD(_indexBuffer, &((Model*)_model)->LODs[_lodIndex]); + if (viewMode == ViewMode::LightmapUVsDensity) + drawCall.Surface.LODDitherFactor = info.LightmapScale; // See LightmapUVsDensityMaterialShader #endif // Push draw call to the render list @@ -547,6 +549,8 @@ void Mesh::Draw(const RenderContextBatch& renderContextBatch, const DrawInfo& in const ViewMode viewMode = renderContextBatch.GetMainContext().View.Mode; if (viewMode == ViewMode::LightmapUVsDensity || viewMode == ViewMode::LODPreview) GBufferPass::AddIndexBufferToModelLOD(_indexBuffer, &((Model*)_model)->LODs[_lodIndex]); + if (viewMode == ViewMode::LightmapUVsDensity) + drawCall.Surface.LODDitherFactor = info.LightmapScale; // See LightmapUVsDensityMaterialShader #endif // Push draw call to the render lists diff --git a/Source/Engine/Graphics/Models/MeshBase.h b/Source/Engine/Graphics/Models/MeshBase.h index 9963ec8ba..a8f7e36b8 100644 --- a/Source/Engine/Graphics/Models/MeshBase.h +++ b/Source/Engine/Graphics/Models/MeshBase.h @@ -241,5 +241,9 @@ public: /// The object sorting key. /// int16 SortOrder; + +#if USE_EDITOR + float LightmapScale = -1.0f; +#endif }; }; diff --git a/Source/Engine/Graphics/Textures/StreamingTexture.cpp b/Source/Engine/Graphics/Textures/StreamingTexture.cpp index ecd9bbd55..2e1aaf457 100644 --- a/Source/Engine/Graphics/Textures/StreamingTexture.cpp +++ b/Source/Engine/Graphics/Textures/StreamingTexture.cpp @@ -213,7 +213,7 @@ protected: const int32 dstMips = dstTexture->MipLevels(); GPUTexture* srcTexture = _streamingTexture->GetTexture(); const int32 srcMips = srcTexture->MipLevels(); - const int32 srcMissingMips = srcMips - srcTexture->ResidentMipLevels();; + const int32 srcMissingMips = srcMips - srcTexture->ResidentMipLevels(); const int32 mipCount = Math::Min(dstMips, srcMips); for (int32 mipIndex = srcMissingMips; mipIndex < mipCount; mipIndex++) { @@ -238,10 +238,10 @@ protected: void OnSync() override { + _newTexture->SetResidentMipLevels(_uploadedMipCount); Swap(_streamingTexture->_texture, _newTexture); - _streamingTexture->GetTexture()->SetResidentMipLevels(_uploadedMipCount); - _streamingTexture->ResidencyChanged(); SAFE_DELETE_GPU_RESOURCE(_newTexture); + _streamingTexture->ResidencyChanged(); // Base GPUTask::OnSync(); diff --git a/Source/Engine/Level/Actors/StaticModel.cpp b/Source/Engine/Level/Actors/StaticModel.cpp index dd77692b3..8d603ec37 100644 --- a/Source/Engine/Level/Actors/StaticModel.cpp +++ b/Source/Engine/Level/Actors/StaticModel.cpp @@ -357,6 +357,10 @@ void StaticModel::Draw(RenderContext& renderContext) draw.ForcedLOD = _forcedLod; draw.SortOrder = _sortOrder; draw.VertexColors = _vertexColorsCount ? _vertexColorsBuffer : nullptr; +#if USE_EDITOR + if (HasStaticFlag(StaticFlags::Lightmap)) + draw.LightmapScale = _scaleInLightmap; +#endif Model->Draw(renderContext, draw); @@ -391,6 +395,10 @@ void StaticModel::Draw(RenderContextBatch& renderContextBatch) draw.ForcedLOD = _forcedLod; draw.SortOrder = _sortOrder; draw.VertexColors = _vertexColorsCount ? _vertexColorsBuffer : nullptr; +#if USE_EDITOR + if (HasStaticFlag(StaticFlags::Lightmap)) + draw.LightmapScale = _scaleInLightmap; +#endif Model->Draw(renderContextBatch, draw); diff --git a/Source/Engine/Renderer/Editor/LightmapUVsDensity.cpp b/Source/Engine/Renderer/Editor/LightmapUVsDensity.cpp index 113d997f2..418ecfc1d 100644 --- a/Source/Engine/Renderer/Editor/LightmapUVsDensity.cpp +++ b/Source/Engine/Renderer/Editor/LightmapUVsDensity.cpp @@ -15,7 +15,6 @@ #include "Engine/Renderer/DrawCall.h" #include "Engine/Foliage/Foliage.h" #include "Engine/ShadowsOfMordor/Builder.Config.h" -#include "Engine/Level/Level.h" #include "Engine/Level/Scene/Scene.h" #include "Engine/Level/Actors/StaticModel.h" @@ -70,40 +69,6 @@ DrawPass LightmapUVsDensityMaterialShader::GetDrawModes() const return DrawPass::GBuffer; } -namespace -{ - Actor* FindActorByDrawCall(Actor* actor, const DrawCall& drawCall, float& scaleInLightmap) - { - // TODO: large-worlds - const auto asStaticModel = ScriptingObject::Cast(actor); - if (asStaticModel && asStaticModel->GetPerInstanceRandom() == drawCall.PerInstanceRandom && asStaticModel->GetPosition() == drawCall.ObjectPosition) - { - scaleInLightmap = asStaticModel->GetScaleInLightmap(); - return asStaticModel; - } - const auto asFoliage = ScriptingObject::Cast(actor); - if (asFoliage) - { - for (auto i = asFoliage->Instances.Begin(); i.IsNotEnd(); ++i) - { - auto& instance = *i; - if (instance.Random == drawCall.PerInstanceRandom && instance.Transform.Translation == drawCall.ObjectPosition) - { - scaleInLightmap = asFoliage->FoliageTypes[instance.Type].ScaleInLightmap; - return asFoliage; - } - } - } - for (Actor* child : actor->Children) - { - const auto other = FindActorByDrawCall(child, drawCall, scaleInLightmap); - if (other) - return other; - } - return nullptr; - } -} - void LightmapUVsDensityMaterialShader::Bind(BindParameters& params) { // Prepare @@ -121,33 +86,6 @@ void LightmapUVsDensityMaterialShader::Bind(BindParameters& params) _ps->Init(psDesc); } - // Find the static model that produced this draw call - const Actor* drawCallActor = nullptr; - float scaleInLightmap = 1.0f; - if (params.RenderContext.Task) - { - // Skip this lookup as it's too slow - - /*if (params.RenderContext.Task->ActorsSource & ActorsSources::CustomActors) - { - for (auto actor : params.RenderContext.Task->CustomActors) - { - drawCallActor = FindActorByDrawCall(actor, drawCall, scaleInLightmap); - if (drawCallActor) - break; - } - } - if (!drawCallActor && params.RenderContext.Task->ActorsSource & ActorsSources::Scenes) - { - for (auto& scene : Level::Scenes) - { - drawCallActor = FindActorByDrawCall(scene, drawCall, scaleInLightmap); - if (drawCallActor) - break; - } - }*/ - } - // Bind constants if (cb && cb->GetSize()) { @@ -166,19 +104,15 @@ void LightmapUVsDensityMaterialShader::Bind(BindParameters& params) data.LightmapSize = 1024.0f; data.LightmapArea = drawCall.Surface.LightmapUVsArea; const ModelLOD* drawCallModelLod; - if (GBufferPass::IndexBufferToModelLOD.TryGet(drawCall.Geometry.IndexBuffer, drawCallModelLod)) + float scaleInLightmap = drawCall.Surface.LODDitherFactor; // Reuse field + if (scaleInLightmap < 0.0f) + data.LightmapSize = -1.0f; // Not using lightmap + else if (GBufferPass::IndexBufferToModelLOD.TryGet(drawCall.Geometry.IndexBuffer, drawCallModelLod)) { // Calculate current lightmap slot size for the object (matches the ShadowsOfMordor calculations when baking the lighting) float globalObjectsScale = 1.0f; int32 atlasSize = 1024; int32 chartsPadding = 3; - const Scene* drawCallScene = drawCallActor ? drawCallActor->GetScene() : (Level::Scenes.Count() != 0 ? Level::Scenes[0] : nullptr); - if (drawCallScene) - { - globalObjectsScale = drawCallScene->Info.LightmapSettings.GlobalObjectsScale; - atlasSize = (int32)drawCallScene->Info.LightmapSettings.AtlasSize; - chartsPadding = drawCallScene->Info.LightmapSettings.ChartsPadding; - } BoundingBox box = drawCallModelLod->GetBox(drawCall.World); Float3 size = box.GetSize(); float dimensionsCoeff = size.AverageArithmetic(); diff --git a/Source/Engine/Terrain/TerrainChunk.cpp b/Source/Engine/Terrain/TerrainChunk.cpp index 6902b5d8d..12613e1f9 100644 --- a/Source/Engine/Terrain/TerrainChunk.cpp +++ b/Source/Engine/Terrain/TerrainChunk.cpp @@ -123,6 +123,10 @@ void TerrainChunk::Draw(const RenderContext& renderContext) const } drawCall.WorldDeterminantSign = Math::FloatSelect(drawCall.World.RotDeterminant(), 1, -1); drawCall.PerInstanceRandom = _perInstanceRandom; +#if USE_EDITOR + if (renderContext.View.Mode == ViewMode::LightmapUVsDensity) + drawCall.Surface.LODDitherFactor = 1.0f; // See LightmapUVsDensityMaterialShader +#endif // Add half-texel offset for heightmap sampling in vertex shader //const float lodHeightmapSize = Math::Max(1, drawCall.TerrainData.Heightmap->Width() >> lod); @@ -180,6 +184,10 @@ void TerrainChunk::Draw(const RenderContext& renderContext, MaterialBase* materi } drawCall.WorldDeterminantSign = Math::FloatSelect(drawCall.World.RotDeterminant(), 1, -1); drawCall.PerInstanceRandom = _perInstanceRandom; +#if USE_EDITOR + if (renderContext.View.Mode == ViewMode::LightmapUVsDensity) + drawCall.Surface.LODDitherFactor = 1.0f; // See LightmapUVsDensityMaterialShader +#endif // Add half-texel offset for heightmap sampling in vertex shader //const float lodHeightmapSize = Math::Max(1, drawCall.TerrainData.Heightmap->Width() >> lod); diff --git a/Source/Shaders/Editor/LightmapUVsDensity.shader b/Source/Shaders/Editor/LightmapUVsDensity.shader index b1fafd193..588332a00 100644 --- a/Source/Shaders/Editor/LightmapUVsDensity.shader +++ b/Source/Shaders/Editor/LightmapUVsDensity.shader @@ -98,7 +98,11 @@ void PS(in PixelInput input, out float4 Light : SV_Target0, out float4 RT0 : SV_ float3 minColor = float3(235/255.0, 52/255.0, 67/255.0); float3 bestColor = float3(51/255.0, 235/255.0, 70/255.0); float3 maxColor = float3(52/255.0, 149/255.0, 235/255.0); - if (density < bestDensity) + if (LightmapSize < 0.0f) + { + color = float3(52/255.0, 229/255.0, 235/255.0); // No lightmap + } + else if (density < bestDensity) { color = lerp(minColor, bestColor, (density - minDensity) / (bestDensity - minDensity)); }