Add LOD Preview debug view mode

This commit is contained in:
Wojtek Figat
2021-09-30 23:48:48 +02:00
parent 0e8987b654
commit 3dff9196c2
8 changed files with 318 additions and 42 deletions

View File

@@ -813,6 +813,11 @@ API_ENUM() enum class ViewMode
/// Draw physics colliders debug view
/// </summary>
PhysicsColliders = 20,
/// <summary>
/// Draw Level Of Detail number as colors to debug LOD switches.
/// </summary>
LODPreview = 21,
};
/// <summary>

View File

@@ -0,0 +1,127 @@
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
#if USE_EDITOR
#include "LODPreview.h"
#include "Engine/Content/Content.h"
#include "Engine/Content/Assets/Model.h"
#include "Engine/Graphics/GPUDevice.h"
#include "Engine/Graphics/GPUPipelineState.h"
#include "Engine/Graphics/Shaders/GPUShader.h"
#include "Engine/Graphics/Shaders/GPUConstantBuffer.h"
#include "Engine/Graphics/RenderTask.h"
#include "Engine/Renderer/DrawCall.h"
PACK_STRUCT(struct LODPreviewMaterialShaderData {
Matrix ViewProjectionMatrix;
Matrix WorldMatrix;
Color Color;
Vector3 WorldInvScale;
float LODDitherFactor;
});
LODPreviewMaterialShader::LODPreviewMaterialShader()
{
_ps = GPUDevice::Instance->CreatePipelineState();
_shader = Content::LoadAsyncInternal<Shader>(TEXT("Shaders/Editor/LODPreview"));
if (!_shader)
return;
#if COMPILE_WITH_DEV_ENV
_shader.Get()->OnReloading.Bind<LODPreviewMaterialShader, &LODPreviewMaterialShader::OnShaderReloading>(this);
#endif
}
#if COMPILE_WITH_DEV_ENV
void LODPreviewMaterialShader::OnShaderReloading(Asset* obj)
{
_ps->ReleaseGPU();
}
#endif
const MaterialInfo& LODPreviewMaterialShader::GetInfo() const
{
return _info;
}
bool LODPreviewMaterialShader::IsReady() const
{
return _shader && _shader->IsLoaded();
}
DrawPass LODPreviewMaterialShader::GetDrawModes() const
{
return DrawPass::GBuffer;
}
void LODPreviewMaterialShader::Bind(BindParameters& params)
{
auto context = params.GPUContext;
auto& drawCall = *params.FirstDrawCall;
auto shader = _shader->GetShader();
auto cb = shader->GetCB(0);
if (!_ps->IsValid())
{
auto psDesc = GPUPipelineState::Description::Default;
psDesc.VS = shader->GetVS("VS");
psDesc.PS = shader->GetPS("PS");
_ps->Init(psDesc);
}
// Find the LOD that produced this draw call
int32 lodIndex = 0;
for (auto& e : Content::GetAssetsRaw())
{
auto model = ScriptingObject::Cast<Model>(e.Value);
if (!model)
continue;
bool found = false;
for (const auto& lod : model->LODs)
{
for (const auto& mesh : lod.Meshes)
{
if (mesh.GetIndexBuffer() == drawCall.Geometry.IndexBuffer)
{
lodIndex = mesh.GetLODIndex();
found = true;
break;
}
}
}
if (found)
break;
}
// Bind
if (cb && cb->GetSize())
{
ASSERT(cb->GetSize() == sizeof(LODPreviewMaterialShaderData));
LODPreviewMaterialShaderData data;
Matrix::Transpose(params.RenderContext.View.Frustum.GetMatrix(), data.ViewProjectionMatrix);
Matrix::Transpose(drawCall.World, data.WorldMatrix);
const float scaleX = Vector3(drawCall.World.M11, drawCall.World.M12, drawCall.World.M13).Length();
const float scaleY = Vector3(drawCall.World.M21, drawCall.World.M22, drawCall.World.M23).Length();
const float scaleZ = Vector3(drawCall.World.M31, drawCall.World.M32, drawCall.World.M33).Length();
data.WorldInvScale = Vector3(
scaleX > 0.00001f ? 1.0f / scaleX : 0.0f,
scaleY > 0.00001f ? 1.0f / scaleY : 0.0f,
scaleZ > 0.00001f ? 1.0f / scaleZ : 0.0f);
const Color colors[MODEL_MAX_LODS] = {
Color::White,
Color::Red,
Color::Orange,
Color::Yellow,
Color::Green,
Color::Blue,
};
ASSERT(lodIndex < MODEL_MAX_LODS);
data.Color = colors[lodIndex];
data.LODDitherFactor = drawCall.Surface.LODDitherFactor;
context->UpdateCB(cb, &data);
context->BindCB(0, cb);
}
context->SetState(_ps);
}
#endif

View File

@@ -0,0 +1,47 @@
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
#pragma once
#if USE_EDITOR
#include "Engine/Content/AssetReference.h"
#include "Engine/Content/Assets/Shader.h"
#include "Engine/Content/Assets/Texture.h"
#include "Engine/Graphics/Materials/IMaterial.h"
class GPUPipelineState;
/// <summary>
/// Rendering Level Of Detail number as colors to debug LOD switches in editor.
/// </summary>
class LODPreviewMaterialShader : public IMaterial
{
private:
AssetReference<Shader> _shader;
GPUPipelineState* _ps = nullptr;
MaterialInfo _info;
public:
LODPreviewMaterialShader();
virtual ~LODPreviewMaterialShader()
{
}
private:
#if COMPILE_WITH_DEV_ENV
void OnShaderReloading(Asset* obj);
#endif
public:
// [IMaterial]
const MaterialInfo& GetInfo() const override;
bool IsReady() const override;
DrawPass GetDrawModes() const override;
void Bind(BindParameters& params) override;
};
#endif

View File

@@ -2,8 +2,11 @@
#include "GBufferPass.h"
#include "RenderList.h"
#if USE_EDITOR
#include "Engine/Renderer/Editor/VertexColors.h"
#include "Engine/Renderer/Editor/LightmapUVsDensity.h"
#include "Engine/Renderer/Editor/LODPreview.h"
#endif
#include "Engine/Core/Collections/Sorting.h"
#include "Engine/Graphics/GPUDevice.h"
#include "Engine/Graphics/GPUContext.h"
@@ -87,11 +90,37 @@ void GBufferPass::Dispose()
_skyModel = nullptr;
_boxModel = nullptr;
#if USE_EDITOR
SAFE_DELETE(_lightmapUVsDensityMaterialShader);
SAFE_DELETE(_vertexColorsMaterialShader);
SAFE_DELETE(_lightmapUVsDensity);
SAFE_DELETE(_vertexColors);
SAFE_DELETE(_lodPreview);
#endif
}
#if USE_EDITOR
void DebugOverrideDrawCallsMaterial(RenderContext& renderContext, IMaterial* material)
{
if (material->IsReady())
{
auto& drawCallsList = renderContext.List->DrawCallsLists[(int32)DrawCallsListType::GBuffer];
for (int32 i : drawCallsList.Indices)
{
auto& drawCall = renderContext.List->DrawCalls[i];
if (drawCall.Material->IsSurface())
{
drawCall.Material = material;
}
}
IMaterial::InstancingHandler handler;
if (!material->CanUseInstancing(handler))
{
drawCallsList.CanUseInstancing = false;
}
}
}
#endif
void GBufferPass::Fill(RenderContext& renderContext, GPUTextureView* lightBuffer)
{
PROFILE_GPU_CPU("GBuffer");
@@ -133,47 +162,21 @@ void GBufferPass::Fill(RenderContext& renderContext, GPUTextureView* lightBuffer
// Override draw calls material to use material debug shader
if (renderContext.View.Mode == ViewMode::LightmapUVsDensity)
{
if (!_lightmapUVsDensityMaterialShader)
_lightmapUVsDensityMaterialShader = New<LightmapUVsDensityMaterialShader>();
if (_lightmapUVsDensityMaterialShader->IsReady())
{
auto& drawCallsList = renderContext.List->DrawCallsLists[(int32)DrawCallsListType::GBuffer];
for (int32 i : drawCallsList.Indices)
{
auto& drawCall = renderContext.List->DrawCalls[i];
if (drawCall.Material->IsSurface())
{
drawCall.Material = _lightmapUVsDensityMaterialShader;
}
}
IMaterial::InstancingHandler handler;
if (!_lightmapUVsDensityMaterialShader->CanUseInstancing(handler))
{
drawCallsList.CanUseInstancing = false;
}
}
if (!_lightmapUVsDensity)
_lightmapUVsDensity = New<LightmapUVsDensityMaterialShader>();
DebugOverrideDrawCallsMaterial(renderContext, _lightmapUVsDensity);
}
else if (renderContext.View.Mode == ViewMode::VertexColors)
{
if (!_vertexColorsMaterialShader)
_vertexColorsMaterialShader = New<VertexColorsMaterialShader>();
if (_vertexColorsMaterialShader->IsReady())
{
auto& drawCallsList = renderContext.List->DrawCallsLists[(int32)DrawCallsListType::GBuffer];
for (int32 i : drawCallsList.Indices)
{
auto& drawCall = renderContext.List->DrawCalls[i];
if (drawCall.Material->IsSurface())
{
drawCall.Material = _vertexColorsMaterialShader;
}
}
IMaterial::InstancingHandler handler;
if (!_vertexColorsMaterialShader->CanUseInstancing(handler))
{
drawCallsList.CanUseInstancing = false;
}
}
if (!_vertexColors)
_vertexColors = New<VertexColorsMaterialShader>();
DebugOverrideDrawCallsMaterial(renderContext, _vertexColors);
}
else if (renderContext.View.Mode == ViewMode::LODPreview)
{
if (!_lodPreview)
_lodPreview = New<LODPreviewMaterialShader>();
DebugOverrideDrawCallsMaterial(renderContext, _lodPreview);
}
if (renderContext.View.Mode == ViewMode::PhysicsColliders)
{

View File

@@ -16,8 +16,9 @@ private:
AssetReference<Model> _skyModel;
AssetReference<Model> _boxModel;
#if USE_EDITOR
class LightmapUVsDensityMaterialShader* _lightmapUVsDensityMaterialShader = nullptr;
class VertexColorsMaterialShader* _vertexColorsMaterialShader = nullptr;
class LightmapUVsDensityMaterialShader* _lightmapUVsDensity = nullptr;
class VertexColorsMaterialShader* _vertexColors = nullptr;
class LODPreviewMaterialShader* _lodPreview = nullptr;
#endif
public: