From de75ee9481e178a230628e3c73c644dec11db421 Mon Sep 17 00:00:00 2001 From: Atdunbg <979541498@qq.com> Date: Fri, 6 Jun 2025 21:49:43 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AE=80=E5=8D=95=E6=B7=BB=E5=8A=A0=E9=BC=A0?= =?UTF-8?q?=E6=A0=87=E6=8B=BE=E5=8F=96=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Hazel/src/Hazel/ImGui/ImGuiLayer.cpp | 4 +- Hazel/src/Hazel/Renderer/FrameBuffer.h | 50 ++++- Hazel/src/Hazel/Renderer/Renderer2D.cpp | 28 ++- Hazel/src/Hazel/Renderer/Renderer2D.h | 9 +- Hazel/src/Hazel/Scene/Scene.cpp | 3 +- Hazel/src/Hazel/Scene/SceneSerializer.cpp | 4 + .../src/Platform/OpenGL/OpenGLFrameBuffer.cpp | 195 +++++++++++++++- Hazel/src/Platform/OpenGL/OpenGLFrameBuffer.h | 20 +- .../src/Platform/OpenGL/OpenGLVertexArray.cpp | 43 +++- Sandbox/assets/shaders/Texture.glsl | 10 +- Sandbox/src/Editor/EditorLayer.cpp | 208 +++++++++++------- Sandbox/src/Editor/EditorLayer.h | 3 + 12 files changed, 461 insertions(+), 116 deletions(-) diff --git a/Hazel/src/Hazel/ImGui/ImGuiLayer.cpp b/Hazel/src/Hazel/ImGui/ImGuiLayer.cpp index ed023fe..d638a62 100644 --- a/Hazel/src/Hazel/ImGui/ImGuiLayer.cpp +++ b/Hazel/src/Hazel/ImGui/ImGuiLayer.cpp @@ -38,8 +38,8 @@ namespace Hazel io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // IF using Docking Branch io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; - io.Fonts->AddFontFromFileTTF("assets/fonts/OpenSans/OpenSans-Bold.ttf", 18.0f); - io.FontDefault = io.Fonts->AddFontFromFileTTF("assets/fonts/OpenSans/OpenSans-Regular.ttf", 18.0f); + io.Fonts->AddFontFromFileTTF("assets/fonts/OpenSans/OpenSans-Bold.ttf", 20.0f); + io.FontDefault = io.Fonts->AddFontFromFileTTF("assets/fonts/OpenSans/OpenSans-Regular.ttf", 20.0f); if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { diff --git a/Hazel/src/Hazel/Renderer/FrameBuffer.h b/Hazel/src/Hazel/Renderer/FrameBuffer.h index 8f1eb01..a8161e6 100644 --- a/Hazel/src/Hazel/Renderer/FrameBuffer.h +++ b/Hazel/src/Hazel/Renderer/FrameBuffer.h @@ -4,6 +4,7 @@ #ifndef FRAMEBUFFER_H #define FRAMEBUFFER_H +#include #include #include "glm/vec2.hpp" @@ -11,10 +12,47 @@ namespace Hazel { + enum class FrameBufferTextureFormat + { + NONE = 0, + + // Color + RGBA8, + RED_INTEGER, + + // Depth/stencil + DEPTH24STENCIL8, + + // Defaults + DEPTH = DEPTH24STENCIL8 + }; + + struct FrameBufferTextureSpecification + { + FrameBufferTextureSpecification() = default; + FrameBufferTextureSpecification(FrameBufferTextureFormat format) + : TextureFormat(format) + {} + + FrameBufferTextureFormat TextureFormat = FrameBufferTextureFormat::NONE; + // TODO: filtering / warp + }; + + struct FrameBufferAttachmentSpecification + { + FrameBufferAttachmentSpecification() = default; + FrameBufferAttachmentSpecification(const std::initializer_list attachments) + : Attachments(attachments) + {} + + std::vector Attachments; + }; + struct FrameBufferSpecification { - uint32_t Width, Height; - uint32_t Samples; + uint32_t Width = 0, Height = 0; + FrameBufferAttachmentSpecification Attachments; + uint32_t Samples = 1; bool SwapChainTarget = false; }; @@ -24,9 +62,15 @@ namespace Hazel { public: virtual ~FrameBuffer() = default; + virtual uint32_t GetColorAttachmentID(uint32_t index = 0) const = 0; + + virtual int ReadPixel(uint32_t attachmentIndex, int x, int y) = 0; + + virtual void ClearAttachment(uint32_t index, int value) = 0; + virtual uint32_t GetColorAttachmentRendererID(uint32_t index) const = 0; + // virtual FrameBufferSpecification& GetSpecification() = 0; virtual const FrameBufferSpecification& GetSpecification() const = 0; - virtual uint32_t GetColorAttachmentID() const = 0; virtual void Bind() = 0; virtual void UnBind() = 0; diff --git a/Hazel/src/Hazel/Renderer/Renderer2D.cpp b/Hazel/src/Hazel/Renderer/Renderer2D.cpp index b969c1d..bec7bb1 100644 --- a/Hazel/src/Hazel/Renderer/Renderer2D.cpp +++ b/Hazel/src/Hazel/Renderer/Renderer2D.cpp @@ -24,7 +24,9 @@ namespace Hazel glm::vec2 TexCoord; float TexIndex; float TilingFactor; - // TODO: + + // TODO: Editor Only + int EntityID; }; struct Renderer2DStorage @@ -68,7 +70,8 @@ namespace Hazel {ShaderDataType::Float4, "a_Color"}, {ShaderDataType::Float2, "a_TexCoord"}, {ShaderDataType::Float, "a_TexIndex"}, - {ShaderDataType::Float, "a_TilingFactor"} + {ShaderDataType::Float, "a_TilingFactor"}, + {ShaderDataType::Int, "a_EntityID"} }); s_Data.QuadVertexArray->AddVertexBuffer(s_Data.QuadVertexBuffer); @@ -301,7 +304,7 @@ namespace Hazel s_Data.Stats.QuadCount ++; } - void Renderer2D::DrawQuad(const glm::mat4& transform, const glm::vec4& Color) + void Renderer2D::DrawQuad(const glm::mat4& transform, const glm::vec4& Color, const int entityID) { HZ_PROFILE_FUNCTION(); if (s_Data.QuadIndexCount >= s_Data.MaxIndices) @@ -309,9 +312,9 @@ namespace Hazel FlushAndReset(); } - glm::vec2 texCoords[] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}}; - const float textureIndex = 0.0f; - const float tilingFactor = 1.0f; + const glm::vec2 texCoords[] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}}; + constexpr float textureIndex = 0.0f; + constexpr float tilingFactor = 1.0f; for (unsigned int i = 0; i < 4; i++) { @@ -320,6 +323,7 @@ namespace Hazel s_Data.QuadVertexBufferPtr->TexCoord = texCoords[i]; s_Data.QuadVertexBufferPtr->TexIndex = textureIndex; s_Data.QuadVertexBufferPtr->TilingFactor = tilingFactor; + s_Data.QuadVertexBufferPtr->EntityID = entityID; s_Data.QuadVertexBufferPtr++; } s_Data.QuadIndexCount += 6; @@ -328,7 +332,7 @@ namespace Hazel } void Renderer2D::DrawQuad(const glm::mat4& transform, const Ref& texture, float tilingFactor, - const glm::vec4& tintColor) + const glm::vec4& tintColor, const int entityID) { HZ_PROFILE_FUNCTION(); if (s_Data.QuadIndexCount >= s_Data.MaxIndices) @@ -365,6 +369,7 @@ namespace Hazel s_Data.QuadVertexBufferPtr->TexCoord = texCoords[i]; s_Data.QuadVertexBufferPtr->TexIndex = textureIndex; s_Data.QuadVertexBufferPtr->TilingFactor = tilingFactor; + s_Data.QuadVertexBufferPtr->EntityID = entityID; s_Data.QuadVertexBufferPtr++; } s_Data.QuadIndexCount += 6; @@ -378,9 +383,7 @@ namespace Hazel { DrawRotateQuad({position.x, position.y, 0.0f}, size, rotation, color); } - - void Renderer2D::DrawRotateQuad(const glm::vec3& position, const glm::vec2& size, const float rotation, - const glm::vec4& color) + void Renderer2D::DrawRotateQuad(const glm::vec3& position, const glm::vec2& size, const float rotation, const glm::vec4& color) { HZ_PROFILE_FUNCTION(); @@ -512,4 +515,9 @@ namespace Hazel s_Data.Stats.QuadCount ++; } + + void Renderer2D::DrawSprite(const glm::mat4& transform, SpriteRendererComponent& src, int entityID) + { + DrawQuad(transform, src.Color, entityID); + } } diff --git a/Hazel/src/Hazel/Renderer/Renderer2D.h b/Hazel/src/Hazel/Renderer/Renderer2D.h index c1cc946..bbd516a 100644 --- a/Hazel/src/Hazel/Renderer/Renderer2D.h +++ b/Hazel/src/Hazel/Renderer/Renderer2D.h @@ -5,6 +5,8 @@ #ifndef RENDERER2D_H #define RENDERER2D_H +#include + #include "Camera.h" #include "EditorCamera.h" #include "OrthographicCamera.h" @@ -42,8 +44,8 @@ namespace Hazel static void DrawQuad(const glm::vec2& position, const glm::vec2& size, const Ref& subTexture, float tilingFactor = 1.0f, const glm::vec4& tintColor = glm::vec4(1.0f)); static void DrawQuad(const glm::vec3& position, const glm::vec2& size, const Ref& subTexture, float tilingFactor = 1.0f, const glm::vec4& tintColor = glm::vec4(1.0f)); - static void DrawQuad(const glm::mat4& transform, const glm::vec4& Color); - static void DrawQuad(const glm::mat4& transform, const Ref& texture, float tilingFactor = 1.0f, const glm::vec4& tintColor = glm::vec4(1.0f)); + static void DrawQuad(const glm::mat4& transform, const glm::vec4& Color, const int entityID = -1); + static void DrawQuad(const glm::mat4& transform, const Ref& texture, float tilingFactor = 1.0f, const glm::vec4& tintColor = glm::vec4(1.0f), const int entityID = -1); static void DrawRotateQuad(const glm::vec2& position, const glm::vec2& size, float rotation, const glm::vec4& color); static void DrawRotateQuad(const glm::vec3& position, const glm::vec2& size, float rotation, const glm::vec4& color); @@ -52,6 +54,9 @@ namespace Hazel static void DrawRotateQuad(const glm::vec2& position, const glm::vec2& size, float rotation, const Ref& subTexture, float tilingFactor = 1.0f, const glm::vec4& tintColor = glm::vec4(1.0f)); static void DrawRotateQuad(const glm::vec3& position, const glm::vec2& size, float rotation, const Ref& subTexture, float tilingFactor = 1.0f, const glm::vec4& tintColor = glm::vec4(1.0f)); + + static void DrawSprite(const glm::mat4& transform, SpriteRendererComponent& src, int entityID); + static void Shutdown(); struct Statistic diff --git a/Hazel/src/Hazel/Scene/Scene.cpp b/Hazel/src/Hazel/Scene/Scene.cpp index 172179f..7387093 100644 --- a/Hazel/src/Hazel/Scene/Scene.cpp +++ b/Hazel/src/Hazel/Scene/Scene.cpp @@ -99,7 +99,8 @@ namespace Hazel { auto [transform, sprite] = group.get(entity); - Renderer2D::DrawQuad(transform.GetTransform(), sprite.Color); + // Renderer2D::DrawQuad(transform.GetTransform(), sprite.Color); + Renderer2D::DrawSprite(transform.GetTransform(), sprite, (int)entity); } Renderer2D::EndScene(); diff --git a/Hazel/src/Hazel/Scene/SceneSerializer.cpp b/Hazel/src/Hazel/Scene/SceneSerializer.cpp index 3fbab90..8bf6d5d 100644 --- a/Hazel/src/Hazel/Scene/SceneSerializer.cpp +++ b/Hazel/src/Hazel/Scene/SceneSerializer.cpp @@ -188,7 +188,11 @@ namespace Hazel YAML::Node data = YAML::Load(strStream.str()); if (!data["Scene"]) + { + HZ_CORE_WARN("cannot find key: Scene"); return false; + } + auto sceneName = data["Scene"].as(); diff --git a/Hazel/src/Platform/OpenGL/OpenGLFrameBuffer.cpp b/Hazel/src/Platform/OpenGL/OpenGLFrameBuffer.cpp index 899129f..958df6d 100644 --- a/Hazel/src/Platform/OpenGL/OpenGLFrameBuffer.cpp +++ b/Hazel/src/Platform/OpenGL/OpenGLFrameBuffer.cpp @@ -11,22 +11,127 @@ namespace Hazel static constexpr uint32_t s_MaxFrameBufferSize = 8192; + namespace Utils + { + + static GLenum TextureTarget(bool multisample) + { + return multisample ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D; + } + + static void CreateTextures(const bool multisample, uint32_t* outID, const uint32_t count) + { + glCreateTextures(TextureTarget(multisample), count, outID); + } + + static void BindTexture(bool multisampleID, uint32_t id) + { + glBindTexture(TextureTarget(multisampleID), id); + } + + static void AtttachColorTexture(uint32_t id, const int samples, const GLenum internalFormat,const GLenum format, const uint32_t width, const uint32_t height, int index) + { + const bool multisample = samples > 1; + if (multisample) + { + glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, internalFormat, width, height, GL_FALSE); + }else + { + glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, GL_UNSIGNED_BYTE, nullptr); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + index, TextureTarget(multisample), id, 0); + } + + static void AtttachDepthTexture(uint32_t id, const int samples, const GLenum format, const GLenum attachmentType, const uint32_t width, const uint32_t height) + { + const bool multisample = samples > 1; + if (multisample) + { + glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, format, width, height, GL_FALSE); + }else + { + glTexStorage2D(GL_TEXTURE_2D, 1, format, width, height); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + + glFramebufferTexture2D(GL_FRAMEBUFFER, attachmentType, TextureTarget(multisample), id, 0); + } + + static bool IsDepthFormat(const FrameBufferTextureFormat format) + { + switch (format) + { + case FrameBufferTextureFormat::DEPTH24STENCIL8: return true; + } + + return false; + } + + static GLenum TextureFormatToGL(const FrameBufferTextureFormat format) + { + switch (format) + { + case FrameBufferTextureFormat::RGBA8: return GL_RGBA8; + case FrameBufferTextureFormat::RED_INTEGER: return GL_RED_INTEGER; + } + + HZ_CORE_WARN("Unknown framebuffer texture format!"); + return 0; + } + + static GLenum GLDataType(const FrameBufferTextureFormat format) + { + switch (format) + { + case FrameBufferTextureFormat::RGBA8: return GL_FLOAT; + case FrameBufferTextureFormat::RED_INTEGER: return GL_INT; + } + + HZ_CORE_WARN("Unknown framebuffer texture format!"); + return 0; + } + + } + OpenGLFrameBuffer::OpenGLFrameBuffer(const FrameBufferSpecification& spec) : m_Specification(spec) { + for (auto spec : m_Specification.Attachments.Attachments) + { + if (!Utils::IsDepthFormat(spec.TextureFormat)) + m_ColorAttachmentsSpecifications.emplace_back(spec); + else + m_DepthAttachmentSpecification = spec; + } + Invalidata(); } OpenGLFrameBuffer::~OpenGLFrameBuffer() { glDeleteFramebuffers(1, &m_RendererID); - glDeleteTextures(1, &m_ColorAttachment); + glDeleteTextures(m_ColorAttachmentsSpecifications.size(), m_ColorAttachments.data()); glDeleteTextures(1, &m_DepthAttachment); } void OpenGLFrameBuffer::Bind() { glBindFramebuffer(GL_FRAMEBUFFER, m_RendererID); + + constexpr int value = -1; + glClearTexImage(m_ColorAttachments[1], 0,GL_RED_INTEGER, GL_INT, &value); } void OpenGLFrameBuffer::UnBind() @@ -34,6 +139,32 @@ namespace Hazel glBindFramebuffer(GL_FRAMEBUFFER, 0); } + void OpenGLFrameBuffer::ClearAttachment(const uint32_t attachmentIndex, const int value) + { + if (attachmentIndex >= m_ColorAttachments.size()) + { + HZ_CORE_ERROR("Attempting to clear an invalid attachment index"); + } + + const auto& spec = m_ColorAttachmentsSpecifications[attachmentIndex]; + + glClearTexImage(m_ColorAttachments[attachmentIndex], 0,Utils::TextureFormatToGL(spec.TextureFormat), GL_INT, &value); + } + + int OpenGLFrameBuffer::ReadPixel(uint32_t attachmentIndex, int x, int y) + { + if (attachmentIndex >= m_ColorAttachmentsSpecifications.size()) + { + HZ_CORE_ERROR("Attempting to read pixel from non-existant attachment"); + } + + glReadBuffer(GL_COLOR_ATTACHMENT0 + attachmentIndex); + int pixelData; + glReadPixels(x, y, 1, 1, GL_RED_INTEGER, GL_INT, &pixelData); + + return pixelData; + } + void OpenGLFrameBuffer::Resize(const uint32_t width, const uint32_t height) { if (width == 0 || height == 0) @@ -53,15 +184,68 @@ namespace Hazel if (m_RendererID) { glDeleteFramebuffers(1, &m_RendererID); - glDeleteTextures(1, &m_ColorAttachment); + glDeleteTextures(m_ColorAttachmentsSpecifications.size(), m_ColorAttachments.data()); glDeleteTextures(1, &m_DepthAttachment); + m_ColorAttachments.clear(); + m_DepthAttachment = 0; + glViewport(0, 0, m_Specification.Width, m_Specification.Height); } - glCreateFramebuffers(1, &m_RendererID); - glBindFramebuffer(GL_FRAMEBUFFER, m_RendererID); + bool multisample = m_Specification.Samples > 1; + glCreateFramebuffers(1, &m_RendererID); glBindFramebuffer(GL_FRAMEBUFFER, m_RendererID); + // Attachments + if (m_ColorAttachmentsSpecifications.size() > 0) + { + m_ColorAttachments.resize(m_ColorAttachmentsSpecifications.size()); + Utils::CreateTextures(multisample, m_ColorAttachments.data(), m_ColorAttachments.size()); + for (size_t i = 0; i < m_ColorAttachmentsSpecifications.size(); i++) + { + Utils::BindTexture(multisample, m_ColorAttachments[i]); + switch (m_ColorAttachmentsSpecifications[i].TextureFormat) + { + case FrameBufferTextureFormat::RGBA8: + Utils::AtttachColorTexture(m_ColorAttachments[i], m_Specification.Samples, GL_RGBA8, GL_RGBA, m_Specification.Width, m_Specification.Height, i); + break; + case FrameBufferTextureFormat::RED_INTEGER: + Utils::AtttachColorTexture(m_ColorAttachments[i], m_Specification.Samples, GL_R32I, GL_RED_INTEGER, m_Specification.Width, m_Specification.Height, i); + break; + } + } + } + + if (m_DepthAttachmentSpecification.TextureFormat != FrameBufferTextureFormat::NONE) + { + Utils::CreateTextures(multisample, &m_DepthAttachment, 1); + Utils::BindTexture(multisample, m_DepthAttachment); + switch (m_DepthAttachmentSpecification.TextureFormat) + { + case FrameBufferTextureFormat::DEPTH24STENCIL8: + Utils::AtttachDepthTexture(m_DepthAttachment, m_Specification.Samples, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL_ATTACHMENT, m_Specification.Width, m_Specification.Height); + break; + } + } + + if (m_ColorAttachments.size() > 1) + { + if (m_ColorAttachments.size() > 4) + { + HZ_CORE_ERROR("Too many color attachments!"); + } + + constexpr GLenum buffers[4] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3}; + glDrawBuffers(m_ColorAttachments.size(), buffers); + } + else if (m_ColorAttachments.empty()) + { + // Only depth pass + glDrawBuffer(GL_NONE); + } + + + /* glCreateTextures(GL_TEXTURE_2D, 1, &m_ColorAttachment); glBindTexture(GL_TEXTURE_2D, m_ColorAttachment); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_Specification.Width, m_Specification.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); @@ -76,9 +260,10 @@ namespace Hazel glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, m_Specification.Width, m_Specification.Height); // glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, m_Specification.Width, m_Specification.Height, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_DepthAttachment, 0); + */ { - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + const GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); switch(status) { case GL_FRAMEBUFFER_COMPLETE: break; diff --git a/Hazel/src/Platform/OpenGL/OpenGLFrameBuffer.h b/Hazel/src/Platform/OpenGL/OpenGLFrameBuffer.h index 112e04c..71e344d 100644 --- a/Hazel/src/Platform/OpenGL/OpenGLFrameBuffer.h +++ b/Hazel/src/Platform/OpenGL/OpenGLFrameBuffer.h @@ -4,6 +4,7 @@ #ifndef OPENGLFRAMEBUFFER_H #define OPENGLFRAMEBUFFER_H +#include #include @@ -19,15 +20,30 @@ namespace Hazel void UnBind() override; virtual const FrameBufferSpecification& GetSpecification() const override { return m_Specification; } - virtual uint32_t GetColorAttachmentID() const override { return m_ColorAttachment; } + virtual uint32_t GetColorAttachmentID(const uint32_t index = 0) const override { + if (index > m_ColorAttachments.size()) + { + HZ_CORE_ERROR("Attempting to access color attachment that is out-of-bounds"); + } + return m_ColorAttachments[index]; + } + + virtual void ClearAttachment(uint32_t attachmentIndex, int value) override; + virtual int ReadPixel(uint32_t attachmentIndex, int x, int y) override; virtual void Resize(uint32_t width, uint32_t height) override; + virtual uint32_t GetColorAttachmentRendererID(const uint32_t index = 0) const override { return m_ColorAttachments[index]; } void Invalidata(); private: uint32_t m_RendererID = 0; - uint32_t m_ColorAttachment = 0, m_DepthAttachment = 0; FrameBufferSpecification m_Specification; + + std::vector m_ColorAttachmentsSpecifications; + FrameBufferTextureSpecification m_DepthAttachmentSpecification = FrameBufferTextureFormat::NONE; + + std::vector m_ColorAttachments; + uint32_t m_DepthAttachment = 0; }; } diff --git a/Hazel/src/Platform/OpenGL/OpenGLVertexArray.cpp b/Hazel/src/Platform/OpenGL/OpenGLVertexArray.cpp index a2f5d11..df3a77c 100644 --- a/Hazel/src/Platform/OpenGL/OpenGLVertexArray.cpp +++ b/Hazel/src/Platform/OpenGL/OpenGLVertexArray.cpp @@ -73,11 +73,44 @@ namespace Hazel uint32_t index = 0; for (const auto& element : vertexBuffer->GetLayout()) { - glEnableVertexAttribArray(index); - glVertexAttribPointer(index, element.GetComponentCount(), ShaderDataTypeToOpenGLBaseType(element.Type), - element.Normalized ? GL_TRUE : GL_FALSE, vertexBuffer->GetLayout().GetStride(), - (void*)element.Offset); - index ++; + switch (element.Type) + { + case ShaderDataType::Float: + case ShaderDataType::Float2: + case ShaderDataType::Float3: + case ShaderDataType::Float4: + case ShaderDataType::Mat3: + case ShaderDataType::Mat4: + { + glEnableVertexAttribArray(index); + glVertexAttribPointer(index, + element.GetComponentCount(), + ShaderDataTypeToOpenGLBaseType(element.Type), + element.Normalized ? GL_TRUE : GL_FALSE, + vertexBuffer->GetLayout().GetStride(), + (const void*)element.Offset); + index++; + break; + } + case ShaderDataType::Int: + case ShaderDataType::Int2: + case ShaderDataType::Int3: + case ShaderDataType::Int4: + case ShaderDataType::Bool: + { + glEnableVertexAttribArray(index); + glVertexAttribIPointer(index, + element.GetComponentCount(), + ShaderDataTypeToOpenGLBaseType(element.Type), + vertexBuffer->GetLayout().GetStride(), + (const void*)element.Offset); + index++; + break; + } + default: + HZ_CORE_DEBUG("Unknown ShaderDataType!"); + break; + } } m_VertexBuffers.push_back(vertexBuffer); diff --git a/Sandbox/assets/shaders/Texture.glsl b/Sandbox/assets/shaders/Texture.glsl index b748425..6988956 100644 --- a/Sandbox/assets/shaders/Texture.glsl +++ b/Sandbox/assets/shaders/Texture.glsl @@ -6,20 +6,23 @@ layout(location = 1) in vec4 a_Color; layout(location = 2) in vec2 a_TexCoord; layout(location = 3) in float a_TexIndex; layout(location = 4) in float a_TilingFactor; +layout(location = 5) in int a_EntityID; uniform mat4 u_ViewProjection; //uniform mat4 u_Transform; out vec2 v_TexCoord; out vec4 v_Color; -out float v_TexIndex; +out flat float v_TexIndex; out float v_TilingFactor; +out flat int v_EntityID; void main() { v_TexCoord = a_TexCoord; v_Color = a_Color; v_TexIndex = a_TexIndex; v_TilingFactor = a_TilingFactor; + v_EntityID = a_EntityID; gl_Position = u_ViewProjection * vec4(a_Position, 1.0f); } @@ -28,11 +31,13 @@ void main() { #version 460 core layout(location = 0) out vec4 color; +layout(location = 1) out int color2; in vec2 v_TexCoord; in vec4 v_Color; -in float v_TexIndex; +in flat float v_TexIndex; in float v_TilingFactor; +in flat int v_EntityID; uniform vec4 u_Color; uniform sampler2D u_Textures[32]; @@ -41,4 +46,5 @@ void main() { color = texture(u_Textures[int(v_TexIndex)], v_TexCoord * v_TilingFactor) * v_Color; // color = v_Color; + color2 = v_EntityID; } diff --git a/Sandbox/src/Editor/EditorLayer.cpp b/Sandbox/src/Editor/EditorLayer.cpp index b059c52..0338b52 100644 --- a/Sandbox/src/Editor/EditorLayer.cpp +++ b/Sandbox/src/Editor/EditorLayer.cpp @@ -27,6 +27,7 @@ namespace Hazel FrameBufferSpecification spec; spec.Width = Application::Get().GetWindow().GetWidth(); spec.Height = Application::Get().GetWindow().GetHeight(); + spec.Attachments = { FrameBufferTextureFormat::RGBA8, FrameBufferTextureFormat::RED_INTEGER,FrameBufferTextureFormat::DEPTH }; m_FrameBuffer = FrameBuffer::Create(spec); m_ViewPortSize = { spec.Width, spec.Height }; @@ -73,12 +74,28 @@ namespace Hazel RendererCommand::SetClearColor(m_BackgroundColor); RendererCommand::Clear(); + m_FrameBuffer->ClearAttachment(1, -1); // Renderer2D::BeginScene(m_CameraController.GetCamera()); // update Scene m_ActiveScene->OnUpdateEditor(ts, m_EditorCamera); + auto [mx, my] = ImGui::GetMousePos(); + mx -= m_ViewPortBounds[0].x; + my -= m_ViewPortBounds[0].y; + const glm::vec2 viewPortSize = m_ViewPortBounds[1] - m_ViewPortBounds[0]; + my = viewPortSize.y - my; + + int mouseX = (int)mx; + int mouseY = (int)my; + + if (mouseX >= 0 && mouseY >= 0 && mouseX < m_ViewPortSize.x && mouseY < m_ViewPortSize.y) + { + int pixelData = m_FrameBuffer->ReadPixel(1, mouseX, mouseY); + m_HoveredEntity = pixelData == -1 ? Entity{} : Entity{ (entt::entity)pixelData, m_ActiveScene.get()}; + } + // Renderer2D::DrawQuad({0, 0.5f}, {1.0f, 1.0f}, {0.2f, 0.3f, 0.8f, 1.0f}); // Renderer2D::DrawQuad({0, -0.5f}, {1.0f, 1.0f}, {0.8f, 0.2f, 0.2f, 1.0f}); // Renderer2D::DrawQuad({-1, 0}, {1, 1}, m_LogoTexture); @@ -138,9 +155,9 @@ namespace Hazel ImGui::PopStyleVar(2); // Submit the DockSpace - ImGuiIO& io = ImGui::GetIO(); - ImGuiStyle& style = ImGui::GetStyle(); - style.WindowMinSize.x = 350.0f; + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle& style = ImGui::GetStyle(); + style.WindowMinSize.x = 350.0f; if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable) { ImGuiID dockspace_id = ImGui::GetID("MyDockSpace"); @@ -156,14 +173,14 @@ namespace Hazel // ImGui::MenuItem("Fullscreen", NULL, &opt_fullscreen); // ImGui::MenuItem("Padding", NULL, &opt_padding); // ImGui::Separator(); - if (ImGui::MenuItem("New", "Ctrl+N")) - NewScene(); - if (ImGui::MenuItem("Open...", "Ctrl+O")) - OpenScene(); - if (ImGui::MenuItem("Save As...", "Ctrl+Shift+S")) - SaveScene(); + if (ImGui::MenuItem("New", "Ctrl+N")) + NewScene(); + if (ImGui::MenuItem("Open...", "Ctrl+O")) + OpenScene(); + if (ImGui::MenuItem("Save As...", "Ctrl+Shift+S")) + SaveScene(); - ImGui::Separator(); + ImGui::Separator(); if (ImGui::MenuItem("Exit")) { Hazel::Application::Get().Close(); } ImGui::EndMenu(); @@ -172,10 +189,10 @@ namespace Hazel ImGui::EndMenuBar(); } - // Scene Hierachy Panel - m_SceneHierachyPanel.OnImGuiRender(); + // Scene Hierachy Panel + m_SceneHierachyPanel.OnImGuiRender(); - // Render Status + // Render Status { ImGui::Begin("Render Status"); @@ -189,15 +206,25 @@ namespace Hazel ImGui::Separator(); ImGui::Text("viewPortSize: (%.2f, %.2f)", m_ViewPortSize.x, m_ViewPortSize.y); + + ImGui::Separator(); + + std::string name = "none"; + if (m_HoveredEntity) + name = m_HoveredEntity.GetComponent().Tag; + + ImGui::Text("Hovered Entity: %s", name.c_str()); + ImGui::End(); } - // ViewPort + // ViewPort { ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, {0.0f, 0.0f}); ImGui::Begin("Viewport"); - m_ViewportFocused = ImGui::IsWindowFocused(); - m_ViewportHovered = ImGui::IsWindowHovered(); + auto viewportOffet = ImGui::GetCursorPos(); + m_ViewportFocused = ImGui::IsWindowFocused(); + m_ViewportHovered = ImGui::IsWindowHovered(); ImVec2 viewPortPanelSize = ImGui::GetContentRegionAvail(); @@ -209,21 +236,34 @@ namespace Hazel ImGui::Image(m_FrameBuffer->GetColorAttachmentID(), {m_ViewPortSize.x, m_ViewPortSize.y}, {0, 1}, {1, 0}); - Entity selectedEntity = m_SceneHierachyPanel.GetSelectedEntity(); - if (selectedEntity) - { - ImGuizmo::SetOrthographic(false); - ImGuizmo::SetDrawlist(); - const float windowWidth = ImGui::GetWindowWidth(); - const float windowHeight = ImGui::GetWindowHeight(); + auto windowsSize = ImGui::GetWindowSize(); + ImVec2 minBound = ImGui::GetWindowPos(); - const ImVec2 windowPos = ImGui::GetWindowPos(); - ImGuizmo::SetRect(windowPos.x,windowPos.y,windowWidth,windowHeight); + minBound.x += viewportOffet.x; + minBound.y += viewportOffet.y + m_ViewPortSize.y - windowsSize.y; - // auto cameraEntity = m_ActiveScene->GetPrimaryCameraEntity(); - if (m_GizmoType != -1) + ImVec2 maxBound = {minBound.x + windowsSize.x, minBound.y + windowsSize.y}; + m_ViewPortBounds[0] = {minBound.x, minBound.y}; + m_ViewPortBounds[1] = {maxBound.x, maxBound.y}; + + // ImGuizmo + Entity selectedEntity = m_SceneHierachyPanel.GetSelectedEntity(); + if (selectedEntity) + { + ImGuizmo::SetOrthographic(false); + ImGuizmo::SetDrawlist(); + + const float windowWidth = ImGui::GetWindowWidth(); + const float windowHeight = ImGui::GetWindowHeight(); + + const ImVec2 windowPos = ImGui::GetWindowPos(); + + ImGuizmo::SetRect(windowPos.x, windowPos.y, windowWidth, windowHeight); + + // auto cameraEntity = m_ActiveScene->GetPrimaryCameraEntity(); + if (m_GizmoType != -1) { // const auto& camera = cameraEntity.GetComponent().Camera; auto& tc = selectedEntity.GetComponent(); @@ -231,38 +271,40 @@ namespace Hazel // const glm::mat4& cameraProjection = camera.GetProjection(); // glm::mat4 cameraView = glm::inverse(cameraEntity.GetComponent().GetTransform()); - glm::mat4 cameraProjection = m_EditorCamera.GetProjection(); - glm::mat4 cameraView = m_EditorCamera.GetViewMatrix(); - glm::mat4 transform = tc.GetTransform(); - bool snap = SDL_GetModState() & SDL_KMOD_CTRL; - float snapValue = 0.5f; - if (m_GizmoType == ImGuizmo::OPERATION::TRANSLATE) - snapValue = 0.25f; - else if (m_GizmoType == ImGuizmo::OPERATION::ROTATE) - snapValue = 15.0f; - else if (m_GizmoType == ImGuizmo::OPERATION::SCALE) - snapValue = 0.25f; + glm::mat4 cameraProjection = m_EditorCamera.GetProjection(); + glm::mat4 cameraView = m_EditorCamera.GetViewMatrix(); + glm::mat4 transform = tc.GetTransform(); + bool snap = SDL_GetModState() & SDL_KMOD_CTRL; + float snapValue = 0.5f; + if (m_GizmoType == ImGuizmo::OPERATION::TRANSLATE) + snapValue = 0.25f; + else if (m_GizmoType == ImGuizmo::OPERATION::ROTATE) + snapValue = 15.0f; + else if (m_GizmoType == ImGuizmo::OPERATION::SCALE) + snapValue = 0.25f; - float snapValues[3] = { snapValue, snapValue, snapValue }; + float snapValues[3] = {snapValue, snapValue, snapValue}; - if (ImGuizmo::Manipulate(glm::value_ptr(cameraView), glm::value_ptr(cameraProjection), ImGuizmo::OPERATION(m_GizmoType), ImGuizmo::LOCAL,glm::value_ptr(transform), nullptr, snap ? snapValues : nullptr)) + if (ImGuizmo::Manipulate(glm::value_ptr(cameraView), glm::value_ptr(cameraProjection), + ImGuizmo::OPERATION(m_GizmoType), ImGuizmo::LOCAL, + glm::value_ptr(transform), nullptr, snap ? snapValues : nullptr)) { if (ImGuizmo::IsUsing()) { - glm::vec3 translation, rotation, scale; + glm::vec3 translation, rotation, scale; - Hazel::Math::DecomposeTransform(transform, translation, rotation, scale); + Hazel::Math::DecomposeTransform(transform, translation, rotation, scale); - glm::vec3 deltaRotation = rotation - tc.Rotation; + glm::vec3 deltaRotation = rotation - tc.Rotation; - tc.Translation = translation; - tc.Rotation += deltaRotation; - tc.Scale = scale; + tc.Translation = translation; + tc.Rotation += deltaRotation; + tc.Scale = scale; } } - } - } + } + ImGui::End(); ImGui::PopStyleVar(); @@ -273,7 +315,7 @@ namespace Hazel void EditorLayer::SaveScene() const { - std::string filepath = FileDiaglogs::SaveFile("Hazel Scene (*.scene)\0*.scene\0"); + std::string filepath = FileDiaglogs::SaveFile("Hazel Scene (*.scene,*.yaml)\0*.scene;*.yaml\0*\0*.*\0\0"); if (!filepath.empty()) { SceneSerializer serializer(m_ActiveScene); @@ -283,7 +325,7 @@ namespace Hazel void EditorLayer::OpenScene() { - std::string filepath = FileDiaglogs::OpenFile("Hazel Scene (*.scene)\0*.scene\0"); + std::string filepath = FileDiaglogs::OpenFile("Scene(*.scene, *.yaml)\0*.scene;*.yaml\0All files\0*.*\0\0"); if (!filepath.empty()) { m_ActiveScene = CreateRef(); @@ -302,11 +344,10 @@ namespace Hazel m_SceneHierachyPanel.SetContext(m_ActiveScene); } - void EditorLayer::ChangeOptMode(unsigned int mode) + void EditorLayer::ChangeOptMode(unsigned int mode) { if (m_ViewportHovered) - m_GizmoType = mode; - + m_GizmoType = mode; } void EditorLayer::OnEvent(SDL_Event& e) @@ -314,46 +355,45 @@ namespace Hazel if (m_ViewportFocused && m_ViewportHovered) { m_CameraController.OnEvent(e); - m_EditorCamera.OnEvent(e); + m_EditorCamera.OnEvent(e); } #define SHORTCUT_NEW (SDL_KMOD_CTRL | SDLK_N) #define SHORTCUT_OPEN (SDL_KMOD_CTRL | SDLK_O) #define SHORTCUT_SAVE_ALL (SDL_KMOD_CTRL | SDL_KMOD_SHIFT | SDLK_S) - const auto mod = SDL_GetModState(); - const auto ctrl = (mod & SDL_KMOD_CTRL) ? SDL_KMOD_CTRL : 0; - const auto shift = (mod & SDL_KMOD_SHIFT) ? SDL_KMOD_SHIFT : 0; + const auto mod = SDL_GetModState(); + const auto ctrl = (mod & SDL_KMOD_CTRL) ? SDL_KMOD_CTRL : 0; + const auto shift = (mod & SDL_KMOD_SHIFT) ? SDL_KMOD_SHIFT : 0; switch (ctrl | shift | e.key.key) - { - case SHORTCUT_NEW: - NewScene(); - break; - case SHORTCUT_OPEN: - OpenScene(); - break; - case SHORTCUT_SAVE_ALL: - SaveScene(); - break; + { + case SHORTCUT_NEW: + NewScene(); + break; + case SHORTCUT_OPEN: + OpenScene(); + break; + case SHORTCUT_SAVE_ALL: + SaveScene(); + break; - // GIZMO - case SDLK_Q: - ChangeOptMode(-1); - break; - case SDLK_W: - ChangeOptMode(ImGuizmo::OPERATION::TRANSLATE); - break; - case SDLK_E: - ChangeOptMode(ImGuizmo::OPERATION::SCALE); - break; - case SDLK_R: - ChangeOptMode(ImGuizmo::OPERATION::ROTATE); - break; + // GIZMO + case SDLK_Q: + ChangeOptMode(-1); + break; + case SDLK_W: + ChangeOptMode(ImGuizmo::OPERATION::TRANSLATE); + break; + case SDLK_E: + ChangeOptMode(ImGuizmo::OPERATION::SCALE); + break; + case SDLK_R: + ChangeOptMode(ImGuizmo::OPERATION::ROTATE); + break; - default: - break; - } + default: + break; + } } - } diff --git a/Sandbox/src/Editor/EditorLayer.h b/Sandbox/src/Editor/EditorLayer.h index 944d297..9c9fccf 100644 --- a/Sandbox/src/Editor/EditorLayer.h +++ b/Sandbox/src/Editor/EditorLayer.h @@ -37,11 +37,14 @@ namespace Hazel Ref m_ActiveScene; EditorCamera m_EditorCamera; + Entity m_HoveredEntity; + glm::vec4 m_BackgroundColor = { 0.2f, 0.2f, 0.2f, 1.0f }; glm::vec4 m_SquareColor = { 0.2f, 0.2f, 0.2f, 1.0f }; bool m_ViewportFocused = false, m_ViewportHovered = false; glm::vec2 m_ViewPortSize = {0, 0}; + glm::vec2 m_ViewPortBounds[2]; Ref m_FrameBuffer;