Fix lightmap uvs density view to handle scale in lightmap and outline non-static objects

#2080
This commit is contained in:
Wojtek Figat
2024-09-09 05:59:17 +02:00
parent fc9aa5c184
commit 545e59aba5
9 changed files with 42 additions and 76 deletions

Binary file not shown.

View File

@@ -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))
{

View File

@@ -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

View File

@@ -241,5 +241,9 @@ public:
/// The object sorting key.
/// </summary>
int16 SortOrder;
#if USE_EDITOR
float LightmapScale = -1.0f;
#endif
};
};

View File

@@ -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();

View File

@@ -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);

View File

@@ -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<StaticModel>(actor);
if (asStaticModel && asStaticModel->GetPerInstanceRandom() == drawCall.PerInstanceRandom && asStaticModel->GetPosition() == drawCall.ObjectPosition)
{
scaleInLightmap = asStaticModel->GetScaleInLightmap();
return asStaticModel;
}
const auto asFoliage = ScriptingObject::Cast<Foliage>(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();

View File

@@ -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);

View File

@@ -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));
}