diff --git a/Editor/Editor/EditorLayer.cpp b/Editor/Editor/EditorLayer.cpp index fb8dd41..78ef6cb 100644 --- a/Editor/Editor/EditorLayer.cpp +++ b/Editor/Editor/EditorLayer.cpp @@ -227,13 +227,25 @@ namespace Prism if (selection.Entity.HasComponent()) { - const auto& size = selection.Entity.GetComponent().Size; + const auto& collider = selection.Entity.GetComponent(); const auto& transform = selection.Entity.GetComponent(); Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false); const auto viewProj = m_EditorCamera.GetViewProjection(); Renderer2D::BeginScene(viewProj, false); - Renderer2D::DrawRotatedQuad({ transform.Translation.x, transform.Translation.y }, size * 2.0f, transform.Rotation.z, { 1.0f, 0.0f, 1.0f, 1.0f }); + Renderer2D::DrawRotatedRect({ transform.Translation.x + collider.Offset.x, transform.Translation.y + collider.Offset.y }, collider.Size * 2.0f, transform.Rotation.z, { 0.0f, 0.0f, 1.0f, 1.0f }); + Renderer2D::EndScene(); + Renderer::EndRenderPass(); + } + if (selection.Entity.HasComponent()) + { + const auto& collider = selection.Entity.GetComponent(); + const TransformComponent& transform = selection.Entity.GetComponent(); + + Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false); + const auto viewProj = m_EditorCamera.GetViewProjection(); + Renderer2D::BeginScene(viewProj, false); + Renderer2D::DrawCircle({ transform.Translation.x + collider.Offset.x, transform.Translation.y + collider.Offset.y}, collider.Radius, { 0.0f, 1.0f, 1.0f, 1.0f }); Renderer2D::EndScene(); Renderer::EndRenderPass(); } diff --git a/Editor/assets/shaders/Renderer2D_Circle.glsl b/Editor/assets/shaders/Renderer2D_Circle.glsl new file mode 100644 index 0000000..bbac2cf --- /dev/null +++ b/Editor/assets/shaders/Renderer2D_Circle.glsl @@ -0,0 +1,44 @@ +// Basic Texture Shader + +#type vertex +#version 430 core + +layout(location = 0) in vec3 a_WorldPosition; +layout(location = 1) in float a_Thickness; +layout(location = 2) in vec2 a_LocalPosition; +layout(location = 3) in vec4 a_Color; +uniform mat4 u_ViewProjection; + +out vec2 v_LocalPosition; +out float v_Thickness; +out vec4 v_Color; + +void main() +{ + v_LocalPosition = a_LocalPosition; + v_Thickness = a_Thickness; + v_Color = a_Color; + gl_Position = u_ViewProjection * vec4(a_WorldPosition, 1.0); +} + +#type fragment +#version 430 core + +layout(location = 0) out vec4 color; + +in vec2 v_LocalPosition; +in float v_Thickness; +in vec4 v_Color; + +void main() +{ + float fade = 0.01; + float dist = sqrt(dot(v_LocalPosition, v_LocalPosition)); + if (dist > 1.0 || dist < 1.0 - v_Thickness - fade) + discard; + + float alpha = 1.0 - smoothstep(1.0f - fade, 1.0f, dist); + alpha *= smoothstep(1.0 - v_Thickness - fade, 1.0 - v_Thickness, dist); + color = v_Color; + color.a = alpha; +} \ No newline at end of file diff --git a/Prism/src/Prism/Core/ImGui/ImGui.h b/Prism/src/Prism/Core/ImGui/ImGui.h index 7a08667..579a11b 100644 --- a/Prism/src/Prism/Core/ImGui/ImGui.h +++ b/Prism/src/Prism/Core/ImGui/ImGui.h @@ -176,7 +176,7 @@ namespace Prism::UI { s_IDBuffer[1] = '#'; memset(s_IDBuffer + 2, 0, 14); snprintf(s_IDBuffer + 2, 14, "%x", s_Counter++); - if (ImGui::DragFloat3(s_IDBuffer, glm::value_ptr(value), delta)) + if (ImGui::DragFloat2(s_IDBuffer, glm::value_ptr(value), delta)) modified = true; ImGui::PopItemWidth(); diff --git a/Prism/src/Prism/Renderer/Renderer2D.cpp b/Prism/src/Prism/Renderer/Renderer2D.cpp index 0a9d33e..6dafaa6 100644 --- a/Prism/src/Prism/Renderer/Renderer2D.cpp +++ b/Prism/src/Prism/Renderer/Renderer2D.cpp @@ -26,6 +26,14 @@ namespace Prism glm::vec4 Color; }; + struct CircleVertex + { + glm::vec3 WorldPosition; + float Thickness; + glm::vec2 LocalPosition; + glm::vec4 Color; + }; + struct Renderer2DData { static constexpr uint32_t MaxQuads = 20000; @@ -65,6 +73,14 @@ namespace Prism LineVertex* LineVertexBufferBase = nullptr; LineVertex* LineVertexBufferPtr = nullptr; + // circles + Ref CircleShader; + Ref CirclePipeline; + Ref CircleVertexBuffer; + uint32_t CircleIndexCount = 0; + CircleVertex* CircleVertexBufferBase = nullptr; + CircleVertex* CircleVertexBufferPtr = nullptr; + glm::mat4 CameraViewProj; bool DepthTest = true; @@ -148,6 +164,22 @@ namespace Prism s_Data.LineIndexBuffer = IndexBuffer::Create(lineIndices, s_Data.MaxLineIndices); delete[] lineIndices; } + + { + s_Data.CircleShader = Shader::Create("assets/shaders/Renderer2D_Circle.glsl"); + + PipelineSpecification pipelineSpecification; + pipelineSpecification.Layout = { + { ShaderDataType::Float3, "a_WorldPosition" }, + { ShaderDataType::Float, "a_Thickness" }, + { ShaderDataType::Float2, "a_LocalPosition" }, + { ShaderDataType::Float4, "a_Color" } + }; + s_Data.CirclePipeline = Pipeline::Create(pipelineSpecification); + + s_Data.CircleVertexBuffer = VertexBuffer::Create(s_Data.MaxVertices * sizeof(QuadVertex)); + s_Data.CircleVertexBufferBase = new CircleVertex[s_Data.MaxVertices]; + } } void Renderer2D::Shutdown() @@ -168,6 +200,9 @@ namespace Prism s_Data.LineIndexCount = 0; s_Data.LineVertexBufferPtr = s_Data.LineVertexBufferBase; + s_Data.CircleIndexCount = 0; + s_Data.CircleVertexBufferPtr = s_Data.CircleVertexBufferBase; + s_Data.TextureSlotIndex = 1; } @@ -187,7 +222,7 @@ namespace Prism s_Data.QuadVertexBuffer->Bind(); s_Data.QuadPipeline->Bind(); s_Data.QuadIndexBuffer->Bind(); - Renderer::DrawIndexed(s_Data.QuadIndexCount, PrimitiveType::Triangles, false); + Renderer::DrawIndexed(s_Data.QuadIndexCount, PrimitiveType::Triangles, s_Data.DepthTest, false); s_Data.Stats.DrawCalls++; } @@ -203,7 +238,22 @@ namespace Prism s_Data.LinePipeline->Bind(); s_Data.LineIndexBuffer->Bind(); Renderer::SetLineThickness(1.0f); - Renderer::DrawIndexed(s_Data.LineIndexCount, PrimitiveType::Lines, s_Data.DepthTest); + Renderer::DrawIndexed(s_Data.LineIndexCount, PrimitiveType::Lines, false, false); + s_Data.Stats.DrawCalls++; + } + + dataSize = (uint8_t*)s_Data.CircleVertexBufferPtr - (uint8_t*)s_Data.CircleVertexBufferBase; + if (dataSize) + { + s_Data.CircleVertexBuffer->SetData(s_Data.CircleVertexBufferBase, dataSize); + + s_Data.CircleShader->Bind(); + s_Data.CircleShader->SetMat4("u_ViewProjection", s_Data.CameraViewProj); + + s_Data.CircleVertexBuffer->Bind(); + s_Data.CirclePipeline->Bind(); + s_Data.QuadIndexBuffer->Bind(); + Renderer::DrawIndexed(s_Data.CircleIndexCount, PrimitiveType::Triangles, false, false); s_Data.Stats.DrawCalls++; } @@ -449,6 +499,73 @@ namespace Prism s_Data.Stats.QuadCount++; } + void Renderer2D::DrawRotatedRect(const glm::vec2& position, const glm::vec2& size, float rotation, const glm::vec4& color) + { + DrawRotatedRect({ position.x, position.y, 0.0f }, size, rotation, color); + } + + void Renderer2D::DrawRotatedRect(const glm::vec3& position, const glm::vec2& size, float rotation, const glm::vec4& color) + { + if (s_Data.LineIndexCount >= Renderer2DData::MaxLineIndices) + FlushAndResetLines(); + + const glm::mat4 transform = glm::translate(glm::mat4(1.0f), position) * + glm::rotate(glm::mat4(1.0f), rotation, { 0.0f, 0.0f, 1.0f }) * + glm::scale(glm::mat4(1.0f), { size.x, size.y, 1.0f }); + + const glm::vec3 positions[4] = + { + transform * s_Data.QuadVertexPositions[0], + transform * s_Data.QuadVertexPositions[1], + transform * s_Data.QuadVertexPositions[2], + transform * s_Data.QuadVertexPositions[3] + }; + + for (int i = 0; i < 4; i++) + { + const auto& v0 = positions[i]; + const auto& v1 = positions[(i + 1) % 4]; + + s_Data.LineVertexBufferPtr->Position = v0; + s_Data.LineVertexBufferPtr->Color = color; + s_Data.LineVertexBufferPtr++; + + s_Data.LineVertexBufferPtr->Position = v1; + s_Data.LineVertexBufferPtr->Color = color; + s_Data.LineVertexBufferPtr++; + + s_Data.LineIndexCount += 2; + s_Data.Stats.LineCount++; + } + } + + void Renderer2D::DrawCircle(const glm::vec2& position, float radius, const glm::vec4& color, float thickness) + { + DrawCircle({ position.x, position.y, 0.0f }, radius, color, thickness); + } + + void Renderer2D::DrawCircle(const glm::vec3& position, float radius, const glm::vec4& color, float thickness) + { + if (s_Data.CircleIndexCount >= Renderer2DData::MaxIndices) + FlushAndReset(); + + const glm::mat4 transform = glm::translate(glm::mat4(1.0f), position) * + glm::scale(glm::mat4(1.0f), { radius * 2.0f, radius * 2.0f, 1.0f }); + + for (int i = 0; i < 4; i++) + { + s_Data.CircleVertexBufferPtr->WorldPosition = transform * s_Data.QuadVertexPositions[i]; + s_Data.CircleVertexBufferPtr->Thickness = thickness; + s_Data.CircleVertexBufferPtr->LocalPosition = s_Data.QuadVertexPositions[i] * 2.0f; + s_Data.CircleVertexBufferPtr->Color = color; + s_Data.CircleVertexBufferPtr++; + + s_Data.CircleIndexCount += 6; + s_Data.Stats.QuadCount++; + } + + } + void Renderer2D::DrawLine(const glm::vec3& p0, const glm::vec3& p1, const glm::vec4& color) { if (s_Data.LineIndexCount >= Renderer2DData::MaxLineIndices) diff --git a/Prism/src/Prism/Renderer/Renderer2D.h b/Prism/src/Prism/Renderer/Renderer2D.h index 05d12c2..3bf9fe4 100644 --- a/Prism/src/Prism/Renderer/Renderer2D.h +++ b/Prism/src/Prism/Renderer/Renderer2D.h @@ -35,6 +35,12 @@ namespace Prism static void DrawRotatedQuad(const glm::vec2& position, const glm::vec2& size, float rotation, const Ref& texture, float tilingFactor = 1.0f, const glm::vec4& tintColor = glm::vec4(1.0f)); static void DrawRotatedQuad(const glm::vec3& position, const glm::vec2& size, float rotation, const Ref& texture, float tilingFactor = 1.0f, const glm::vec4& tintColor = glm::vec4(1.0f)); + static void DrawRotatedRect(const glm::vec2& position, const glm::vec2& size, float rotation, const glm::vec4& color); + static void DrawRotatedRect(const glm::vec3& position, const glm::vec2& size, float rotation, const glm::vec4& color); + + static void DrawCircle(const glm::vec2& position, float radius, const glm::vec4& color, float thickness = 0.05f); + static void DrawCircle(const glm::vec3& position, float radius, const glm::vec4& color, float thickness = 0.05f); + static void DrawLine(const glm::vec3& p0, const glm::vec3& p1, const glm::vec4& color = glm::vec4(1.0f)); // Stats struct Statistics @@ -43,8 +49,8 @@ namespace Prism uint32_t QuadCount = 0; uint32_t LineCount = 0; - uint32_t GetTotalVertexCount() { return QuadCount * 4 + LineCount * 2; } - uint32_t GetTotalIndexCount() { return QuadCount * 6 + LineCount * 2; } + uint32_t GetTotalVertexCount() const { return QuadCount * 4 + LineCount * 2; } + uint32_t GetTotalIndexCount() const { return QuadCount * 6 + LineCount * 2; } }; static void ResetStats(); static Statistics GetStats();