Merge branch '1.1' of https://github.com/FlaxEngine/FlaxEngine into network
This commit is contained in:
@@ -20,6 +20,8 @@
|
||||
#include "Engine/Animations/AnimationUtils.h"
|
||||
#include "Engine/Profiler/Profiler.h"
|
||||
#include "Engine/Debug/DebugLog.h"
|
||||
#include "Engine/Render2D/Render2D.h"
|
||||
#include "Engine/Render2D/FontAsset.h"
|
||||
|
||||
// Debug draw service configuration
|
||||
#define DEBUG_DRAW_INITIAL_VB_CAPACITY (4 * 1024)
|
||||
@@ -54,6 +56,25 @@ struct DebugTriangle
|
||||
float TimeLeft;
|
||||
};
|
||||
|
||||
struct DebugText2D
|
||||
{
|
||||
Array<Char, InlinedAllocation<64>> Text;
|
||||
Vector2 Position;
|
||||
int32 Size;
|
||||
Color Color;
|
||||
float TimeLeft;
|
||||
};
|
||||
|
||||
struct DebugText3D
|
||||
{
|
||||
Array<Char, InlinedAllocation<64>> Text;
|
||||
Transform Transform;
|
||||
bool FaceCamera;
|
||||
int32 Size;
|
||||
Color Color;
|
||||
float TimeLeft;
|
||||
};
|
||||
|
||||
PACK_STRUCT(struct Vertex {
|
||||
Vector3 Position;
|
||||
Color32 Color;
|
||||
@@ -133,10 +154,14 @@ struct DebugDrawData
|
||||
Array<DebugTriangle> OneFrameTriangles;
|
||||
Array<DebugTriangle> DefaultWireTriangles;
|
||||
Array<DebugTriangle> OneFrameWireTriangles;
|
||||
Array<DebugText2D> DefaultText2D;
|
||||
Array<DebugText2D> OneFrameText2D;
|
||||
Array<DebugText3D> DefaultText3D;
|
||||
Array<DebugText3D> OneFrameText3D;
|
||||
|
||||
inline int32 Count() const
|
||||
{
|
||||
return LinesCount() + TrianglesCount();
|
||||
return LinesCount() + TrianglesCount() + TextCount();
|
||||
}
|
||||
|
||||
inline int32 LinesCount() const
|
||||
@@ -149,6 +174,11 @@ struct DebugDrawData
|
||||
return DefaultTriangles.Count() + OneFrameTriangles.Count() + DefaultWireTriangles.Count() + OneFrameWireTriangles.Count();
|
||||
}
|
||||
|
||||
inline int32 TextCount() const
|
||||
{
|
||||
return DefaultText2D.Count() + OneFrameText2D.Count() + DefaultText3D.Count() + OneFrameText3D.Count();
|
||||
}
|
||||
|
||||
inline void Add(const DebugLine& l)
|
||||
{
|
||||
if (l.TimeLeft > 0)
|
||||
@@ -178,10 +208,14 @@ struct DebugDrawData
|
||||
UpdateList(deltaTime, DefaultLines);
|
||||
UpdateList(deltaTime, DefaultTriangles);
|
||||
UpdateList(deltaTime, DefaultWireTriangles);
|
||||
UpdateList(deltaTime, DefaultText2D);
|
||||
UpdateList(deltaTime, DefaultText3D);
|
||||
|
||||
OneFrameLines.Clear();
|
||||
OneFrameTriangles.Clear();
|
||||
OneFrameWireTriangles.Clear();
|
||||
OneFrameText2D.Clear();
|
||||
OneFrameText3D.Clear();
|
||||
}
|
||||
|
||||
inline void Clear()
|
||||
@@ -192,6 +226,10 @@ struct DebugDrawData
|
||||
OneFrameTriangles.Clear();
|
||||
DefaultWireTriangles.Clear();
|
||||
OneFrameWireTriangles.Clear();
|
||||
DefaultText2D.Clear();
|
||||
OneFrameText2D.Clear();
|
||||
DefaultText3D.Clear();
|
||||
OneFrameText3D.Clear();
|
||||
}
|
||||
|
||||
inline void Release()
|
||||
@@ -202,6 +240,10 @@ struct DebugDrawData
|
||||
OneFrameTriangles.Resize(0);
|
||||
DefaultWireTriangles.Resize(0);
|
||||
OneFrameWireTriangles.Resize(0);
|
||||
DefaultText2D.Resize(0);
|
||||
OneFrameText2D.Resize(0);
|
||||
DefaultText3D.Resize(0);
|
||||
OneFrameText3D.Resize(0);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -216,6 +258,7 @@ namespace
|
||||
DebugDrawContext GlobalContext;
|
||||
DebugDrawContext* Context;
|
||||
AssetReference<Shader> DebugDrawShader;
|
||||
AssetReference<FontAsset> DebugDrawFont;
|
||||
PsData DebugDrawPsLinesDefault;
|
||||
PsData DebugDrawPsLinesDepthTest;
|
||||
PsData DebugDrawPsWireTrianglesDefault;
|
||||
@@ -299,6 +342,21 @@ DebugDrawCall WriteLists(int32& vertexCounter, const Array<T>& listA, const Arra
|
||||
return drawCall;
|
||||
}
|
||||
|
||||
inline void DrawText3D(const DebugText3D& t, const RenderContext& renderContext, const Vector3& viewUp, const Matrix& f, const Matrix& vp, const Viewport& viewport, GPUContext* context, GPUTextureView* target, GPUTextureView* depthBuffer)
|
||||
{
|
||||
Matrix w, fw, m;
|
||||
if (t.FaceCamera)
|
||||
Matrix::CreateWorld(t.Transform.Translation, renderContext.View.Direction, viewUp, w);
|
||||
else
|
||||
t.Transform.GetWorld(w);
|
||||
Matrix::Multiply(f, w, fw);
|
||||
Matrix::Multiply(fw, vp, m);
|
||||
Render2D::Begin(context, target, depthBuffer, viewport, m);
|
||||
const StringView text(t.Text.Get(), t.Text.Count() - 1);
|
||||
Render2D::DrawText(DebugDrawFont->CreateFont(t.Size), text, t.Color, Vector2::Zero);
|
||||
Render2D::End();
|
||||
}
|
||||
|
||||
class DebugDrawService : public EngineService
|
||||
{
|
||||
public:
|
||||
@@ -569,7 +627,7 @@ void DebugDraw::Draw(RenderContext& renderContext, GPUTextureView* target, GPUTe
|
||||
return;
|
||||
auto context = GPUDevice::Instance->GetMainContext();
|
||||
|
||||
// Fallback to task backbuffer
|
||||
// Fallback to task buffers
|
||||
if (target == nullptr && renderContext.Task)
|
||||
target = renderContext.Task->GetOutputView();
|
||||
|
||||
@@ -601,8 +659,6 @@ void DebugDraw::Draw(RenderContext& renderContext, GPUTextureView* target, GPUTe
|
||||
context->BindCB(0, cb);
|
||||
auto vb = DebugDrawVB->GetBuffer();
|
||||
|
||||
#define DRAW(drawCall) if (drawCall.VertexCount)
|
||||
|
||||
// Draw with depth test
|
||||
if (depthTestLines.VertexCount + depthTestTriangles.VertexCount + depthTestWireTriangles.VertexCount > 0)
|
||||
{
|
||||
@@ -673,7 +729,50 @@ void DebugDraw::Draw(RenderContext& renderContext, GPUTextureView* target, GPUTe
|
||||
}
|
||||
}
|
||||
|
||||
#undef DRAW
|
||||
// Text
|
||||
if (Context->DebugDrawDefault.TextCount() + Context->DebugDrawDepthTest.TextCount())
|
||||
{
|
||||
PROFILE_GPU_CPU_NAMED("Text");
|
||||
auto features = Render2D::Features;
|
||||
Render2D::Features = (Render2D::RenderingFeatures)((uint32)features & ~(uint32)Render2D::RenderingFeatures::VertexSnapping);
|
||||
|
||||
if (!DebugDrawFont)
|
||||
DebugDrawFont = Content::LoadAsyncInternal<FontAsset>(TEXT("Editor/Fonts/Roboto-Regular"));
|
||||
if (DebugDrawFont && DebugDrawFont->IsLoaded())
|
||||
{
|
||||
Viewport viewport = renderContext.Task->GetViewport();
|
||||
|
||||
if (Context->DebugDrawDefault.DefaultText2D.Count() + Context->DebugDrawDefault.OneFrameText2D.Count())
|
||||
{
|
||||
Render2D::Begin(context, target, nullptr, viewport);
|
||||
for (auto& t : Context->DebugDrawDefault.DefaultText2D)
|
||||
{
|
||||
const StringView text(t.Text.Get(), t.Text.Count() - 1);
|
||||
Render2D::DrawText(DebugDrawFont->CreateFont(t.Size), text, t.Color, t.Position);
|
||||
}
|
||||
for (auto& t : Context->DebugDrawDefault.OneFrameText2D)
|
||||
{
|
||||
const StringView text(t.Text.Get(), t.Text.Count() - 1);
|
||||
Render2D::DrawText(DebugDrawFont->CreateFont(t.Size), text, t.Color, t.Position);
|
||||
}
|
||||
Render2D::End();
|
||||
}
|
||||
|
||||
if (Context->DebugDrawDefault.DefaultText3D.Count() + Context->DebugDrawDefault.OneFrameText3D.Count())
|
||||
{
|
||||
Matrix f;
|
||||
Matrix::RotationZ(PI, f);
|
||||
Vector3 viewUp;
|
||||
Vector3::Transform(Vector3::Up, Quaternion::LookRotation(renderContext.View.Direction, Vector3::Up), viewUp);
|
||||
for (auto& t : Context->DebugDrawDefault.DefaultText3D)
|
||||
DrawText3D(t, renderContext, viewUp, f, vp, viewport, context, target, nullptr);
|
||||
for (auto& t : Context->DebugDrawDefault.OneFrameText3D)
|
||||
DrawText3D(t, renderContext, viewUp, f, vp, viewport, context, target, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
Render2D::Features = features;
|
||||
}
|
||||
}
|
||||
|
||||
void DebugDraw::DrawActors(Actor** selectedActors, int32 selectedActorsCount, bool drawScenes)
|
||||
@@ -1276,4 +1375,51 @@ void DebugDraw::DrawBox(const OrientedBoundingBox& box, const Color& color, floa
|
||||
}
|
||||
}
|
||||
|
||||
void DebugDraw::DrawText(const StringView& text, const Vector2& position, const Color& color, int32 size, float duration)
|
||||
{
|
||||
if (text.Length() == 0 || size < 4)
|
||||
return;
|
||||
Array<DebugText2D>* list = duration > 0 ? &Context->DebugDrawDefault.DefaultText2D : &Context->DebugDrawDefault.OneFrameText2D;
|
||||
auto& t = list->AddOne();
|
||||
t.Text.Resize(text.Length() + 1);
|
||||
Platform::MemoryCopy(t.Text.Get(), text.Get(), text.Length() * sizeof(Char));
|
||||
t.Text[text.Length()] = 0;
|
||||
t.Position = position;
|
||||
t.Size = size;
|
||||
t.Color = color;
|
||||
t.TimeLeft = duration;
|
||||
}
|
||||
|
||||
void DebugDraw::DrawText(const StringView& text, const Vector3& position, const Color& color, int32 size, float duration)
|
||||
{
|
||||
if (text.Length() == 0 || size < 4)
|
||||
return;
|
||||
Array<DebugText3D>* list = duration > 0 ? &Context->DebugDrawDefault.DefaultText3D : &Context->DebugDrawDefault.OneFrameText3D;
|
||||
auto& t = list->AddOne();
|
||||
t.Text.Resize(text.Length() + 1);
|
||||
Platform::MemoryCopy(t.Text.Get(), text.Get(), text.Length() * sizeof(Char));
|
||||
t.Text[text.Length()] = 0;
|
||||
t.Transform = position;
|
||||
t.FaceCamera = true;
|
||||
t.Size = size;
|
||||
t.Color = color;
|
||||
t.TimeLeft = duration;
|
||||
}
|
||||
|
||||
void DebugDraw::DrawText(const StringView& text, const Transform& transform, const Color& color, int32 size, float duration)
|
||||
{
|
||||
if (text.Length() == 0 || size < 4)
|
||||
return;
|
||||
Array<DebugText3D>* list = duration > 0 ? &Context->DebugDrawDefault.DefaultText3D : &Context->DebugDrawDefault.OneFrameText3D;
|
||||
auto& t = list->AddOne();
|
||||
t.Text.Resize(text.Length() + 1);
|
||||
Platform::MemoryCopy(t.Text.Get(), text.Get(), text.Length() * sizeof(Char));
|
||||
t.Text[text.Length()] = 0;
|
||||
t.Transform = transform;
|
||||
t.FaceCamera = false;
|
||||
t.Size = size;
|
||||
t.Color = color;
|
||||
t.TimeLeft = duration;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,6 +15,7 @@ class GPUContext;
|
||||
class RenderTask;
|
||||
class SceneRenderTask;
|
||||
class Actor;
|
||||
struct Transform;
|
||||
|
||||
/// <summary>
|
||||
/// The debug shapes rendering service. Not available in final game. For use only in the editor.
|
||||
@@ -307,6 +308,36 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(DebugDraw);
|
||||
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
|
||||
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
|
||||
API_FUNCTION() static void DrawBox(const OrientedBoundingBox& box, const Color& color, float duration = 0.0f, bool depthTest = true);
|
||||
|
||||
/// <summary>
|
||||
/// Draws the text on a screen (2D).
|
||||
/// </summary>
|
||||
/// <param name="text">The text.</param>
|
||||
/// <param name="position">The position of the text on the screen (in screen-space coordinates).</param>
|
||||
/// <param name="color">The color.</param>
|
||||
/// <param name="size">The font size.</param>
|
||||
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
|
||||
API_FUNCTION() static void DrawText(const StringView& text, const Vector2& position, const Color& color, int32 size = 20, float duration = 0.0f);
|
||||
|
||||
/// <summary>
|
||||
/// Draws the text (3D) that automatically faces the camera.
|
||||
/// </summary>
|
||||
/// <param name="text">The text.</param>
|
||||
/// <param name="position">The position of the text (world-space).</param>
|
||||
/// <param name="color">The color.</param>
|
||||
/// <param name="size">The font size.</param>
|
||||
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
|
||||
API_FUNCTION() static void DrawText(const StringView& text, const Vector3& position, const Color& color, int32 size = 32, float duration = 0.0f);
|
||||
|
||||
/// <summary>
|
||||
/// Draws the text (3D).
|
||||
/// </summary>
|
||||
/// <param name="text">The text.</param>
|
||||
/// <param name="transform">The transformation of the text (world-space).</param>
|
||||
/// <param name="color">The color.</param>
|
||||
/// <param name="size">The font size.</param>
|
||||
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
|
||||
API_FUNCTION() static void DrawText(const StringView& text, const Transform& transform, const Color& color, int32 size = 32, float duration = 0.0f);
|
||||
};
|
||||
|
||||
#define DEBUG_DRAW_LINE(start, end, color, duration, depthTest) DebugDraw::DrawLine(start, end, color, duration, depthTest)
|
||||
@@ -326,7 +357,8 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(DebugDraw);
|
||||
#define DEBUG_DRAW_WIRE_SPHERE(sphere, color, duration, depthTest) DebugDraw::DrawWireSphere(sphere, color, duration, depthTest)
|
||||
#define DEBUG_DRAW_WIRE_TUBE(position, orientation, radius, length, color, duration, depthTest) DebugDraw::DrawWireTube(position, orientation, radius, length, color, duration, depthTest)
|
||||
#define DEBUG_DRAW_WIRE_CYLINDER(position, orientation, radius, height, color, duration, depthTest) DebugDraw::DrawWireTube(position, orientation, radius, height, color, duration, depthTest)
|
||||
#define DEBUG_DRAW_WIRE_ARROW(position, orientation, scale, color, duration, depthTest) DebugDraw::DrawWireTube(position, orientation, scale, color, duration, depthTest)
|
||||
#define DEBUG_DRAW_WIRE_ARROW(position, orientation, scale, color, duration, depthTest) DebugDraw::DrawWireArrow(position, orientation, scale, color, duration, depthTest)
|
||||
#define DEBUG_DRAW_TEXT(text, position, color, size, duration) DebugDraw::DrawText(text, position, color, size, duration)
|
||||
|
||||
#else
|
||||
|
||||
@@ -348,5 +380,6 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(DebugDraw);
|
||||
#define DEBUG_DRAW_WIRE_TUBE(position, orientation, radius, length, color, duration, depthTest)
|
||||
#define DEBUG_DRAW_WIRE_CYLINDER(position, orientation, radius, height, color, duration, depthTest)
|
||||
#define DEBUG_DRAW_WIRE_ARROW(position, orientation, scale, color, duration, depthTest)
|
||||
#define DEBUG_DRAW_TEXT(text, position, color, size, duration)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -270,6 +270,34 @@ FORCE_INLINE Render2DVertex MakeVertex(const Vector2& point, const Vector2& uv,
|
||||
};
|
||||
}
|
||||
|
||||
void WriteTri(const Vector2& p0, const Vector2& p1, const Vector2& p2, const Vector2& uv0, const Vector2& uv1, const Vector2& uv2, const Color& color0, const Color& color1, const Color& color2)
|
||||
{
|
||||
Render2DVertex tris[3];
|
||||
tris[0] = MakeVertex(p0, uv0, color0);
|
||||
tris[1] = MakeVertex(p1, uv1, color1);
|
||||
tris[2] = MakeVertex(p2, uv2, color2);
|
||||
VB.Write(tris, sizeof(tris));
|
||||
|
||||
uint32 indices[3];
|
||||
indices[0] = VBIndex + 0;
|
||||
indices[1] = VBIndex + 1;
|
||||
indices[2] = VBIndex + 2;
|
||||
IB.Write(indices, sizeof(indices));
|
||||
|
||||
VBIndex += 3;
|
||||
IBIndex += 3;
|
||||
}
|
||||
|
||||
void WriteTri(const Vector2& p0, const Vector2& p1, const Vector2& p2, const Color& color0, const Color& color1, const Color& color2)
|
||||
{
|
||||
WriteTri(p0, p1, p2, Vector2::Zero, Vector2::Zero, Vector2::Zero, color0, color1, color2);
|
||||
}
|
||||
|
||||
void WriteTri(const Vector2& p0, const Vector2& p1, const Vector2& p2, const Vector2& uv0, const Vector2& uv1, const Vector2& uv2)
|
||||
{
|
||||
WriteTri(p0, p1, p2, uv0, uv1, uv2, Color::Black, Color::Black, Color::Black);
|
||||
}
|
||||
|
||||
void WriteRect(const Rectangle& rect, const Color& color1, const Color& color2, const Color& color3, const Color& color4)
|
||||
{
|
||||
const Vector2 uvUpperLeft = Vector2::Zero;
|
||||
@@ -1716,3 +1744,45 @@ void Render2D::DrawBlur(const Rectangle& rect, float blurStrength)
|
||||
drawCall.AsBlur.BottomRightY = p.Y;
|
||||
WriteRect(rect, Color::White);
|
||||
}
|
||||
|
||||
void Render2D::DrawTexturedTriangles(GPUTexture* t, const Span<Vector2>& vertices, const Span<Vector2>& uvs)
|
||||
{
|
||||
CHECK(vertices.Length() == uvs.Length())
|
||||
|
||||
RENDER2D_CHECK_RENDERING_STATE;
|
||||
|
||||
Render2DDrawCall& drawCall = DrawCalls.AddOne();
|
||||
drawCall.Type = DrawCallType::FillTexture;
|
||||
drawCall.StartIB = IBIndex;
|
||||
drawCall.CountIB = vertices.Length();
|
||||
drawCall.AsTexture.Ptr = t;
|
||||
|
||||
for (int32 i = 0; i < vertices.Length(); i += 3)
|
||||
WriteTri(vertices[i], vertices[i + 1], vertices[i + 2], uvs[i], uvs[i + 1], uvs[i + 2]);
|
||||
}
|
||||
|
||||
void Render2D::FillTriangles(const Span<Vector2>& vertices, const Span<Color>& colors, bool useAlpha)
|
||||
{
|
||||
CHECK(vertices.Length() == colors.Length());
|
||||
|
||||
RENDER2D_CHECK_RENDERING_STATE;
|
||||
|
||||
Render2DDrawCall& drawCall = DrawCalls.AddOne();
|
||||
drawCall.Type = useAlpha ? DrawCallType::FillRect : DrawCallType::FillRectNoAlpha;
|
||||
drawCall.StartIB = IBIndex;
|
||||
drawCall.CountIB = vertices.Length();
|
||||
|
||||
for (int32 i = 0; i < vertices.Length(); i += 3)
|
||||
WriteTri(vertices[i], vertices[i + 1], vertices[i + 2], colors[i], colors[i + 1], colors[i + 2]);
|
||||
}
|
||||
|
||||
void Render2D::FillTriangle(const Vector2& p0, const Vector2& p1, const Vector2& p2, const Color& color)
|
||||
{
|
||||
RENDER2D_CHECK_RENDERING_STATE;
|
||||
|
||||
Render2DDrawCall& drawCall = DrawCalls.AddOne();
|
||||
drawCall.Type = color.A < 1.0f ? DrawCallType::FillRect : DrawCallType::FillRectNoAlpha;
|
||||
drawCall.StartIB = IBIndex;
|
||||
drawCall.CountIB = 3;
|
||||
WriteTri(p0, p1, p2, color, color, color);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "Engine/Core/Math/Color.h"
|
||||
#include "Engine/Scripting/ScriptingType.h"
|
||||
#include "Engine/Core/Types/Span.h"
|
||||
|
||||
struct SpriteHandle;
|
||||
struct TextLayoutOptions;
|
||||
@@ -339,4 +340,29 @@ public:
|
||||
/// <param name="rect">The target rectangle to draw (blurs its background).</param>
|
||||
/// <param name="blurStrength">The blur strength defines how blurry the background is. Larger numbers increase blur, resulting in a larger runtime cost on the GPU.</param>
|
||||
API_FUNCTION() static void DrawBlur(const Rectangle& rect, float blurStrength);
|
||||
|
||||
/// <summary>
|
||||
/// Draws vertices array.
|
||||
/// </summary>
|
||||
/// <param name="t">The texture.</param>
|
||||
/// <param name="vertices">The vertices array.</param>
|
||||
/// <param name="uvs">The uvs array.</param>
|
||||
API_FUNCTION() static void DrawTexturedTriangles(GPUTexture* t, const Span<Vector2>& vertices, const Span<Vector2>& uvs);
|
||||
|
||||
/// <summary>
|
||||
/// Draws vertices array.
|
||||
/// </summary>
|
||||
/// <param name="vertices">The vertices array.</param>
|
||||
/// <param name="colors">The colors array.</param>
|
||||
/// <param name="useAlpha">If true alpha blending will be enabled.</param>
|
||||
API_FUNCTION() static void FillTriangles(const Span<Vector2>& vertices, const Span<Color>& colors, bool useAlpha);
|
||||
|
||||
/// <summary>
|
||||
/// Fills a triangular area.
|
||||
/// </summary>
|
||||
/// <param name="p0">The first point.</param>
|
||||
/// <param name="p1">The second point.</param>
|
||||
/// <param name="p2">The third point.</param>
|
||||
/// <param name="color">The color.</param>
|
||||
API_FUNCTION() static void FillTriangle(const Vector2& p0, const Vector2& p1, const Vector2& p2, const Color& color);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user