diff --git a/.gitmodules b/.gitmodules index 14af16a..ca63bf8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -17,3 +17,9 @@ [submodule "Hazel/vendor/ImGuizmo"] path = Hazel/vendor/ImGuizmo url = https://github.com/CedricGuillemet/ImGuizmo.git +[submodule "Hazel/vendor/shaderc"] + path = Hazel/vendor/shaderc + url = https://github.com/google/shaderc.git +[submodule "Hazel/vendor/SPIRV-Cross"] + path = Hazel/vendor/SPIRV-Cross + url = https://github.com/KhronosGroup/SPIRV-Cross.git diff --git a/Hazel/CMakeLists.txt b/Hazel/CMakeLists.txt index 0e1b385..b8ecaa9 100644 --- a/Hazel/CMakeLists.txt +++ b/Hazel/CMakeLists.txt @@ -6,6 +6,8 @@ add_subdirectory(vendor/spdlog) add_subdirectory(vendor/GLAD) add_subdirectory(vendor/glm) add_subdirectory(vendor/yaml-cpp) +add_subdirectory(vendor/shaderc) +add_subdirectory(vendor/SPIRV-Cross) file(GLOB_RECURSE SOURCES "src/**.cpp") @@ -59,7 +61,9 @@ target_link_libraries(${PROJECT_NAME} PUBLIC opengl32 glm::glm yaml-cpp::yaml-cpp - + shaderc + spirv-cross-cpp + spirv-cross-core ) # target_compile_definitions(${PROJECT_NAME} PRIVATE HZ_BUILD_DLL IMGUI_API=__declspec\(dllexport\) STB_IMAGE_IMPLEMENTATION)# 编译DLL时定义 target_compile_definitions(${PROJECT_NAME} PRIVATE STB_IMAGE_IMPLEMENTATION) diff --git a/Hazel/src/Hazel/Core/Timer.cpp b/Hazel/src/Hazel/Core/Timer.cpp new file mode 100644 index 0000000..18b92a4 --- /dev/null +++ b/Hazel/src/Hazel/Core/Timer.cpp @@ -0,0 +1,5 @@ +// +// Created by sfd on 25-6-8. +// + +#include "Timer.h" diff --git a/Hazel/src/Hazel/Core/Timer.h b/Hazel/src/Hazel/Core/Timer.h new file mode 100644 index 0000000..64acd6d --- /dev/null +++ b/Hazel/src/Hazel/Core/Timer.h @@ -0,0 +1,42 @@ +// +// Created by sfd on 25-6-8. +// + +#ifndef TIMER_H +#define TIMER_H + +#include +#include "Core.h" + +namespace Hazel +{ + class HAZEL_API Timer + { + public: + Timer() + { + Reset(); + } + + void Reset() + { + m_Start = std::chrono::high_resolution_clock::now(); + } + + float Elapsed() + { + return std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - m_Start).count() * 0.001f * 0.001f * 0.001f; + } + + float ElapsedMillis() + { + return Elapsed() * 1000.0f; + } + + private: + std::chrono::time_point m_Start; + }; +} + + +#endif //TIMER_H diff --git a/Hazel/src/Hazel/Renderer/EditorCamera.cpp b/Hazel/src/Hazel/Renderer/EditorCamera.cpp index cfe7a7c..83ce68e 100644 --- a/Hazel/src/Hazel/Renderer/EditorCamera.cpp +++ b/Hazel/src/Hazel/Renderer/EditorCamera.cpp @@ -75,7 +75,7 @@ namespace Hazel else if (Input::IsMouseButtonPressed(SDL_BUTTON_LEFT)) MouseRotate(delta); else if (Input::IsMouseButtonPressed(SDL_BUTTON_RIGHT)) - MouseZoom(delta.y); + MouseZoom(-delta.y); } UpdateView(); diff --git a/Hazel/src/Hazel/Renderer/Renderer2D.cpp b/Hazel/src/Hazel/Renderer/Renderer2D.cpp index bec7bb1..6c56a99 100644 --- a/Hazel/src/Hazel/Renderer/Renderer2D.cpp +++ b/Hazel/src/Hazel/Renderer/Renderer2D.cpp @@ -9,6 +9,7 @@ #include #include "RendererCommand.h" #include "Shader.h" +#include "UniformBuffer.h" #include "glm/ext/matrix_transform.hpp" @@ -51,6 +52,13 @@ namespace Hazel glm::vec4 QuadVertexPosition[4]; Renderer2D::Statistic Stats; + + struct CameraData + { + glm::mat4 ViewProjection; + }; + CameraData CameraBuffer; + Ref CameraUniformBuffer; }; static Renderer2DStorage s_Data; @@ -128,6 +136,8 @@ namespace Hazel s_Data.QuadVertexPosition[1] = {0.5f, -0.5f, 0.0f, 1.0f}; s_Data.QuadVertexPosition[2] = {0.5f, 0.5f, 0.0f, 1.0f}; s_Data.QuadVertexPosition[3] = {-0.5f, 0.5f, 0.0f, 1.0f}; + + s_Data.CameraUniformBuffer = UniformBuffer::Create(sizeof(Renderer2DStorage::CameraBuffer), 0); } void Renderer2D::BeginScene(const Camera& camera, const glm::mat4& tranform) @@ -135,10 +145,11 @@ namespace Hazel HZ_PROFILE_FUNCTION(); const glm::mat4 viewProjection = camera.GetProjection() * glm::inverse(tranform); + s_Data.CameraBuffer.ViewProjection = viewProjection; + s_Data.CameraUniformBuffer->SetData(&s_Data.CameraBuffer, sizeof(Renderer2DStorage::CameraBuffer)); - - s_Data.TextureShader->Bind(); - s_Data.TextureShader->SetMat4("u_ViewProjection", viewProjection); + // s_Data.TextureShader->Bind(); + // s_Data.TextureShader->SetMat4("u_ViewProjection", viewProjection); StartBatch(); } @@ -147,10 +158,13 @@ namespace Hazel { HZ_PROFILE_FUNCTION(); - const glm::mat4 vieweProjection = camera.GetViewProjection(); + const glm::mat4 viewProjection = camera.GetViewProjection(); - s_Data.TextureShader->Bind(); - s_Data.TextureShader->SetMat4("u_ViewProjection", vieweProjection); + s_Data.CameraBuffer.ViewProjection = viewProjection; + s_Data.CameraUniformBuffer->SetData(&s_Data.CameraBuffer, sizeof(Renderer2DStorage::CameraBuffer)); + + // s_Data.TextureShader->Bind(); + // s_Data.TextureShader->SetMat4("u_ViewProjection", viewProjection); StartBatch(); } @@ -158,8 +172,10 @@ namespace Hazel void Renderer2D::BeginScene(const OrthographicCamera& camera) { HZ_PROFILE_FUNCTION(); - s_Data.TextureShader->Bind(); - s_Data.TextureShader->SetMat4("u_ViewProjection", camera.GetViewProjectionMatrix()); + // s_Data.TextureShader->Bind(); + // s_Data.TextureShader->SetMat4("u_ViewProjection", camera.GetViewProjectionMatrix()); + s_Data.CameraBuffer.ViewProjection = camera.GetViewProjectionMatrix(); + s_Data.CameraUniformBuffer->SetData(&s_Data.CameraBuffer, sizeof(Renderer2DStorage::CameraBuffer)); StartBatch(); } diff --git a/Hazel/src/Hazel/Renderer/RendererAPI.h b/Hazel/src/Hazel/Renderer/RendererAPI.h index 5aabc19..7648b1f 100644 --- a/Hazel/src/Hazel/Renderer/RendererAPI.h +++ b/Hazel/src/Hazel/Renderer/RendererAPI.h @@ -29,7 +29,7 @@ namespace Hazel virtual void SetViewPort(uint32_t x, uint32_t y, uint32_t width, uint32_t height) = 0; virtual void Clear() = 0; - virtual void DrawIndexed(const std::shared_ptr& vertexArray, uint32_t indexCount = 0) = 0; + virtual void DrawIndexed(const std::shared_ptr& vertexArray, uint32_t indexCount) = 0; inline static API GetAPI() {return s_API; } diff --git a/Hazel/src/Hazel/Renderer/RendererCommand.h b/Hazel/src/Hazel/Renderer/RendererCommand.h index 2afe15b..2589d85 100644 --- a/Hazel/src/Hazel/Renderer/RendererCommand.h +++ b/Hazel/src/Hazel/Renderer/RendererCommand.h @@ -31,7 +31,11 @@ namespace Hazel { s_RendererAPI->Clear(); } - inline static void DrawIndexed(const std::shared_ptr& vertexArray, uint32_t indexCount = 0) + inline static void DrawIndexed(const std::shared_ptr& vertexArray) + { + s_RendererAPI->DrawIndexed(vertexArray, -1); + } + inline static void DrawIndexed(const std::shared_ptr& vertexArray, const uint32_t indexCount) { s_RendererAPI->DrawIndexed(vertexArray, indexCount); } diff --git a/Hazel/src/Hazel/Renderer/UniformBuffer.cpp b/Hazel/src/Hazel/Renderer/UniformBuffer.cpp new file mode 100644 index 0000000..def7ac2 --- /dev/null +++ b/Hazel/src/Hazel/Renderer/UniformBuffer.cpp @@ -0,0 +1,29 @@ +// +// Created by sfd on 25-6-8. +// + +#include "UniformBuffer.h" + +#include + +#include "Renderer.h" + +namespace Hazel +{ + Ref UniformBuffer::Create(uint32_t size, uint32_t binding) + { + switch (Renderer::GetAPI()) + { + case RendererAPI::API::NONE: + HZ_CORE_ERROR("NONE is not Support!"); + return nullptr; + case RendererAPI::API::OPENGL: + return CreateRef(size, binding); + default: + break; + } + + HZ_CORE_ERROR("Unknown RendererAPI!"); + return nullptr; + } +} diff --git a/Hazel/src/Hazel/Renderer/UniformBuffer.h b/Hazel/src/Hazel/Renderer/UniformBuffer.h new file mode 100644 index 0000000..29c9b75 --- /dev/null +++ b/Hazel/src/Hazel/Renderer/UniformBuffer.h @@ -0,0 +1,23 @@ +// +// Created by sfd on 25-6-8. +// + +#ifndef UNIFORMBUFFER_H +#define UNIFORMBUFFER_H + +#include "Hazel/Core/Core.h" + +namespace Hazel +{ + class HAZEL_API UniformBuffer + { + public: + virtual ~UniformBuffer() {} + virtual void SetData(const void* data, uint32_t size, uint32_t offset = 0) = 0; + + static Ref Create(uint32_t size, uint32_t binding); + }; +} + + +#endif //UNIFORMBUFFER_H diff --git a/Hazel/src/Platform/OpenGL/OpenGLRendererAPI.cpp b/Hazel/src/Platform/OpenGL/OpenGLRendererAPI.cpp index c2968cf..64ad287 100644 --- a/Hazel/src/Platform/OpenGL/OpenGLRendererAPI.cpp +++ b/Hazel/src/Platform/OpenGL/OpenGLRendererAPI.cpp @@ -35,7 +35,11 @@ namespace Hazel void OpenGLRendererAPI::DrawIndexed(const std::shared_ptr& vertexArray, const uint32_t indexCount) { - const uint32_t count = indexCount ? indexCount : vertexArray->GetIndexBuffer()->GetCount(); + uint32_t count; + if (indexCount != -1) + count = indexCount; + else + count = vertexArray->GetIndexBuffer()->GetCount(); glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, nullptr); glBindTexture(GL_TEXTURE_2D, 0); } diff --git a/Hazel/src/Platform/OpenGL/OpenGLShader.cpp b/Hazel/src/Platform/OpenGL/OpenGLShader.cpp index 17fa14a..6c25472 100644 --- a/Hazel/src/Platform/OpenGL/OpenGLShader.cpp +++ b/Hazel/src/Platform/OpenGL/OpenGLShader.cpp @@ -7,14 +7,90 @@ #include #include #include +#include #include #include +#include + +#include +#include +#include #include "glm/gtc/type_ptr.hpp" #include "spdlog/fmt/bundled/compile.h" namespace Hazel { + namespace Utils + { + static GLenum ShaderTypeFromString(const std::string& type) + { + if (type == "vertex") + return GL_VERTEX_SHADER; + if (type == "fragment" || type == "pixel") + return GL_FRAGMENT_SHADER; + + HZ_CORE_ERROR("Unknown shader type!"); + return 0; + } + + static const char* GLShaderStageToString(GLenum stage) + { + switch (stage) + { + case GL_VERTEX_SHADER: return "GL_VERTEX_SHADER"; + case GL_FRAGMENT_SHADER: return "GL_FRAGMENT_SHADER"; + } + HZ_CORE_ERROR("Unknown shader stage!"); + return nullptr; + } + + static shaderc_shader_kind GLShaderStageToShaderC(GLenum stage) + { + switch (stage) + { + case GL_VERTEX_SHADER: return shaderc_glsl_vertex_shader; + case GL_FRAGMENT_SHADER: return shaderc_glsl_fragment_shader; + } + HZ_CORE_ERROR("Unknown shader stage!"); + return (shaderc_shader_kind)0; + } + + static const char* GLShaderStageCachedOpenGLFileExtension(uint32_t stage) + { + switch (stage) + { + case GL_VERTEX_SHADER: return ".cached_opengl.vert"; + case GL_FRAGMENT_SHADER: return ".cached_opengl.frag"; + } + HZ_CORE_ERROR("cannot find opengl shader cache"); + return ""; + } + + static const char* GLShaderStageCachedVulkanFileExtension(uint32_t stage) + { + switch (stage) + { + case GL_VERTEX_SHADER: return ".cached_vulkan.vert"; + case GL_FRAGMENT_SHADER: return ".cached_vulkan.frag"; + } + HZ_CORE_ERROR("cannot find vulkan shader cache"); + return ""; + } + + static const char* GetCacheDirectory() + { + return "assets/cache/shader/opengl"; + } + + static void CreateCacheDirectoryIfNeeded() + { + const std::string cacheDirectory = GetCacheDirectory(); + if (!std::filesystem::exists(cacheDirectory)) + std::filesystem::create_directories(cacheDirectory); + } + } + static GLenum ShaderTypeFromString(const std::string& type) { if (type == "vertex") return GL_VERTEX_SHADER; @@ -27,8 +103,29 @@ namespace Hazel OpenGLShader::OpenGLShader(const std::string& filepath) + : m_FilePath(filepath) { HZ_PROFILE_FUNCTION(); + + Utils::CreateCacheDirectoryIfNeeded(); + + + const std::string source = ReadFile(filepath); + auto shaderSource = PreProcess(source); + + { + Timer timer; + CompileOrGetVulkanBinaries(shaderSource); + CompileOrGetOpenGLBinaries(); + CreateProgram(); + HZ_CORE_INFO("shader create took {0}ms",timer.ElapsedMillis()); + } + + const auto lastSlash = filepath.find_last_of("\\/"); + const auto lastDot = filepath.find_last_of("."); + m_Name = filepath.substr(lastSlash + 1, lastDot - lastSlash - 1); + + /* std::string shaderSrc = ReadFile(filepath); auto shaderSources = PreProcess(shaderSrc); Compile(shaderSources); @@ -39,7 +136,6 @@ namespace Hazel m_Name = filepath.substr(lastSlash + 1, lastDot - lastSlash - 1); - /* auto lastSlash = filepath.find_last_of("\\/"); lastSlash = lastSlash == std::string::npos ? 0 : lastSlash + 1; auto lastDot = filepath.rfind("."); @@ -48,13 +144,19 @@ namespace Hazel */ } - OpenGLShader::OpenGLShader(const std::string& name, const std::string& vertexSrc, const std::string& fragmentSrc): m_Name(name) + OpenGLShader::OpenGLShader(const std::string& name, const std::string& vertexSrc, const std::string& fragmentSrc) + : m_Name(name) { HZ_PROFILE_FUNCTION(); + std::unordered_map shaderSources; shaderSources[GL_VERTEX_SHADER] = vertexSrc; shaderSources[GL_FRAGMENT_SHADER] = fragmentSrc; - Compile(shaderSources); + // Compile(shaderSources); + + CompileOrGetVulkanBinaries(shaderSources); + CompileOrGetOpenGLBinaries(); + CreateProgram(); } @@ -249,6 +351,188 @@ namespace Hazel m_RendererID = program; } + void OpenGLShader::CompileOrGetVulkanBinaries(const std::unordered_map& shaderSources) + { + + GLuint program = glCreateProgram(); + + shaderc::Compiler compiler; + shaderc::CompileOptions options; + options.SetTargetEnvironment(shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_2); + const bool optimize = true; + if (optimize) + options.SetOptimizationLevel(shaderc_optimization_level_performance); + + std::filesystem::path cacheDirectory = Utils::GetCacheDirectory(); + + auto& shaderData = m_VulkanSPIRV; + shaderData.clear(); + for (auto&& [stage, source] : shaderSources) + { + std::filesystem::path shaderFilePath = m_FilePath; + std::filesystem::path cachedPath = cacheDirectory / (shaderFilePath.filename().string() + Utils::GLShaderStageCachedVulkanFileExtension(stage)); + + std::ifstream in(cachedPath, std::ios::in | std::ios::binary); + if (in.is_open()) + { + in.seekg(0, std::ios::end); + auto size = in.tellg(); + in.seekg(0, std::ios::beg); + + auto& data = shaderData[stage]; + data.resize(size / sizeof(uint32_t)); + in.read((char*)data.data(), size); + } + else + { + shaderc::SpvCompilationResult module = compiler.CompileGlslToSpv(source, Utils::GLShaderStageToShaderC(stage), m_FilePath.c_str(), options); + if (module.GetCompilationStatus() != shaderc_compilation_status_success) + { + HZ_CORE_ERROR(module.GetErrorMessage()); + assert(-1); + } + + shaderData[stage] = std::vector(module.cbegin(), module.cend()); + + std::ofstream out(cachedPath, std::ios::out | std::ios::binary); + if (out.is_open()) + { + auto& data = shaderData[stage]; + out.write((char*)data.data(), data.size() * sizeof(uint32_t)); + out.flush(); + out.close(); + } + } + } + + for (auto&& [stage, data]: shaderData) + Reflect(stage, data); + } + + void OpenGLShader::CompileOrGetOpenGLBinaries() + { + + auto& shaderData = m_OpenGLSPIRV; + + shaderc::Compiler compiler; + shaderc::CompileOptions options; + options.SetTargetEnvironment(shaderc_target_env_opengl, shaderc_env_version_opengl_4_5); + const bool optimize = false; + if (optimize) + options.SetOptimizationLevel(shaderc_optimization_level_performance); + + std::filesystem::path cacheDirectory = Utils::GetCacheDirectory(); + + shaderData.clear(); + m_OpenGLSourceCode.clear(); + for (auto&& [stage, spirv] : m_VulkanSPIRV) + { + std::filesystem::path shaderFilePath = m_FilePath; + std::filesystem::path cachedPath = cacheDirectory / (shaderFilePath.filename().string() + Utils::GLShaderStageCachedOpenGLFileExtension(stage)); + + std::ifstream in(cachedPath, std::ios::in | std::ios::binary); + if (in.is_open()) + { + in.seekg(0, std::ios::end); + auto size = in.tellg(); + in.seekg(0, std::ios::beg); + + auto& data = shaderData[stage]; + data.resize(size / sizeof(uint32_t)); + in.read((char*)data.data(), size); + } + else + { + spirv_cross::CompilerGLSL glslCompiler(spirv); + m_OpenGLSourceCode[stage] = glslCompiler.compile(); + auto& source = m_OpenGLSourceCode[stage]; + + shaderc::SpvCompilationResult module = compiler.CompileGlslToSpv(source, Utils::GLShaderStageToShaderC(stage), m_FilePath.c_str()); + if (module.GetCompilationStatus() != shaderc_compilation_status_success) + { + HZ_CORE_ERROR(module.GetErrorMessage()); + assert(-1); + } + + shaderData[stage] = std::vector(module.cbegin(), module.cend()); + + std::ofstream out(cachedPath, std::ios::out | std::ios::binary); + if (out.is_open()) + { + auto& data = shaderData[stage]; + out.write((char*)data.data(), data.size() * sizeof(uint32_t)); + out.flush(); + out.close(); + } + } + } + } + + void OpenGLShader::CreateProgram() + { + GLuint program = glCreateProgram(); + + std::vector shaderIDs; + for (auto&& [stage, spirv] : m_OpenGLSPIRV) + { + GLuint shaderID = shaderIDs.emplace_back(glCreateShader(stage)); + glShaderBinary(1, &shaderID, GL_SHADER_BINARY_FORMAT_SPIR_V, spirv.data(), spirv.size() * sizeof(uint32_t)); + glSpecializeShader(shaderID, "main", 0, nullptr, nullptr); + glAttachShader(program, shaderID); + } + + glLinkProgram(program); + + GLint isLinked; + glGetProgramiv(program, GL_LINK_STATUS, &isLinked); + if (isLinked == GL_FALSE) + { + GLint maxLength; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength); + + std::vector infoLog(maxLength); + glGetProgramInfoLog(program, maxLength, &maxLength, infoLog.data()); + HZ_CORE_ERROR("Shader linking failed ({0}):\n{1}", m_FilePath, infoLog.data()); + + glDeleteProgram(program); + + for (auto id : shaderIDs) + glDeleteShader(id); + } + + for (auto id : shaderIDs) + { + glDetachShader(program, id); + glDeleteShader(id); + } + + m_RendererID = program; + } + + void OpenGLShader::Reflect(GLenum stage, const std::vector& shaderData) + { + spirv_cross::Compiler compiler(shaderData); + spirv_cross::ShaderResources resources = compiler.get_shader_resources(); + + HZ_CORE_INFO("OpenGLShader::Reflect - {0} {1}", Utils::GLShaderStageToString(stage), m_FilePath); + HZ_CORE_TRACE(" {0} uniform buffers", resources.uniform_buffers.size()); + HZ_CORE_TRACE(" {0} resources", resources.sampled_images.size()); + + HZ_CORE_TRACE("Uniform buffers:"); + for (const auto& resource : resources.uniform_buffers) + { + const auto& bufferType = compiler.get_type(resource.base_type_id); + uint32_t bufferSize = compiler.get_declared_struct_size(bufferType); + uint32_t binding = compiler.get_decoration(resource.id, spv::DecorationBinding); + int memberCount = bufferType.member_types.size(); + + HZ_CORE_TRACE(" {0}", resource.name); + HZ_CORE_TRACE(" Size = {0}", bufferSize); + HZ_CORE_TRACE(" Binding = {0}", binding); + HZ_CORE_TRACE(" Members = {0}", memberCount); + } + } + void OpenGLShader::UploadUniformFloat3(const std::string& name, const glm::vec3& value) const { GLint location = glGetUniformLocation(m_RendererID, name.c_str()); diff --git a/Hazel/src/Platform/OpenGL/OpenGLShader.h b/Hazel/src/Platform/OpenGL/OpenGLShader.h index cff7d46..9efd149 100644 --- a/Hazel/src/Platform/OpenGL/OpenGLShader.h +++ b/Hazel/src/Platform/OpenGL/OpenGLShader.h @@ -47,9 +47,20 @@ namespace Hazel std::unordered_map PreProcess(const std::string& source); void Compile(std::unordered_map& shaderSource); + void CompileOrGetVulkanBinaries(const std::unordered_map& shaderSources); + void CompileOrGetOpenGLBinaries(); + void CreateProgram(); + void Reflect(GLenum stage, const std::vector& shaderData); + private: uint32_t m_RendererID; + std::string m_FilePath; std::string m_Name; + + std::unordered_map> m_VulkanSPIRV; + std::unordered_map> m_OpenGLSPIRV; + + std::unordered_map m_OpenGLSourceCode; }; } diff --git a/Hazel/src/Platform/OpenGL/OpenGLUniformBuffer.cpp b/Hazel/src/Platform/OpenGL/OpenGLUniformBuffer.cpp new file mode 100644 index 0000000..431565a --- /dev/null +++ b/Hazel/src/Platform/OpenGL/OpenGLUniformBuffer.cpp @@ -0,0 +1,28 @@ +// +// Created by sfd on 25-6-8. +// + +#include "OpenGLUniformBuffer.h" + +#include + +namespace Hazel +{ + OpenGLUniformBuffer::OpenGLUniformBuffer(uint32_t size, uint32_t binding) + { + glCreateBuffers(1, &m_RendererID); + glNamedBufferData(m_RendererID, size, nullptr, GL_DYNAMIC_DRAW); // TODO: investigate usage hint + glBindBufferBase(GL_UNIFORM_BUFFER, binding, m_RendererID); + } + + OpenGLUniformBuffer::~OpenGLUniformBuffer() + { + glDeleteBuffers(1, &m_RendererID); + } + + + void OpenGLUniformBuffer::SetData(const void* data, uint32_t size, uint32_t offset) + { + glNamedBufferSubData(m_RendererID, offset, size, data); + } +} diff --git a/Hazel/src/Platform/OpenGL/OpenGLUniformBuffer.h b/Hazel/src/Platform/OpenGL/OpenGLUniformBuffer.h new file mode 100644 index 0000000..5aadc8d --- /dev/null +++ b/Hazel/src/Platform/OpenGL/OpenGLUniformBuffer.h @@ -0,0 +1,25 @@ +// +// Created by sfd on 25-6-8. +// + +#ifndef OPENGLUNIFORMBUFFER_H +#define OPENGLUNIFORMBUFFER_H +#include + +namespace Hazel +{ + class OpenGLUniformBuffer : public UniformBuffer + { + public: + OpenGLUniformBuffer(uint32_t size, uint32_t binding); + + virtual ~OpenGLUniformBuffer(); + + virtual void SetData(const void* data, uint32_t size, uint32_t offset = 0) override; + private: + uint32_t m_RendererID = 0; + }; +} + + +#endif //OPENGLUNIFORMBUFFER_H diff --git a/Hazel/vendor/SPIRV-Cross b/Hazel/vendor/SPIRV-Cross new file mode 160000 index 0000000..1a69a91 --- /dev/null +++ b/Hazel/vendor/SPIRV-Cross @@ -0,0 +1 @@ +Subproject commit 1a69a919fa302e92b337594bd0a8aaea61037d91 diff --git a/Hazel/vendor/shaderc b/Hazel/vendor/shaderc new file mode 160000 index 0000000..a5a8caa --- /dev/null +++ b/Hazel/vendor/shaderc @@ -0,0 +1 @@ +Subproject commit a5a8caa1951b3f893a08f63cab2dc877087dc05b diff --git a/Sandbox/CMakeLists.txt b/Sandbox/CMakeLists.txt index c327a36..ead5bd2 100644 --- a/Sandbox/CMakeLists.txt +++ b/Sandbox/CMakeLists.txt @@ -17,7 +17,9 @@ set(PROJECT_NAME "${PROJECT_NAME}-Editor") project(${PROJECT_NAME}) file(GLOB_RECURSE SOURCES src/SandboxApp.cpp - src/Editor/**.cpp) + src/Editor/**.cpp + src/logo/logo.rc +) add_executable(${PROJECT_NAME} ${SOURCES}) diff --git a/Sandbox/assets/shaders/FlatColor.glsl b/Sandbox/assets/shaders/FlatColor.glsl index 8cbe71d..fc023a7 100644 --- a/Sandbox/assets/shaders/FlatColor.glsl +++ b/Sandbox/assets/shaders/FlatColor.glsl @@ -6,12 +6,13 @@ layout(location = 0) in vec3 a_Position; layout(location = 1) in vec2 a_TexCoord; -uniform mat4 u_ViewProjection; -uniform mat4 u_Transform; - +layout(std140, binding = 0) uniform Camera +{ +mat4 u_ViewProjection; +}; void main() { - gl_Position = u_ViewProjection * u_Transform * vec4(a_Position, 1.0f); + gl_Position = u_ViewProjection * vec4(a_Position, 1.0f); } #type fragment @@ -19,8 +20,7 @@ void main() { layout(location = 0) out vec4 color; -uniform vec4 u_Color; void main() { - color = u_Color; + color = vec4(1.0f, 0.0f, 0.0f, 1.0f); } diff --git a/Sandbox/assets/shaders/Texture.glsl b/Sandbox/assets/shaders/Texture.glsl index 6988956..3df0c0a 100644 --- a/Sandbox/assets/shaders/Texture.glsl +++ b/Sandbox/assets/shaders/Texture.glsl @@ -1,5 +1,7 @@ +// Basic Texture Shader + #type vertex -#version 460 core +#version 450 core layout(location = 0) in vec3 a_Position; layout(location = 1) in vec4 a_Color; @@ -8,43 +10,55 @@ 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; +layout(std140, binding = 0) uniform Camera +{ + mat4 u_ViewProjection; +}; -out vec2 v_TexCoord; -out vec4 v_Color; -out flat float v_TexIndex; -out float v_TilingFactor; -out flat int v_EntityID; +struct VertexOutput +{ + vec4 Color; + vec2 TexCoord; + float TilingFactor; +}; -void main() { - v_TexCoord = a_TexCoord; - v_Color = a_Color; +layout (location = 0) out VertexOutput Output; +layout (location = 3) out flat float v_TexIndex; +layout (location = 4) out flat int v_EntityID; + +void main() +{ + Output.Color = a_Color; + Output.TexCoord = a_TexCoord; + Output.TilingFactor = a_TilingFactor; v_TexIndex = a_TexIndex; - v_TilingFactor = a_TilingFactor; v_EntityID = a_EntityID; - gl_Position = u_ViewProjection * vec4(a_Position, 1.0f); + gl_Position = u_ViewProjection * vec4(a_Position, 1.0); } #type fragment -#version 460 core +#version 450 core -layout(location = 0) out vec4 color; -layout(location = 1) out int color2; +layout(location = 0) out vec4 o_Color; +layout(location = 1) out int o_EntityID; -in vec2 v_TexCoord; -in vec4 v_Color; -in flat float v_TexIndex; -in float v_TilingFactor; -in flat int v_EntityID; +struct VertexOutput +{ + vec4 Color; + vec2 TexCoord; + float TilingFactor; +}; -uniform vec4 u_Color; -uniform sampler2D u_Textures[32]; +layout (location = 0) in VertexOutput Input; +layout (location = 3) in flat float v_TexIndex; +layout (location = 4) in flat int v_EntityID; -void main() { +layout (binding = 0) uniform sampler2D u_Textures[32]; - color = texture(u_Textures[int(v_TexIndex)], v_TexCoord * v_TilingFactor) * v_Color; -// color = v_Color; - color2 = v_EntityID; +void main() +{ + o_Color = texture(u_Textures[int(v_TexIndex)], Input.TexCoord * Input.TilingFactor) * Input.Color; + + o_EntityID = v_EntityID; } diff --git a/Sandbox/assets/shaders/quad.glsl b/Sandbox/assets/shaders/quad.glsl new file mode 100644 index 0000000..5265c09 --- /dev/null +++ b/Sandbox/assets/shaders/quad.glsl @@ -0,0 +1,104 @@ +// Basic Texture Shader + +#type vertex +#version 450 core + +layout(location = 0) in vec3 a_Position; +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; + +layout(std140, binding = 0) uniform Camera +{ + mat4 u_ViewProjection; +}; + +struct VertexOutput +{ + vec4 Color; + vec2 TexCoord; + float TilingFactor; +}; + +layout (location = 0) out VertexOutput Output; +layout (location = 3) out flat float v_TexIndex; +layout (location = 4) out flat int v_EntityID; + +void main() +{ + Output.Color = a_Color; + Output.TexCoord = a_TexCoord; + Output.TilingFactor = a_TilingFactor; + v_TexIndex = a_TexIndex; + v_EntityID = a_EntityID; + + gl_Position = u_ViewProjection * vec4(a_Position, 1.0); +} + +#type fragment +#version 450 core + +layout(location = 0) out vec4 o_Color; +layout(location = 1) out int o_EntityID; + +struct VertexOutput +{ + vec4 Color; + vec2 TexCoord; + float TilingFactor; +}; + +layout (location = 0) in VertexOutput Input; +layout (location = 3) in flat float v_TexIndex; +layout (location = 4) in flat int v_EntityID; + +layout (binding = 0) uniform sampler2D u_Textures[32]; + +void main() +{ + vec4 texColor = Input.Color; + + switch(int(v_TexIndex)) + { + case 0: texColor *= texture(u_Textures[ 0], Input.TexCoord * Input.TilingFactor); break; + case 1: texColor *= texture(u_Textures[ 1], Input.TexCoord * Input.TilingFactor); break; + case 2: texColor *= texture(u_Textures[ 2], Input.TexCoord * Input.TilingFactor); break; + case 3: texColor *= texture(u_Textures[ 3], Input.TexCoord * Input.TilingFactor); break; + case 4: texColor *= texture(u_Textures[ 4], Input.TexCoord * Input.TilingFactor); break; + case 5: texColor *= texture(u_Textures[ 5], Input.TexCoord * Input.TilingFactor); break; + case 6: texColor *= texture(u_Textures[ 6], Input.TexCoord * Input.TilingFactor); break; + case 7: texColor *= texture(u_Textures[ 7], Input.TexCoord * Input.TilingFactor); break; + case 8: texColor *= texture(u_Textures[ 8], Input.TexCoord * Input.TilingFactor); break; + case 9: texColor *= texture(u_Textures[ 9], Input.TexCoord * Input.TilingFactor); break; + case 10: texColor *= texture(u_Textures[10], Input.TexCoord * Input.TilingFactor); break; + case 11: texColor *= texture(u_Textures[11], Input.TexCoord * Input.TilingFactor); break; + case 12: texColor *= texture(u_Textures[12], Input.TexCoord * Input.TilingFactor); break; + case 13: texColor *= texture(u_Textures[13], Input.TexCoord * Input.TilingFactor); break; + case 14: texColor *= texture(u_Textures[14], Input.TexCoord * Input.TilingFactor); break; + case 15: texColor *= texture(u_Textures[15], Input.TexCoord * Input.TilingFactor); break; + case 16: texColor *= texture(u_Textures[16], Input.TexCoord * Input.TilingFactor); break; + case 17: texColor *= texture(u_Textures[17], Input.TexCoord * Input.TilingFactor); break; + case 18: texColor *= texture(u_Textures[18], Input.TexCoord * Input.TilingFactor); break; + case 19: texColor *= texture(u_Textures[19], Input.TexCoord * Input.TilingFactor); break; + case 20: texColor *= texture(u_Textures[20], Input.TexCoord * Input.TilingFactor); break; + case 21: texColor *= texture(u_Textures[21], Input.TexCoord * Input.TilingFactor); break; + case 22: texColor *= texture(u_Textures[22], Input.TexCoord * Input.TilingFactor); break; + case 23: texColor *= texture(u_Textures[23], Input.TexCoord * Input.TilingFactor); break; + case 24: texColor *= texture(u_Textures[24], Input.TexCoord * Input.TilingFactor); break; + case 25: texColor *= texture(u_Textures[25], Input.TexCoord * Input.TilingFactor); break; + case 26: texColor *= texture(u_Textures[26], Input.TexCoord * Input.TilingFactor); break; + case 27: texColor *= texture(u_Textures[27], Input.TexCoord * Input.TilingFactor); break; + case 28: texColor *= texture(u_Textures[28], Input.TexCoord * Input.TilingFactor); break; + case 29: texColor *= texture(u_Textures[29], Input.TexCoord * Input.TilingFactor); break; + case 30: texColor *= texture(u_Textures[30], Input.TexCoord * Input.TilingFactor); break; + case 31: texColor *= texture(u_Textures[31], Input.TexCoord * Input.TilingFactor); break; + } + + if (texColor.a == 0.0) + discard; + + o_Color = texColor; + o_EntityID = v_EntityID; +} diff --git a/Sandbox/src/Editor/EditorLayer.cpp b/Sandbox/src/Editor/EditorLayer.cpp index 0338b52..861027c 100644 --- a/Sandbox/src/Editor/EditorLayer.cpp +++ b/Sandbox/src/Editor/EditorLayer.cpp @@ -63,7 +63,7 @@ namespace Hazel } // update camera - if (m_ViewportFocused && m_ViewportHovered) + if (m_ViewportFocused) { m_CameraController.OnUpdate(ts); m_EditorCamera.OnUpdate(ts); @@ -284,10 +284,9 @@ namespace Hazel snapValue = 0.25f; 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)) + glm::value_ptr(transform), nullptr, snap ? snapValues : nullptr) && !Input::IsKeyPressed(SDL_SCANCODE_LALT)) { if (ImGuizmo::IsUsing()) { @@ -352,11 +351,13 @@ namespace Hazel void EditorLayer::OnEvent(SDL_Event& e) { - if (m_ViewportFocused && m_ViewportHovered) + if (m_ViewportFocused) { m_CameraController.OnEvent(e); m_EditorCamera.OnEvent(e); } + if (e.button.clicks && m_ViewportHovered && !ImGuizmo::IsOver() && Input::IsMouseButtonPressed(SDL_BUTTON_LEFT) && !Input::IsKeyPressed(SDL_SCANCODE_LALT)) + m_SceneHierachyPanel.SetSelectedEntity(m_HoveredEntity); #define SHORTCUT_NEW (SDL_KMOD_CTRL | SDLK_N) #define SHORTCUT_OPEN (SDL_KMOD_CTRL | SDLK_O) diff --git a/Sandbox/src/Editor/Panels/SceneHierachyPanel.cpp b/Sandbox/src/Editor/Panels/SceneHierachyPanel.cpp index cbbf696..cea3a70 100644 --- a/Sandbox/src/Editor/Panels/SceneHierachyPanel.cpp +++ b/Sandbox/src/Editor/Panels/SceneHierachyPanel.cpp @@ -338,4 +338,9 @@ namespace Hazel ImGui::ColorEdit4("Color", glm::value_ptr(component.Color)); }); } + + void SceneHierachyPanel::SetSelectedEntity(const Entity entity) + { + m_SelectionContext = entity; + } } diff --git a/Sandbox/src/Editor/Panels/SceneHierachyPanel.h b/Sandbox/src/Editor/Panels/SceneHierachyPanel.h index 3fe48b2..df18f41 100644 --- a/Sandbox/src/Editor/Panels/SceneHierachyPanel.h +++ b/Sandbox/src/Editor/Panels/SceneHierachyPanel.h @@ -20,6 +20,7 @@ namespace Hazel void OnImGuiRender(); void DrawComponents(Entity entity); + void SetSelectedEntity(const Entity entity); Entity GetSelectedEntity() const { return m_SelectionContext; } private: