**Refactor meshes format to support custom vertex layouts and new flexible api to access mesh data**

#3044 #2667
This commit is contained in:
Wojtek Figat
2025-01-06 22:47:19 +01:00
parent 29bfef677f
commit db4d7d2a05
65 changed files with 4428 additions and 3106 deletions

View File

@@ -18,18 +18,37 @@
#include "Engine/Content/Content.h"
#include "Engine/Core/Types/Variant.h"
#include "Engine/Graphics/RenderTools.h"
#include "Engine/Graphics/Shaders/GPUVertexLayout.h"
#include "Engine/Localization/Localization.h"
#if USE_EDITOR
#include "Editor/Editor.h"
#endif
PACK_STRUCT(struct TextRenderVertex
{
Float3 Position;
Color32 Color;
Float1010102 Normal;
Float1010102 Tangent;
Half2 TexCoord;
static GPUVertexLayout* GetLayout()
{
return GPUVertexLayout::Get({
{ VertexElement::Types::Position, 0, 0, 0, PixelFormat::R32G32B32_Float },
{ VertexElement::Types::Color, 0, 0, 0, PixelFormat::R8G8B8A8_UNorm },
{ VertexElement::Types::Normal, 0, 0, 0, PixelFormat::R10G10B10A2_UNorm },
{ VertexElement::Types::Tangent, 0, 0, 0, PixelFormat::R10G10B10A2_UNorm },
{ VertexElement::Types::TexCoord, 0, 0, 0, PixelFormat::R16G16_Float },
});
}
});
TextRender::TextRender(const SpawnParams& params)
: Actor(params)
, _size(32)
, _ib(0, sizeof(uint16))
, _vb0(0, sizeof(VB0ElementType), String::Empty, VB0ElementType::GetLayout())
, _vb1(0, sizeof(VB1ElementType), String::Empty, VB1ElementType::GetLayout())
, _vb2(0, sizeof(VB2ElementType), String::Empty, VB2ElementType::GetLayout())
, _vb(0, sizeof(TextRenderVertex), String::Empty, TextRenderVertex::GetLayout())
{
_color = Color::White;
_localBox = BoundingBox(Vector3::Zero);
@@ -102,9 +121,7 @@ void TextRender::UpdateLayout()
{
// Clear
_ib.Clear();
_vb0.Clear();
_vb1.Clear();
_vb2.Clear();
_vb.Clear();
_localBox = BoundingBox(Vector3::Zero);
BoundingBox::Transform(_localBox, _transform, _box);
BoundingSphere::FromBox(_box, _sphere);
@@ -163,9 +180,7 @@ void TextRender::UpdateLayout()
// Prepare buffers capacity
_ib.Data.EnsureCapacity(text.Length() * 6 * sizeof(uint16));
_vb0.Data.EnsureCapacity(text.Length() * 4 * sizeof(VB0ElementType));
_vb1.Data.EnsureCapacity(text.Length() * 4 * sizeof(VB1ElementType));
_vb2.Data.EnsureCapacity(text.Length() * 4 * sizeof(VB2ElementType));
_vb.Data.EnsureCapacity(text.Length() * 4 * sizeof(TextRenderVertex));
_buffersDirty = true;
// Init draw chunks data
@@ -268,20 +283,15 @@ void TextRender::UpdateLayout()
byte sign = 0;
// Write vertices
VB0ElementType vb0;
VB1ElementType vb1;
VB2ElementType vb2;
TextRenderVertex v;
#define WRITE_VB(pos, uv) \
vb0.Position = Float3(-pos, 0.0f); \
box.Merge(vb0.Position); \
_vb0.Write(vb0); \
vb1.TexCoord = Half2(uv); \
vb1.Normal = Float1010102(normal * 0.5f + 0.5f, 0); \
vb1.Tangent = Float1010102(tangent * 0.5f + 0.5f, sign); \
vb1.LightmapUVs = Half2::Zero; \
_vb1.Write(vb1); \
vb2.Color = color; \
_vb2.Write(vb2)
v.Position = Float3(-pos, 0.0f); \
box.Merge(v.Position); \
v.TexCoord = Half2(uv); \
v.Normal = Float1010102(normal * 0.5f + 0.5f, 0); \
v.Tangent = Float1010102(tangent * 0.5f + 0.5f, sign); \
v.Color = color; \
_vb.Write(v)
//
WRITE_VB(charRect.GetBottomRight(), rightBottomUV);
WRITE_VB(charRect.GetBottomLeft(), Float2(upperLeftUV.X, rightBottomUV.Y));
@@ -317,7 +327,7 @@ void TextRender::UpdateLayout()
#if MODEL_USE_PRECISE_MESH_INTERSECTS
// Setup collision proxy for detailed collision detection for triangles
const int32 totalIndicesCount = _ib.Data.Count() / sizeof(uint16);
_collisionProxy.Init(_vb0.Data.Count() / sizeof(Float3), totalIndicesCount / 3, (Float3*)_vb0.Data.Get(), (uint16*)_ib.Data.Get());
_collisionProxy.Init(_vb.Data.Count() / sizeof(TextRenderVertex), totalIndicesCount / 3, (const Float3*)_vb.Data.Get(), (const uint16*)_ib.Data.Get(), sizeof(TextRenderVertex));
#endif
// Update text bounds (from build vertex positions)
@@ -351,16 +361,14 @@ void TextRender::Draw(RenderContext& renderContext)
GEOMETRY_DRAW_STATE_EVENT_BEGIN(_drawState, world);
const DrawPass drawModes = DrawModes & renderContext.View.Pass & renderContext.View.GetShadowsDrawPassMask(ShadowsMode);
if (_vb0.Data.Count() > 0 && drawModes != DrawPass::None)
if (_vb.Data.Count() > 0 && drawModes != DrawPass::None)
{
// Flush buffers
if (_buffersDirty)
{
_buffersDirty = false;
_ib.Flush();
_vb0.Flush();
_vb1.Flush();
_vb2.Flush();
_vb.Flush();
}
// Setup draw call
@@ -373,9 +381,7 @@ void TextRender::Draw(RenderContext& renderContext)
drawCall.WorldDeterminantSign = RenderTools::GetWorldDeterminantSign(drawCall.World);
drawCall.PerInstanceRandom = GetPerInstanceRandom();
drawCall.Geometry.IndexBuffer = _ib.GetBuffer();
drawCall.Geometry.VertexBuffers[0] = _vb0.GetBuffer();
drawCall.Geometry.VertexBuffers[1] = _vb1.GetBuffer();
drawCall.Geometry.VertexBuffers[2] = _vb2.GetBuffer();
drawCall.Geometry.VertexBuffers[0] = _vb.GetBuffer();
drawCall.InstanceCount = 1;
// Submit draw calls