diff --git a/Editor/Editor/EditorLayer.cpp b/Editor/Editor/EditorLayer.cpp index c03c560..a3d5b50 100644 --- a/Editor/Editor/EditorLayer.cpp +++ b/Editor/Editor/EditorLayer.cpp @@ -4,6 +4,8 @@ #include "EditorLayer.h" #include "ImGuizmo.h" +#include "Prism/Core/Input.h" +#include "Prism/Renderer/Renderer2D.h" namespace Prism { @@ -12,16 +14,18 @@ namespace Prism None = 0, ColorProperty = 1 }; - void Property(const std::string& name, bool& value) + bool Property(const std::string& name, bool& value) { ImGui::Text(name.c_str()); ImGui::NextColumn(); ImGui::PushItemWidth(-1); - std::string id = "##" + name; - ImGui::Checkbox(id.c_str(), &value); + const std::string id = "##" + name; + const bool result = ImGui::Checkbox(id.c_str(), &value); ImGui::PopItemWidth(); ImGui::NextColumn(); + + return result; } void Property(const std::string& name, float& value, float min = -1.0f, float max = 1.0f, @@ -137,14 +141,16 @@ namespace Prism m_Scene->SetEnvironment(environment); - m_MeshEntity = m_Scene->CreateEntity(); - - const auto mesh = CreateRef("assets/models/m1911/m1911.fbx"); - //auto mesh = CreateRef("assets/meshes/cerberus/CerberusMaterials.fbx"); - // auto mesh = CreateRef("assets/models/m1911/M1911Materials.fbx"); + m_MeshEntity = m_Scene->CreateEntity("test Entity"); + auto mesh = CreateRef("assets/meshes/TestScene.fbx"); m_MeshEntity->SetMesh(mesh); m_MeshMaterial = mesh->GetMaterial(); + + auto secondEntity = m_Scene->CreateEntity("Gun Entity"); + secondEntity->Transform() = glm::translate(glm::mat4(1.0f), { 5, 5, 5 }) * glm::scale(glm::mat4(1.0f), {10, 10, 10}); + mesh = CreateRef("assets/models/m1911/m1911.fbx"); + secondEntity->SetMesh(mesh); } // Sphere Scene @@ -213,43 +219,55 @@ namespace Prism void EditorLayer::OnUpdate(const TimeStep deltaTime) { + // THINGS TO LOOK AT: + // - BRDF LUT + // - Tonemapping and proper HDR pipeline + using namespace Prism; + using namespace glm; + + m_MeshMaterial->Set("u_AlbedoColor", m_AlbedoInput.Color); + m_MeshMaterial->Set("u_Metalness", m_MetalnessInput.Value); + m_MeshMaterial->Set("u_Roughness", m_RoughnessInput.Value); + m_MeshMaterial->Set("lights", m_Light); + m_MeshMaterial->Set("u_AlbedoTexToggle", m_AlbedoInput.UseTexture ? 1.0f : 0.0f); + m_MeshMaterial->Set("u_NormalTexToggle", m_NormalInput.UseTexture ? 1.0f : 0.0f); + m_MeshMaterial->Set("u_MetalnessTexToggle", m_MetalnessInput.UseTexture ? 1.0f : 0.0f); + m_MeshMaterial->Set("u_RoughnessTexToggle", m_RoughnessInput.UseTexture ? 1.0f : 0.0f); + m_MeshMaterial->Set("u_EnvMapRotation", m_EnvMapRotation); + + m_SphereBaseMaterial->Set("u_AlbedoColor", m_AlbedoInput.Color); + m_SphereBaseMaterial->Set("lights", m_Light); + m_SphereBaseMaterial->Set("u_RadiancePrefilter", m_RadiancePrefilter ? 1.0f : 0.0f); + m_SphereBaseMaterial->Set("u_AlbedoTexToggle", m_AlbedoInput.UseTexture ? 1.0f : 0.0f); + m_SphereBaseMaterial->Set("u_NormalTexToggle", m_NormalInput.UseTexture ? 1.0f : 0.0f); + m_SphereBaseMaterial->Set("u_MetalnessTexToggle", m_MetalnessInput.UseTexture ? 1.0f : 0.0f); + m_SphereBaseMaterial->Set("u_RoughnessTexToggle", m_RoughnessInput.UseTexture ? 1.0f : 0.0f); + m_SphereBaseMaterial->Set("u_EnvMapRotation", m_EnvMapRotation); + + + if (m_AlbedoInput.TextureMap) + m_MeshMaterial->Set("u_AlbedoTexture", m_AlbedoInput.TextureMap); + if (m_NormalInput.TextureMap) + m_MeshMaterial->Set("u_NormalTexture", m_NormalInput.TextureMap); + if (m_MetalnessInput.TextureMap) + m_MeshMaterial->Set("u_MetalnessTexture", m_MetalnessInput.TextureMap); + if (m_RoughnessInput.TextureMap) + m_MeshMaterial->Set("u_RoughnessTexture", m_RoughnessInput.TextureMap); + + if (m_AllowViewportCameraEvents) + m_Scene->GetCamera().OnUpdate(deltaTime); + + m_ActiveScene->OnUpdate(deltaTime); + + if (m_DrawOnTopBoundingBoxes) { - // THINGS TO LOOK AT: - // - BRDF LUT - // - Tonemapping and proper HDR pipeline - using namespace Prism; - using namespace glm; - - m_MeshMaterial->Set("u_AlbedoColor", m_AlbedoInput.Color); - m_MeshMaterial->Set("u_Metalness", m_MetalnessInput.Value); - m_MeshMaterial->Set("u_Roughness", m_RoughnessInput.Value); - m_MeshMaterial->Set("lights", m_Light); - m_MeshMaterial->Set("u_AlbedoTexToggle", m_AlbedoInput.UseTexture ? 1.0f : 0.0f); - m_MeshMaterial->Set("u_NormalTexToggle", m_NormalInput.UseTexture ? 1.0f : 0.0f); - m_MeshMaterial->Set("u_MetalnessTexToggle", m_MetalnessInput.UseTexture ? 1.0f : 0.0f); - m_MeshMaterial->Set("u_RoughnessTexToggle", m_RoughnessInput.UseTexture ? 1.0f : 0.0f); - m_MeshMaterial->Set("u_EnvMapRotation", m_EnvMapRotation); - - m_SphereBaseMaterial->Set("u_AlbedoColor", m_AlbedoInput.Color); - m_SphereBaseMaterial->Set("lights", m_Light); - m_SphereBaseMaterial->Set("u_RadiancePrefilter", m_RadiancePrefilter ? 1.0f : 0.0f); - m_SphereBaseMaterial->Set("u_AlbedoTexToggle", m_AlbedoInput.UseTexture ? 1.0f : 0.0f); - m_SphereBaseMaterial->Set("u_NormalTexToggle", m_NormalInput.UseTexture ? 1.0f : 0.0f); - m_SphereBaseMaterial->Set("u_MetalnessTexToggle", m_MetalnessInput.UseTexture ? 1.0f : 0.0f); - m_SphereBaseMaterial->Set("u_RoughnessTexToggle", m_RoughnessInput.UseTexture ? 1.0f : 0.0f); - m_SphereBaseMaterial->Set("u_EnvMapRotation", m_EnvMapRotation); - - - if (m_AlbedoInput.TextureMap) - m_MeshMaterial->Set("u_AlbedoTexture", m_AlbedoInput.TextureMap); - if (m_NormalInput.TextureMap) - m_MeshMaterial->Set("u_NormalTexture", m_NormalInput.TextureMap); - if (m_MetalnessInput.TextureMap) - m_MeshMaterial->Set("u_MetalnessTexture", m_MetalnessInput.TextureMap); - if (m_RoughnessInput.TextureMap) - m_MeshMaterial->Set("u_RoughnessTexture", m_RoughnessInput.TextureMap); - - m_ActiveScene->OnUpdate(deltaTime); + Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false); + auto viewProj = m_Scene->GetCamera().GetViewProjection(); + Renderer2D::BeginScene(viewProj, false); + // Prism::Renderer2D::DrawQuad({ 0, 0, 0 }, { 4.0f, 5.0f }, { 1.0f, 1.0f, 0.5f, 1.0f }); + Renderer::DrawAABB(m_MeshEntity->GetMesh()); + Renderer2D::EndScene(); + Renderer::EndRenderPass(); } } @@ -431,6 +449,11 @@ namespace Prism Property("Radiance Prefiltering", m_RadiancePrefilter); Property("Env Map Rotation", m_EnvMapRotation, -360.0f, 360.0f); + if (Property("Show Bounding Boxes", m_UIShowBoundingBoxes)) + ShowBoundingBoxes(m_UIShowBoundingBoxes, m_UIShowBoundingBoxesOnTop); + if (m_UIShowBoundingBoxes && Property("On Top", m_UIShowBoundingBoxesOnTop)) + ShowBoundingBoxes(m_UIShowBoundingBoxes, m_UIShowBoundingBoxesOnTop); + ImGui::Columns(1); ImGui::End(); @@ -620,12 +643,17 @@ namespace Prism ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); ImGui::Begin("Viewport"); auto viewportSize = ImGui::GetContentRegionAvail(); - SceneRenderer::SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y); m_ActiveScene->GetCamera().SetProjectionMatrix(glm::perspectiveFov(glm::radians(45.0f), viewportSize.x, viewportSize.y, 0.1f, 10000.0f)); m_ActiveScene->GetCamera().SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y); ImGui::Image((ImTextureRef)SceneRenderer::GetFinalColorBufferRendererID(), viewportSize, { 0, 1 }, { 1, 0 }); + + auto windowSize = ImGui::GetWindowSize(); + ImVec2 minBound = ImGui::GetWindowPos(); + ImVec2 maxBound = { minBound.x + windowSize.x, minBound.y + windowSize.y }; + m_AllowViewportCameraEvents = ImGui::IsMouseHoveringRect(minBound, maxBound); + // ImGuizmo if (m_GizmoType != -1) { @@ -645,8 +673,11 @@ namespace Prism void EditorLayer::OnEvent(Event& e) { + if (m_AllowViewportCameraEvents) + m_Scene->GetCamera().OnEvent(e); + EventDispatcher dispatcher(e); - dispatcher.Dispatch(HZ_BIND_EVENT_FN(EditorLayer::OnKeyPressedEvent)); + dispatcher.Dispatch(PM_BIND_EVENT_FN(EditorLayer::OnKeyPressedEvent)); } bool EditorLayer::OnKeyPressedEvent(KeyPressedEvent& e) @@ -665,7 +696,27 @@ namespace Prism case PM_KEY_R: m_GizmoType = ImGuizmo::OPERATION::SCALE; break; + case PM_KEY_G: + // Toggle grid + if (Input::IsKeyPressed(PM_KEY_LEFT_CONTROL)) + SceneRenderer::GetOptions().ShowGrid = !SceneRenderer::GetOptions().ShowGrid; + break; + case PM_KEY_B: + // Toggle bounding boxes + if (Input::IsKeyPressed(PM_KEY_LEFT_CONTROL)) + { + m_UIShowBoundingBoxes = !m_UIShowBoundingBoxes; + ShowBoundingBoxes(m_UIShowBoundingBoxes, m_UIShowBoundingBoxesOnTop); + } + break; + } return false; } + + void EditorLayer::ShowBoundingBoxes(bool show, bool onTop) + { + SceneRenderer::GetOptions().ShowBoundingBoxes = show && !onTop; + m_DrawOnTopBoundingBoxes = show && onTop; + } } diff --git a/Editor/Editor/EditorLayer.h b/Editor/Editor/EditorLayer.h index 14db0e4..4bd7b26 100644 --- a/Editor/Editor/EditorLayer.h +++ b/Editor/Editor/EditorLayer.h @@ -25,6 +25,8 @@ namespace Prism private: bool OnKeyPressedEvent(KeyPressedEvent& e); + void ShowBoundingBoxes(bool show, bool onTop = false); + private: Scope m_SceneHierarchyPanel; @@ -54,6 +56,13 @@ namespace Prism // Imguizmo int m_GizmoType = -1; // -1 = no gizmo + // configure button + bool m_AllowViewportCameraEvents = false; + bool m_DrawOnTopBoundingBoxes = false; + + bool m_UIShowBoundingBoxes = false; + bool m_UIShowBoundingBoxesOnTop = false; + struct AlbedoInput { diff --git a/Editor/assets/meshes/TestScene.fbx b/Editor/assets/meshes/TestScene.fbx new file mode 100644 index 0000000..e6808db Binary files /dev/null and b/Editor/assets/meshes/TestScene.fbx differ diff --git a/Editor/assets/shaders/PBRShader_Static.glsl b/Editor/assets/shaders/PBRShader_Static.glsl index 65b1544..d46a0a3 100644 --- a/Editor/assets/shaders/PBRShader_Static.glsl +++ b/Editor/assets/shaders/PBRShader_Static.glsl @@ -34,7 +34,7 @@ out VertexOutput void main() { vs_Output.WorldPosition = vec3(u_Transform * vec4(a_Position, 1.0)); - vs_Output.Normal = a_Normal; + vs_Output.Normal = mat3(u_Transform) * a_Normal; vs_Output.TexCoord = vec2(a_TexCoord.x, 1.0 - a_TexCoord.y); vs_Output.WorldNormals = mat3(u_Transform) * mat3(a_Tangent, a_Binormal, a_Normal); vs_Output.WorldTransform = mat3(u_Transform); @@ -271,7 +271,8 @@ vec3 Lighting(vec3 F0) vec3 IBL(vec3 F0, vec3 Lr) { vec3 irradiance = texture(u_EnvIrradianceTex, m_Params.Normal).rgb; - vec3 F = fresnelSchlickRoughness(F0, m_Params.NdotV, m_Params.Roughness); +// vec3 F = fresnelSchlickRoughness(F0, m_Params.NdotV, m_Params.Roughness); + vec3 F = fresnelSchlick(F0, m_Params.NdotV); vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness); vec3 diffuseIBL = m_Params.Albedo * irradiance; @@ -316,4 +317,5 @@ void main() vec3 iblContribution = IBL(F0, Lr); color = vec4(lightContribution + iblContribution, 1.0); + color = vec4(iblContribution, 1.0); } diff --git a/Editor/assets/shaders/Renderer2D.glsl b/Editor/assets/shaders/Renderer2D.glsl new file mode 100644 index 0000000..203cc89 --- /dev/null +++ b/Editor/assets/shaders/Renderer2D.glsl @@ -0,0 +1,43 @@ +// Basic Texture Shader + +#type vertex +#version 430 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; + +uniform mat4 u_ViewProjection; + +out vec4 v_Color; +out vec2 v_TexCoord; +out float v_TexIndex; +out float v_TilingFactor; + +void main() +{ + v_Color = a_Color; + v_TexCoord = a_TexCoord; + v_TexIndex = a_TexIndex; + v_TilingFactor = a_TilingFactor; + gl_Position = u_ViewProjection * vec4(a_Position, 1.0); +} + +#type fragment +#version 430 core + +layout(location = 0) out vec4 color; + +in vec4 v_Color; +in vec2 v_TexCoord; +in float v_TexIndex; +in float v_TilingFactor; + +uniform sampler2D u_Textures[32]; + +void main() +{ + color = texture(u_Textures[int(v_TexIndex)], v_TexCoord * v_TilingFactor) * v_Color; +} diff --git a/Editor/assets/shaders/Renderer2D_Line.glsl b/Editor/assets/shaders/Renderer2D_Line.glsl new file mode 100644 index 0000000..b55d02a --- /dev/null +++ b/Editor/assets/shaders/Renderer2D_Line.glsl @@ -0,0 +1,29 @@ +// Basic Texture Shader + +#type vertex +#version 430 core + +layout(location = 0) in vec3 a_Position; +layout(location = 1) in vec4 a_Color; + +uniform mat4 u_ViewProjection; + +out vec4 v_Color; + +void main() +{ + v_Color = a_Color; + gl_Position = u_ViewProjection * vec4(a_Position, 1.0); +} + +#type fragment +#version 430 core + +layout(location = 0) out vec4 color; + +in vec4 v_Color; + +void main() +{ + color = v_Color; +} diff --git a/Editor/assets/shaders/hdr.glsl b/Editor/assets/shaders/SceneComposite.glsl similarity index 55% rename from Editor/assets/shaders/hdr.glsl rename to Editor/assets/shaders/SceneComposite.glsl index cf91719..a1d0e24 100644 --- a/Editor/assets/shaders/hdr.glsl +++ b/Editor/assets/shaders/SceneComposite.glsl @@ -16,20 +16,34 @@ void main() #type fragment #version 430 +layout(location = 0) out vec4 o_Color; + in vec2 v_TexCoord; -uniform sampler2D u_Texture; - -layout(location=0) out vec4 outColor; - +uniform sampler2DMS u_Texture; uniform float u_Exposure; +uniform int u_TextureSamples; + +vec4 MultiSampleTexture(sampler2DMS tex, ivec2 texCoord, int samples) +{ + vec4 result = vec4(0.0); + for (int i = 0; i < samples; i++) + result += texelFetch(tex, texCoord, i); + + result /= float(samples); + return result; +} void main() { const float gamma = 2.2; const float pureWhite = 1.0; - vec3 color = texture(u_Texture, v_TexCoord).rgb * u_Exposure; + ivec2 texSize = textureSize(u_Texture); + ivec2 texCoord = ivec2(v_TexCoord * texSize); + vec4 msColor = MultiSampleTexture(u_Texture, texCoord, u_TextureSamples); + vec3 color = msColor.rgb * u_Exposure;//texture(u_Texture, v_TexCoord).rgb * u_Exposure; + // Reinhard tonemapping operator. // see: "Photographic Tone Reproduction for Digital Images", eq. 4 float luminance = dot(color, vec3(0.2126, 0.7152, 0.0722)); @@ -39,5 +53,5 @@ void main() vec3 mappedColor = (mappedLuminance / luminance) * color; // Gamma correction. - outColor = vec4(pow(mappedColor, vec3(1.0/gamma)), 1.0); + o_Color = vec4(pow(mappedColor, vec3(1.0 / gamma)), 1.0); } \ No newline at end of file diff --git a/Prism/CMakeLists.txt b/Prism/CMakeLists.txt index b0f525e..9bde539 100644 --- a/Prism/CMakeLists.txt +++ b/Prism/CMakeLists.txt @@ -83,6 +83,7 @@ set(STATIC_LIBRARY ${PROJECT_NAME}-static) add_library(${STATIC_LIBRARY} STATIC ${SRC_SOURCE}) target_compile_definitions(${STATIC_LIBRARY} PRIVATE + PUBLIC ${DEBUG_DEFINITIONS} INTERFACE PRISM_STATIC diff --git a/Prism/src/Prism/Core/Application.h b/Prism/src/Prism/Core/Application.h index ee09bfc..c122806 100644 --- a/Prism/src/Prism/Core/Application.h +++ b/Prism/src/Prism/Core/Application.h @@ -69,9 +69,9 @@ namespace Prism } #ifdef _MSC_VER - #define HZ_BIND_EVENT_FN(fn) std::bind(&##fn, this, std::placeholders::_1) + #define PM_BIND_EVENT_FN(fn) std::bind(&##fn, this, std::placeholders::_1) #else - #define HZ_BIND_EVENT_FN(fn) std::bind(&fn, this, std::placeholders::_1) + #define PM_BIND_EVENT_FN(fn) std::bind(&fn, this, std::placeholders::_1) #endif #endif //APPLICATION_H diff --git a/Prism/src/Prism/Core/Buffer.h b/Prism/src/Prism/Core/Buffer.h index 012b3e2..f81f26d 100644 --- a/Prism/src/Prism/Core/Buffer.h +++ b/Prism/src/Prism/Core/Buffer.h @@ -50,7 +50,7 @@ namespace Prism memset(Data, 0, Size); } - void Write(const byte* data, const uint32_t size, const uint32_t offset = 0) const + void Write(const void* data, const uint32_t size, const uint32_t offset = 0) const { PM_CORE_ASSERT(offset + size <= Size, "Buffer overflow!"); memcpy(Data + offset, data, size); diff --git a/Prism/src/Prism/Editor/SceneHierachyPanel.cpp b/Prism/src/Prism/Editor/SceneHierachyPanel.cpp index 465e370..495bac8 100644 --- a/Prism/src/Prism/Editor/SceneHierachyPanel.cpp +++ b/Prism/src/Prism/Editor/SceneHierachyPanel.cpp @@ -29,18 +29,11 @@ namespace Prism { ImGui::Begin("Scene Hierarchy"); + uint32_t entityCount = 0, meshCount = 0; auto& sceneEntities = m_Context->m_Entities; - for (Entity* entity : sceneEntities) + for (const auto& entity : sceneEntities) { - auto mesh = entity->GetMesh(); - auto material = entity->GetMaterial(); - const auto& transform = entity->GetTransform(); - - if (mesh) - { - DrawMeshNode(mesh); - } - + DrawEntityNode(entity, entityCount, meshCount); } ImGui::End(); @@ -89,7 +82,26 @@ namespace Prism } - static std::tuple GetTransformDecomposition(const glm::mat4& transform) + void SceneHierarchyPanel::DrawEntityNode(Entity* entity, uint32_t& imguiEntityID, uint32_t& imguiMeshID) + { + const char* name = entity->GetName().c_str(); + static char imguiName[128]; + memset(imguiName, 0, 128); + sprintf(imguiName, "%s##%d", name, imguiEntityID++); + if (ImGui::TreeNode(imguiName)) + { + auto mesh = entity->GetMesh(); + auto material = entity->GetMaterial(); + const auto& transform = entity->GetTransform(); + + if (mesh) + DrawMeshNode(mesh, imguiMeshID); + + ImGui::TreePop(); + } + } + + static std::tuple GetTransformDecomposition(const glm::mat4& transform) { glm::vec3 scale, translation, skew; glm::vec4 perspective; @@ -99,13 +111,23 @@ namespace Prism return { translation, orientation, scale }; } - void SceneHierarchyPanel::DrawMeshNode(const Ref& mesh) + void SceneHierarchyPanel::DrawMeshNode(const Ref& mesh, uint32_t& imguiMeshID) { - auto rootNode = mesh->m_Scene->mRootNode; - MeshNodeHierarchy(mesh, rootNode); + static char imguiName[128]; + memset(imguiName, 0, 128); + sprintf(imguiName, "Mesh##%d", imguiMeshID++); + + // Mesh Hierarchy + if (ImGui::TreeNode(imguiName)) + { + auto rootNode = mesh->m_Scene->mRootNode; + MeshNodeHierarchy(mesh, rootNode); + ImGui::TreePop(); + } } + void SceneHierarchyPanel::MeshNodeHierarchy(const Ref& mesh, aiNode* node, const glm::mat4& parentTransform, uint32_t level) { glm::mat4 localTransform = Mat4FromAssimpMat4(node->mTransformation); diff --git a/Prism/src/Prism/Editor/SceneHierachyPanel.h b/Prism/src/Prism/Editor/SceneHierachyPanel.h index 9d83756..27845c2 100644 --- a/Prism/src/Prism/Editor/SceneHierachyPanel.h +++ b/Prism/src/Prism/Editor/SceneHierachyPanel.h @@ -18,7 +18,8 @@ namespace Prism void OnImGuiRender(); private: - void DrawMeshNode(const Ref& mesh); + void DrawEntityNode(Entity* entity, uint32_t& imguiEntityID, uint32_t& imguiMeshID); + void DrawMeshNode(const Ref& mesh, uint32_t& imguiMeshID); void MeshNodeHierarchy(const Ref& mesh, aiNode* node, const glm::mat4& parentTransform = glm::mat4(1.0f), uint32_t level = 0); private: Ref m_Context; diff --git a/Prism/src/Prism/Platform/OpenGL/OpenGLFrameBuffer.cpp b/Prism/src/Prism/Platform/OpenGL/OpenGLFrameBuffer.cpp index b0a7b96..9243e75 100644 --- a/Prism/src/Prism/Platform/OpenGL/OpenGLFrameBuffer.cpp +++ b/Prism/src/Prism/Platform/OpenGL/OpenGLFrameBuffer.cpp @@ -26,7 +26,7 @@ namespace Prism void OpenGLFrameBuffer::Bind() const { - Renderer::Submit([this](){ + Renderer::Submit([=](){ glBindFramebuffer(GL_FRAMEBUFFER, m_RendererID); glViewport(0, 0, m_Specification.Width, m_Specification.Height); }); @@ -34,66 +34,116 @@ namespace Prism void OpenGLFrameBuffer::Unbind() const { - Renderer::Submit([this](){ + Renderer::Submit([=](){ glBindFramebuffer(GL_FRAMEBUFFER, 0); }); } void OpenGLFrameBuffer::Resize(const uint32_t width, const uint32_t height) { - if (m_RendererID && m_Specification.Width == width && m_Specification.Height == height) - return; + if (m_Specification.Width == width && m_Specification.Height == height) + return; - m_Specification.Width = width; - m_Specification.Height = height; - Renderer::Submit([this](){ - if (m_RendererID) - { - glDeleteFramebuffers(1, &m_RendererID); - glDeleteTextures(1, &m_ColorAttachment); - glDeleteTextures(1, &m_DepthAttachment); - } + m_Specification.Width = width; + m_Specification.Height = height; + Renderer::Submit([this]() + { + if (m_RendererID) + { + glDeleteFramebuffers(1, &m_RendererID); + glDeleteTextures(1, &m_ColorAttachment); + glDeleteTextures(1, &m_DepthAttachment); + } - glGenFramebuffers(1, &m_RendererID); - glBindFramebuffer(GL_FRAMEBUFFER, m_RendererID); + glGenFramebuffers(1, &m_RendererID); + glBindFramebuffer(GL_FRAMEBUFFER, m_RendererID); - glGenTextures(1, &m_ColorAttachment); - glBindTexture(GL_TEXTURE_2D, m_ColorAttachment); + bool multisample = m_Specification.Samples > 1; + if (multisample) + { + glCreateTextures(GL_TEXTURE_2D_MULTISAMPLE, 1, &m_ColorAttachment); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_ColorAttachment); - // TODO: Create Hazel texture object based on format here - if (m_Specification.Format == FramebufferFormat::RGBA16F) - { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, m_Specification.Width, m_Specification.Height, 0, GL_RGBA, GL_FLOAT, nullptr); - } - else if (m_Specification.Format == FramebufferFormat::RGBA8) - { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_Specification.Width, m_Specification.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_ColorAttachment, 0); + // TODO: Create Hazel texture object based on format here + if (m_Specification.Format == FramebufferFormat::RGBA16F) + { + glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_Specification.Samples, GL_RGBA16F, m_Specification.Width, m_Specification.Height, GL_FALSE); + //glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_Specification.Samples, GL_RGBA16F, m_Specification.Width, m_Specification.Height, GL_FALSE); + } + else if (m_Specification.Format == FramebufferFormat::RGBA8) + { + // glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 8, GL_RGBA8, m_Specification.Width, m_Specification.Height, GL_TRUE); + glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_Specification.Samples, GL_RGBA8, m_Specification.Width, m_Specification.Height, GL_FALSE); + } + // glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + // glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + // glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, m_ColorAttachment, 0); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); + } + else + { + glCreateTextures(GL_TEXTURE_2D, 1, &m_ColorAttachment); + glBindTexture(GL_TEXTURE_2D, m_ColorAttachment); - glGenTextures(1, &m_DepthAttachment); - glBindTexture(GL_TEXTURE_2D, m_DepthAttachment); - glTexImage2D( - GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, m_Specification.Width, m_Specification.Height, 0, - GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL - ); + // TODO: Create Hazel texture object based on format here + if (m_Specification.Format == FramebufferFormat::RGBA16F) + { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, m_Specification.Width, m_Specification.Height, 0, GL_RGBA, GL_FLOAT, nullptr); + } + else if (m_Specification.Format == FramebufferFormat::RGBA8) + { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_Specification.Width, m_Specification.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_ColorAttachment, 0); + } - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_DepthAttachment, 0); + if (multisample) + { + glCreateTextures(GL_TEXTURE_2D_MULTISAMPLE, 1, &m_DepthAttachment); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_DepthAttachment); + // glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 8, GL_DEPTH24_STENCIL8, m_Specification.Width, m_Specification.Height, GL_TRUE); + glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_Specification.Samples, GL_DEPTH24_STENCIL8, m_Specification.Width, m_Specification.Height, GL_FALSE); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); + // glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, m_DepthAttachment, 0); + } + else + { + glCreateTextures(GL_TEXTURE_2D, 1, &m_DepthAttachment); + glBindTexture(GL_TEXTURE_2D, m_DepthAttachment); + glTexImage2D( + GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, m_Specification.Width, m_Specification.Height, 0, + GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL + ); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_DepthAttachment, 0); + } - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - PM_CORE_ERROR("Framebuffer is incomplete!"); + // glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_ColorAttachment, 0); + if (multisample) + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, m_ColorAttachment, 0); + else + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_ColorAttachment, 0); + glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, m_DepthAttachment, 0); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - }); + PM_CORE_ASSERT(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Framebuffer is incomplete!"); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + }); } - void OpenGLFrameBuffer::BindTexture(uint32_t slot) const + void OpenGLFrameBuffer::BindTexture(const uint32_t slot) const { - Renderer::Submit([this, slot](){ + Renderer::Submit([=](){ glActiveTexture(GL_TEXTURE0 + slot); - glBindTexture(GL_TEXTURE_2D, m_ColorAttachment); + + if (m_Specification.Samples > 1) { + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_ColorAttachment); + } else { + glBindTexture(GL_TEXTURE_2D, m_ColorAttachment); + } + + // glBindTexture(GL_TEXTURE_2D, m_ColorAttachment); }); } } diff --git a/Prism/src/Prism/Platform/OpenGL/OpenGLRendererAPI.cpp b/Prism/src/Prism/Platform/OpenGL/OpenGLRendererAPI.cpp index 16b9eb0..14747bf 100644 --- a/Prism/src/Prism/Platform/OpenGL/OpenGLRendererAPI.cpp +++ b/Prism/src/Prism/Platform/OpenGL/OpenGLRendererAPI.cpp @@ -12,17 +12,6 @@ namespace Prism { static void OpenGLLogMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) { - /* - if (severity != GL_DEBUG_SEVERITY_NOTIFICATION) - { - - PM_CORE_ERROR("{0}", message); - PM_CORE_ASSERT(false, ""); - }else - { - PM_CORE_TRACE("{0}", message); - } - */ if (severity == GL_DEBUG_SEVERITY_NOTIFICATION) { @@ -81,11 +70,10 @@ namespace Prism switch (severity) { case GL_DEBUG_SEVERITY_HIGH: - PM_CORE_ERROR("[OpenGL HIGH] Source: {0}, Type: {1}, ID: {2}\nMessage: {3}", - sourceStr, typeStr, id, message); - if (type == GL_DEBUG_TYPE_ERROR) + PM_CORE_ERROR("[OpenGL HIGH] Source: {0}, Type: {1}, ID: {2}\nMessage: {3}", sourceStr, typeStr, id, message); + if(type == GL_DEBUG_TYPE_ERROR) { - PM_CORE_ASSERT(false, "OpenGL严重错误"); + PM_CORE_ASSERT(false, "ERROR"); } break; @@ -134,6 +122,7 @@ namespace Prism glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_MULTISAMPLE); auto& caps = GetCapabilities(); @@ -143,6 +132,7 @@ namespace Prism glGetIntegerv(GL_MAX_SAMPLES, &caps.MaxSamples); glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY, &caps.MaxAnisotropy); + glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &caps.MaxTextureUnits); GLenum error = glGetError(); @@ -168,14 +158,30 @@ namespace Prism glClearColor(r, g, b, a); } - void RendererAPI::DrawIndexed(const unsigned int count, const bool depthTest) + void RendererAPI::DrawIndexed(uint32_t count, PrimitiveType type, bool depthTest) { if (!depthTest) glDisable(GL_DEPTH_TEST); - glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, nullptr); + GLenum glPrimitiveType = 0; + switch (type) + { + case PrimitiveType::Triangles: + glPrimitiveType = GL_TRIANGLES; + break; + case PrimitiveType::Lines: + glPrimitiveType = GL_LINES; + break; + } + + glDrawElements(glPrimitiveType, count, GL_UNSIGNED_INT, nullptr); if (!depthTest) glEnable(GL_DEPTH_TEST); } + + void RendererAPI::SetLineThickness(const float thickness) + { + glLineWidth(thickness); + } } diff --git a/Prism/src/Prism/Platform/OpenGL/OpenGLShader.cpp b/Prism/src/Prism/Platform/OpenGL/OpenGLShader.cpp index a8755f8..456e7e2 100644 --- a/Prism/src/Prism/Platform/OpenGL/OpenGLShader.cpp +++ b/Prism/src/Prism/Platform/OpenGL/OpenGLShader.cpp @@ -40,7 +40,7 @@ namespace Prism if (!m_IsCompute) Parse(); - Renderer::Submit([this](){ + Renderer::Submit([=](){ auto &a = m_RendererID; if (m_RendererID) glDeleteProgram(m_RendererID); @@ -125,6 +125,13 @@ namespace Prism }); } + void OpenGLShader::SetInt(const std::string& name, int value) + { + Renderer::Submit([=]() { + UploadUniformInt(name, value); + }); + } + void OpenGLShader::SetMat4(const std::string& name, const glm::mat4& value) { Renderer::Submit([=]() { @@ -132,6 +139,13 @@ namespace Prism }); } + void OpenGLShader::SetIntArray(const std::string& name, int* values, uint32_t size) + { + Renderer::Submit([=]() { + UploadUniformIntArray(name, values, size); + }); + } + void OpenGLShader::SetVSMaterialUniformBuffer(Buffer buffer) { Renderer::Submit([this, buffer]() { @@ -351,6 +365,7 @@ namespace Prism static bool IsTypeStringResource(const std::string& type) { if (type == "sampler2D") return true; + if (type == "sampler2DMS") return true; if (type == "samplerCube") return true; if (type == "sampler2DShadow") return true; return false; @@ -371,7 +386,7 @@ namespace Prism { int32_t result = glGetUniformLocation(m_RendererID, name.c_str()); if (result == -1) - PM_CORE_WARN("Could not find uniform '{0}' in shader", name); + PM_CORE_WARN("Could not find uniform '{0}' in shader: {1}", name, m_Name); return result; } @@ -932,7 +947,7 @@ namespace Prism } } - void OpenGLShader::UploadUniformIntArray(const std::string& name, const int32_t* values, const int32_t count) const + void OpenGLShader::UploadUniformIntArray(const std::string& name, const int32_t* values, const uint32_t count) const { int32_t location = GetUniformLocation(name); glUniform1iv(location, count, values); diff --git a/Prism/src/Prism/Platform/OpenGL/OpenGLShader.h b/Prism/src/Prism/Platform/OpenGL/OpenGLShader.h index 41b4f6a..cfaed54 100644 --- a/Prism/src/Prism/Platform/OpenGL/OpenGLShader.h +++ b/Prism/src/Prism/Platform/OpenGL/OpenGLShader.h @@ -28,8 +28,11 @@ namespace Prism virtual void AddShaderReloadedCallback(const ShaderReloadedCallback& callback) override; virtual void SetFloat(const std::string& name, float value) override; + virtual void SetInt(const std::string& name, int value) override; virtual void SetMat4(const std::string& name, const glm::mat4& value) override; + virtual void SetIntArray(const std::string& name, int* values, uint32_t size) override; + virtual void SetVSMaterialUniformBuffer(Buffer buffer) override; virtual void SetPSMaterialUniformBuffer(Buffer buffer) override; @@ -81,7 +84,7 @@ namespace Prism void UploadUniformMat4Array(uint32_t location, const glm::mat4& values, uint32_t count); void UploadUniformStruct(const OpenGLShaderUniformDeclaration* uniform, byte* buffer, uint32_t offset); - void UploadUniformIntArray(const std::string& name, const int32_t* values, int32_t count) const; + void UploadUniformIntArray(const std::string& name, const int32_t* values, uint32_t count) const; virtual const ShaderUniformBufferList& GetVSRendererUniforms() const override { return m_VSRendererUniformBuffers; } virtual const ShaderUniformBufferList& GetPSRendererUniforms() const override { return m_PSRendererUniformBuffers; } diff --git a/Prism/src/Prism/Platform/OpenGL/OpenGLShaderUniform.cpp b/Prism/src/Prism/Platform/OpenGL/OpenGLShaderUniform.cpp index 9f2d908..53709a0 100644 --- a/Prism/src/Prism/Platform/OpenGL/OpenGLShaderUniform.cpp +++ b/Prism/src/Prism/Platform/OpenGL/OpenGLShaderUniform.cpp @@ -48,6 +48,7 @@ namespace Prism OpenGLShaderUniformDeclaration::Type OpenGLShaderUniformDeclaration::StringToType(const std::string& type) { + if (type == "int") return Type::INT32; if (type == "int32") return Type::INT32; if (type == "float") return Type::FLOAT32; if (type == "vec2") return Type::VEC2; @@ -112,6 +113,7 @@ namespace Prism OpenGLShaderResourceDeclaration::Type OpenGLShaderResourceDeclaration::StringToType(const std::string& type) { if (type == "sampler2D") return Type::TEXTURE2D; + if (type == "sampler2DMS") return Type::TEXTURE2D; if (type == "samplerCube") return Type::TEXTURECUBE; return Type::NONE; @@ -121,7 +123,7 @@ namespace Prism { switch (type) { - case Type::TEXTURE2D: return "sampler2D"; + case Type::TEXTURE2D: return "sampler2D"; case Type::TEXTURECUBE: return "samplerCube"; } return "Invalid Type"; diff --git a/Prism/src/Prism/Platform/OpenGL/OpenGLShaderUniform.h b/Prism/src/Prism/Platform/OpenGL/OpenGLShaderUniform.h index 444491d..8b66153 100644 --- a/Prism/src/Prism/Platform/OpenGL/OpenGLShaderUniform.h +++ b/Prism/src/Prism/Platform/OpenGL/OpenGLShaderUniform.h @@ -70,7 +70,7 @@ namespace Prism int32_t GetLocation() const { return m_Location; } inline Type GetType() const { return m_Type; } inline bool IsArray() const { return m_Count > 1; } - inline const ShaderStruct& GetShaderUniformStruct() const { PM_CORE_ASSERT(m_Struct, ""); return *m_Struct; } + inline const ShaderStruct& GetShaderUniformStruct() const { PM_CORE_ASSERT(m_Struct); return *m_Struct; } protected: void SetOffset(uint32_t offset) override; public: diff --git a/Prism/src/Prism/Platform/OpenGL/OpenGLTexture.cpp b/Prism/src/Prism/Platform/OpenGL/OpenGLTexture.cpp index 477b550..8c058bd 100644 --- a/Prism/src/Prism/Platform/OpenGL/OpenGLTexture.cpp +++ b/Prism/src/Prism/Platform/OpenGL/OpenGLTexture.cpp @@ -42,11 +42,12 @@ namespace Prism glTextureParameterf(m_RendererID, GL_TEXTURE_MAX_ANISOTROPY, RendererAPI::GetCapabilities().MaxAnisotropy); glTexImage2D(GL_TEXTURE_2D, 0, PrismToOpenGLTextureFormat(m_Format), (GLint)m_Width, (GLint)m_Height, 0, Prism::PrismToOpenGLTextureFormat(m_Format), GL_UNSIGNED_BYTE, nullptr); - glGenerateMipmap(GL_TEXTURE_2D); + // glGenerateMipmap(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); }); + m_ImageData.Allocate(width * height * GetBPP(m_Format)); } diff --git a/Prism/src/Prism/Platform/OpenGL/OpenGLTexture.h b/Prism/src/Prism/Platform/OpenGL/OpenGLTexture.h index 9f83686..5268f3f 100644 --- a/Prism/src/Prism/Platform/OpenGL/OpenGLTexture.h +++ b/Prism/src/Prism/Platform/OpenGL/OpenGLTexture.h @@ -38,6 +38,11 @@ namespace Prism virtual const std::string& GetPath() const override { return m_FilePath; } virtual RendererID GetRendererID() const override { return m_RendererID; } + + virtual bool operator==(const Texture& other) const override + { + return m_RendererID == ((OpenGLTexture2D&)other).m_RendererID; + } private: RendererID m_RendererID; TextureFormat m_Format; @@ -73,6 +78,10 @@ namespace Prism virtual RendererID GetRendererID() const override { return m_RendererID; } + virtual bool operator==(const Texture& other) const override + { + return m_RendererID == ((OpenGLTextureCube&)other).m_RendererID; + } private: RendererID m_RendererID; TextureFormat m_Format; diff --git a/Prism/src/Prism/Platform/OpenGL/OpenGLVertexArray.h b/Prism/src/Prism/Platform/OpenGL/OpenGLVertexArray.h index c639e9f..ae8da7e 100644 --- a/Prism/src/Prism/Platform/OpenGL/OpenGLVertexArray.h +++ b/Prism/src/Prism/Platform/OpenGL/OpenGLVertexArray.h @@ -21,8 +21,9 @@ namespace Prism virtual void AddVertexBuffer(const Ref& vertexBuffer) override; virtual void SetIndexBuffer(const Ref& indexBuffer) override; - virtual const std::vector>& GetVertexBuffers() const { return m_VertexBuffers; } - virtual const Ref& GetIndexBuffer() const { return m_IndexBuffer; } + virtual const std::vector>& GetVertexBuffers() const override { return m_VertexBuffers; } + virtual const Ref& GetIndexBuffer() const override { return m_IndexBuffer; } + virtual RendererID GetRendererID() const override { return m_RendererID; } private: RendererID m_RendererID = 0; uint32_t m_VertexBufferIndex = 0; diff --git a/Prism/src/Prism/Renderer/Camera.cpp b/Prism/src/Prism/Renderer/Camera.cpp index 61902b7..2ce80de 100644 --- a/Prism/src/Prism/Renderer/Camera.cpp +++ b/Prism/src/Prism/Renderer/Camera.cpp @@ -10,7 +10,9 @@ #include "glm/gtc/quaternion.hpp" #define GLM_ENABLE_EXPERIMENTAL #include "glm/gtx/quaternion.hpp" +#include "Prism/Core/Application.h" #include "Prism/Core/Input.h" +#include "Prism/Core/Events/MouseEvent.h" #ifndef M_PI #define M_PI 3.1415926f @@ -36,7 +38,7 @@ namespace Prism { } - void Camera::Update(TimeStep deltaTime) + void Camera::OnUpdate(TimeStep deltaTime) { if (Input::IsKeyPressed(GLFW_KEY_LEFT_ALT)) { @@ -63,6 +65,12 @@ namespace Prism m_ViewMatrix = glm::inverse(m_ViewMatrix); } + void Camera::OnEvent(Event& e) + { + EventDispatcher dispatcher(e); + dispatcher.Dispatch(PM_BIND_EVENT_FN(Camera::OnMouseScroll)); + } + glm::vec3 Camera::GetUpDirection() { return glm::rotate(GetOrientation(), glm::vec3(0.0f, 1.0f, 0.0f)); @@ -78,6 +86,13 @@ namespace Prism return glm::rotate(GetOrientation(), glm::vec3(0.0f, 0.0f, -1.0f)); } + bool Camera::OnMouseScroll(MouseScrolledEvent& e) + { + const float delta = e.GetOffsetY() * 0.1f; + MouseZoom(delta); + return false; + } + void Camera::MousePan(const glm::vec2& delta) { auto [xSpeed, ySpeed] = PanSpeed(); diff --git a/Prism/src/Prism/Renderer/Camera.h b/Prism/src/Prism/Renderer/Camera.h index fd76140..4042726 100644 --- a/Prism/src/Prism/Renderer/Camera.h +++ b/Prism/src/Prism/Renderer/Camera.h @@ -6,11 +6,12 @@ #define CAMERA_H #include - #include "Prism/Core/TimeStep.h" namespace Prism { + class MouseScrolledEvent; + class Event; class PRISM_API Camera { @@ -19,7 +20,8 @@ namespace Prism Camera(const glm::mat4& projectionMatrix); void Focus(); - void Update(TimeStep deltaTime); + void OnUpdate(TimeStep deltaTime); + void OnEvent(Event& e); inline float GetDistance() const { return m_Distance; } inline void SetDistance(float distance) { m_Distance = distance; } @@ -28,6 +30,7 @@ namespace Prism const glm::mat4& GetProjectionMatrix() const { return m_ProjectionMatrix; } const glm::mat4& GetViewMatrix() const { return m_ViewMatrix; } + glm::mat4 GetViewProjection() const { return m_ProjectionMatrix * m_ViewMatrix; } glm::vec3 GetUpDirection(); glm::vec3 GetRightDirection(); @@ -40,6 +43,7 @@ namespace Prism public: inline void SetViewportSize(const uint32_t width, const uint32_t height) { m_ViewportWidth = width; m_ViewportHeight = height; } private: + bool OnMouseScroll(MouseScrolledEvent& e); void MousePan(const glm::vec2& delta); void MouseRotate(const glm::vec2& delta); void MouseZoom(float delta); diff --git a/Prism/src/Prism/Renderer/FrameBuffer.h b/Prism/src/Prism/Renderer/FrameBuffer.h index 8bf5eda..46dc016 100644 --- a/Prism/src/Prism/Renderer/FrameBuffer.h +++ b/Prism/src/Prism/Renderer/FrameBuffer.h @@ -23,6 +23,7 @@ namespace Prism uint32_t Height = 720; glm::vec4 ClearColor; FramebufferFormat Format; + uint32_t Samples = 1; // SwapChainTarget = screen buffer (i.e. no framebuffer) bool SwapChainTarget = false; diff --git a/Prism/src/Prism/Renderer/Material.cpp b/Prism/src/Prism/Renderer/Material.cpp index 5b33315..0a4a27d 100644 --- a/Prism/src/Prism/Renderer/Material.cpp +++ b/Prism/src/Prism/Renderer/Material.cpp @@ -45,6 +45,7 @@ namespace Prism void Material::OnShaderReloaded() { + return; AllocateStorage(); for (auto mi : m_MaterialInstances) diff --git a/Prism/src/Prism/Renderer/Material.h b/Prism/src/Prism/Renderer/Material.h index c3c0125..90ed755 100644 --- a/Prism/src/Prism/Renderer/Material.h +++ b/Prism/src/Prism/Renderer/Material.h @@ -98,7 +98,7 @@ namespace Prism const auto decl = m_Material->FindUniformDeclaration(name); if (!decl) PM_CORE_WARN("Could not find uniform with name {0}", name); auto& buffer = GetUniformBufferTarget(decl); - buffer.Write((byte*)& value, decl->GetSize(), decl->GetOffset()); + buffer.Write(&value, decl->GetSize(), decl->GetOffset()); m_OverriddenValues.insert(name); } @@ -152,7 +152,7 @@ namespace Prism // HZ_CORE_ASSERT(decl, "Could not find uniform with name '{0}'", name); PM_CORE_ASSERT(decl, "Could not find uniform with name 'x'"); auto& buffer = GetUniformBufferTarget(decl); - buffer.Write((byte*)&value, decl->GetSize(), decl->GetOffset()); + buffer.Write(&value, decl->GetSize(), decl->GetOffset()); for (auto mi : m_MaterialInstances) mi->OnMaterialValueUpdated(decl); diff --git a/Prism/src/Prism/Renderer/Mesh.cpp b/Prism/src/Prism/Renderer/Mesh.cpp index 30020be..29d95f5 100644 --- a/Prism/src/Prism/Renderer/Mesh.cpp +++ b/Prism/src/Prism/Renderer/Mesh.cpp @@ -155,12 +155,23 @@ namespace Prism } }else { - for (size_t i = 0; i < mesh->mNumVertices; i++) + submesh.Min = { FLT_MAX, FLT_MAX, FLT_MAX }; + submesh.Max = { -FLT_MAX, -FLT_MAX, -FLT_MAX }; + + for (size_t i = 0; i < mesh->mNumVertices; i++) { Vertex vertex; vertex.Position = { mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z }; vertex.Normal = { mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z }; + submesh.Min.x = glm::min(vertex.Position.x, submesh.Min.x); + submesh.Min.y = glm::min(vertex.Position.y, submesh.Min.y); + submesh.Min.z = glm::min(vertex.Position.z, submesh.Min.z); + submesh.Max.x = glm::max(vertex.Position.x, submesh.Max.x); + submesh.Max.y = glm::max(vertex.Position.y, submesh.Max.y); + submesh.Max.z = glm::max(vertex.Position.z, submesh.Max.z); + + if (mesh->HasTangentsAndBitangents()) { vertex.Tangent = { mesh->mTangents[i].x, mesh->mTangents[i].y, mesh->mTangents[i].z }; @@ -273,8 +284,97 @@ namespace Prism { mi->Set("u_AlbedoTexToggle", 0.0f); mi->Set("u_AlbedoColor", glm::vec3 { aiColor.r, aiColor.g, aiColor.b }); + + PM_CORE_INFO("Mesh has no albedo map"); } + // Normal Maps + mi->Set("u_NormalTexToggle", 0.0f); + + if (aiMaterial->GetTexture(aiTextureType_NORMALS, 0, &aiTexPath) == AI_SUCCESS) + { + // TODO: Temp - this should be handled by Hazel's filesystem + std::filesystem::path path = filename; + auto parentPath = path.parent_path(); + parentPath /= std::string(aiTexPath.data); + std::string texturePath = parentPath.string(); + + auto texture = Texture2D::Create(texturePath); + if (texture->Loaded()) + { + PM_CORE_TRACE(" Normal map path = {0}", texturePath); + mi->Set("u_NormalTexture", texture); + mi->Set("u_NormalTexToggle", 1.0f); + } + else + { + PM_CORE_ERROR("Could not load texture: {0}", texturePath); + } + } + else + { + PM_CORE_TRACE("Mesh has no normal map"); + } + + // Roughness map + // mi->Set("u_Roughness", 1.0f); + // mi->Set("u_RoughnessTexToggle", 0.0f); + if (aiMaterial->GetTexture(aiTextureType_SHININESS, 0, &aiTexPath) == AI_SUCCESS) + { + // TODO: Temp - this should be handled by Hazel's filesystem + std::filesystem::path path = filename; + auto parentPath = path.parent_path(); + parentPath /= std::string(aiTexPath.data); + std::string texturePath = parentPath.string(); + + auto texture = Texture2D::Create(texturePath); + if (texture->Loaded()) + { + PM_CORE_TRACE(" Roughness map path = {0}", texturePath); + mi->Set("u_RoughnessTexture", texture); + mi->Set("u_RoughnessTexToggle", 1.0f); + } + else + { + PM_CORE_ERROR("Could not load texture: {0}", texturePath); + } + } + else + { + PM_CORE_TRACE("Mesh has no roughness texture"); + } + + // Metalness map + // mi->Set("u_Metalness", 0.0f); + // mi->Set("u_MetalnessTexToggle", 0.0f); + if (aiMaterial->Get("$raw.ReflectionFactor|file", aiPTI_String, 0, aiTexPath) == AI_SUCCESS) + { + // TODO: Temp - this should be handled by Hazel's filesystem + std::filesystem::path path = filename; + auto parentPath = path.parent_path(); + parentPath /= std::string(aiTexPath.data); + std::string texturePath = parentPath.string(); + + auto texture = Texture2D::Create(texturePath); + if (texture->Loaded()) + { + PM_CORE_TRACE(" Metalness map path = {0}", texturePath); + mi->Set("u_MetalnessTexture", texture); + mi->Set("u_MetalnessTexToggle", 1.0f); + } + else + { + PM_CORE_ERROR("Could not load texture: {0}", texturePath); + } + } + else + { + PM_CORE_TRACE("Mesh has no metalness texture"); + } + continue; + + + for (uint32_t i = 0; i < aiMaterial->mNumProperties; i++) { auto prop = aiMaterial->mProperties[i]; @@ -357,6 +457,7 @@ namespace Prism } + /* // Normal maps if (aiMaterial->GetTexture(aiTextureType_NORMALS, 0, &aiTexPath) == AI_SUCCESS) { @@ -428,6 +529,8 @@ namespace Prism mi->Set("u_MetalnessTexToggle", 1.0f); } } + */ + } } diff --git a/Prism/src/Prism/Renderer/Mesh.h b/Prism/src/Prism/Renderer/Mesh.h index f33a497..12c1cbc 100644 --- a/Prism/src/Prism/Renderer/Mesh.h +++ b/Prism/src/Prism/Renderer/Mesh.h @@ -87,6 +87,7 @@ namespace Prism uint32_t IndexCount; glm::mat4 Transform; + glm::vec3 Min, Max; //TODO: AABB }; class PRISM_API Mesh diff --git a/Prism/src/Prism/Renderer/Renderer.cpp b/Prism/src/Prism/Renderer/Renderer.cpp index e2f3868..b4aa61b 100644 --- a/Prism/src/Prism/Renderer/Renderer.cpp +++ b/Prism/src/Prism/Renderer/Renderer.cpp @@ -4,6 +4,7 @@ #include "Renderer.h" +#include "Renderer2D.h" #include "RendererAPI.h" #include "SceneRenderer.h" #include "glad/glad.h" @@ -35,10 +36,10 @@ namespace Prism // FullScreen Quad static float fullScreenQuadVertex[] = { - -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, - 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, - -1.0f, 1.0f, 0.0f, 0.0f, 1.0f + -1.0f, -1.0f, 0.1f, 0.0f, 0.0f, + 1.0f, -1.0f, 0.1f, 1.0f, 0.0f, + 1.0f, 1.0f, 0.1f, 1.0f, 1.0f, + -1.0f, 1.0f, 0.1f, 0.0f, 1.0f }; static uint32_t fullScreenQuadIndices[] = { 0, 1, 2, 2, 3, 0 @@ -55,6 +56,7 @@ namespace Prism s_Data.m_FullscreenQuadVertexArray->AddVertexBuffer(quadVB); s_Data.m_FullscreenQuadVertexArray->SetIndexBuffer(quadIB); + Renderer2D::Init(); } void Renderer::Clear() @@ -76,10 +78,10 @@ namespace Prism { } - void Renderer::DrawIndexed(uint32_t count, bool depthTest) + void Renderer::DrawIndexed(const uint32_t count, const PrimitiveType type, const bool depthTest) { Submit([=]() { - RendererAPI::DrawIndexed(count, depthTest); + RendererAPI::DrawIndexed(count, type, depthTest); }); } @@ -90,12 +92,19 @@ namespace Prism return s_Data.m_ShaderLibrary; } + void Renderer::SetLineThickness(const float thickness) + { + Submit([=]() { + RendererAPI::SetLineThickness(thickness); + }); + } + void Renderer::WaitAndRender() { s_Data.m_CommandQueue.Execute(); } - void Renderer::BeginRenderPass(const Ref& renderPass) + void Renderer::BeginRenderPass(const Ref& renderPass, bool clear) { PM_CORE_ASSERT(renderPass, "Render pass cannot be null!"); @@ -103,10 +112,14 @@ namespace Prism s_Data.m_ActiveRenderPass = renderPass; renderPass->GetSpecification().TargetFramebuffer->Bind(); - const glm::vec4& clearColor = renderPass->GetSpecification().TargetFramebuffer->GetSpecification().ClearColor; - Renderer::Submit([=]() { - RendererAPI::Clear(clearColor.r, clearColor.g, clearColor.b, clearColor.a); - }); + + if (clear) + { + const glm::vec4& clearColor = renderPass->GetSpecification().TargetFramebuffer->GetSpecification().ClearColor; + Submit([=]() { + RendererAPI::Clear(clearColor.r, clearColor.g, clearColor.b, clearColor.a); + }); + } } void Renderer::EndRenderPass() @@ -129,7 +142,7 @@ namespace Prism } s_Data.m_FullscreenQuadVertexArray->Bind(); - Renderer::DrawIndexed(6, depthTest); + Renderer::DrawIndexed(6, PrimitiveType::Triangles, depthTest); } void Renderer::SubmitFullscreenQuad(const Ref& material) @@ -142,7 +155,7 @@ namespace Prism } s_Data.m_FullscreenQuadVertexArray->Bind(); - Renderer::DrawIndexed(6, depthTest); + Renderer::DrawIndexed(6, PrimitiveType::Triangles, depthTest); } void Renderer::SubmitMesh(const Ref& mesh, const glm::mat4& transform, const Ref& overrideMaterial) @@ -182,6 +195,36 @@ namespace Prism } } + void Renderer::DrawAABB(const Ref& mesh, const glm::vec4& color) + { + for (Submesh& submesh : mesh->m_Submeshes) + { + const auto& transform = submesh.Transform; + + const glm::vec4 corners[8] = + { + transform * glm::vec4 { submesh.Min.x, submesh.Min.y, submesh.Max.z, 1.0f }, + transform * glm::vec4 { submesh.Min.x, submesh.Max.y, submesh.Max.z, 1.0f }, + transform * glm::vec4 { submesh.Max.x, submesh.Max.y, submesh.Max.z, 1.0f }, + transform * glm::vec4 { submesh.Max.x, submesh.Min.y, submesh.Max.z, 1.0f }, + + transform * glm::vec4 { submesh.Min.x, submesh.Min.y, submesh.Min.z, 1.0f }, + transform * glm::vec4 { submesh.Min.x, submesh.Max.y, submesh.Min.z, 1.0f }, + transform * glm::vec4 { submesh.Max.x, submesh.Max.y, submesh.Min.z, 1.0f }, + transform * glm::vec4 { submesh.Max.x, submesh.Min.y, submesh.Min.z, 1.0f } + }; + + for (uint32_t i = 0; i < 4; i++) + Renderer2D::DrawLine(corners[i], corners[(i + 1) % 4], color); + + for (uint32_t i = 0; i < 4; i++) + Renderer2D::DrawLine(corners[i + 4], corners[((i + 1) % 4) + 4], color); + + for (uint32_t i = 0; i < 4; i++) + Renderer2D::DrawLine(corners[i], corners[i + 4], color); + } + } + RenderCommandQueue& Renderer::GetRenderCommandQueue() { return s_Data.m_CommandQueue; diff --git a/Prism/src/Prism/Renderer/Renderer.h b/Prism/src/Prism/Renderer/Renderer.h index f4f9f0c..7571ba2 100644 --- a/Prism/src/Prism/Renderer/Renderer.h +++ b/Prism/src/Prism/Renderer/Renderer.h @@ -22,11 +22,13 @@ namespace Prism static void Clear(); static void Clear(float r, float g, float b, float a = 1.0f); static void SetClearColor(float r, float g, float b, float a); - static void DrawIndexed(uint32_t count, bool depthTest = true); - static const Scope& GetShaderLibrary(); + static void DrawIndexed(uint32_t count, PrimitiveType type, bool depthTest = true); + // For OpenGL + static void SetLineThickness(float thickness); + template static void Submit(FuncT&& func) { @@ -47,13 +49,14 @@ namespace Prism public: - static void BeginRenderPass(const Ref& renderPass); + static void BeginRenderPass(const Ref& renderPass, bool clear = true); static void EndRenderPass(); static void SubmitQuad(const Ref& material, const glm::mat4& transform = glm::mat4(1.0f)); static void SubmitFullscreenQuad(const Ref& material); static void SubmitMesh(const Ref& mesh, const glm::mat4& transform, const Ref& overrideMaterial = nullptr); + static void DrawAABB(const Ref& mesh, const glm::vec4& color = glm::vec4(1.0f)); private: static RenderCommandQueue& GetRenderCommandQueue(); }; diff --git a/Prism/src/Prism/Renderer/Renderer2D.cpp b/Prism/src/Prism/Renderer/Renderer2D.cpp new file mode 100644 index 0000000..b40d901 --- /dev/null +++ b/Prism/src/Prism/Renderer/Renderer2D.cpp @@ -0,0 +1,418 @@ +// +// Created by sfd on 25-12-1. +// + +#include "Renderer2D.h" + +#include "Renderer.h" +#include "Shader.h" +#include "VertexArray.h" + +namespace Prism +{ + + struct QuadVertex + { + glm::vec3 Position; + glm::vec4 Color; + glm::vec2 TexCoord; + float TexIndex; + float TilingFactor; + }; + + struct LineVertex + { + glm::vec3 Position; + glm::vec4 Color; + }; + + struct Renderer2DData + { + static constexpr uint32_t MaxQuads = 20000; + static constexpr uint32_t MaxVertices = MaxQuads * 4; + static constexpr uint32_t MaxIndices = MaxQuads * 6; + static constexpr uint32_t MaxTextureSlots = 32; // TODO: RenderCaps + + static constexpr uint32_t MaxLines = 10000; + static constexpr uint32_t MaxLineVertices = MaxLines * 2; + static constexpr uint32_t MaxLineIndices = MaxLines * 6; + + // Quad + Ref QuadVertexArray; + Ref QuadVertexBuffer; + Ref TextureShader; + Ref WhiteTexture; + + uint32_t QuadIndexCount = 0; + QuadVertex* QuadVertexBufferBase = nullptr; + QuadVertex* QuadVertexBufferPtr = nullptr; + + std::array, MaxTextureSlots> TextureSlots; + uint32_t TextureSlotIndex = 1; // 0 = white texture + + glm::vec4 QuadVertexPositions[4]; + + + // Lines + Ref LineVertexArray; + Ref LineVertexBuffer; + Ref LineShader; + + uint32_t LineIndexCount = 0; + LineVertex* LineVertexBufferBase = nullptr; + LineVertex* LineVertexBufferPtr = nullptr; + + glm::mat4 CameraViewProj; + bool DepthTest = true; + + Renderer2D::Statistics Stats; + }; + + static Renderer2DData s_Data; + static glm::vec2 defaultTexCoords[] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}}; + + + void Renderer2D::Init() + { + s_Data.QuadVertexArray = VertexArray::Create(); + + s_Data.QuadVertexBuffer = VertexBuffer::Create(s_Data.MaxVertices * sizeof(QuadVertex)); + s_Data.QuadVertexBuffer->SetLayout({ + { ShaderDataType::Float3, "a_Position" }, + { ShaderDataType::Float4, "a_Color" }, + { ShaderDataType::Float2, "a_TexCoord" }, + { ShaderDataType::Float, "a_TexIndex" }, + { ShaderDataType::Float, "a_TilingFactor" } + }); + s_Data.QuadVertexArray->AddVertexBuffer(s_Data.QuadVertexBuffer); + + s_Data.QuadVertexBufferBase = new QuadVertex[s_Data.MaxVertices]; + + uint32_t* quadIndices = new uint32_t[s_Data.MaxIndices]; + + uint32_t offset = 0; + for (uint32_t i = 0; i < s_Data.MaxIndices; i += 6) + { + quadIndices[i + 0] = offset + 0; + quadIndices[i + 1] = offset + 1; + quadIndices[i + 2] = offset + 2; + + quadIndices[i + 3] = offset + 2; + quadIndices[i + 4] = offset + 3; + quadIndices[i + 5] = offset + 0; + + offset += 4; + } + + Ref quadIB = IndexBuffer::Create(quadIndices, s_Data.MaxIndices); + s_Data.QuadVertexArray->SetIndexBuffer(quadIB); + delete[] quadIndices; + + s_Data.WhiteTexture = Texture2D::Create(TextureFormat::RGBA, 1, 1); + uint32_t whiteTextureData = 0xffffffff; + s_Data.WhiteTexture->Lock(); + s_Data.WhiteTexture->GetWriteableBuffer().Write(&whiteTextureData, sizeof(uint32_t)); + s_Data.WhiteTexture->Unlock(); + + s_Data.TextureShader = Shader::Create("assets/shaders/Renderer2D.glsl"); + + // Set all texture slots to 0 + s_Data.TextureSlots[0] = s_Data.WhiteTexture; + + s_Data.QuadVertexPositions[0] = { -0.5f, -0.5f, 0.0f, 1.0f }; + s_Data.QuadVertexPositions[1] = { 0.5f, -0.5f, 0.0f, 1.0f }; + s_Data.QuadVertexPositions[2] = { 0.5f, 0.5f, 0.0f, 1.0f }; + s_Data.QuadVertexPositions[3] = { -0.5f, 0.5f, 0.0f, 1.0f }; + + // Lines + s_Data.LineShader = Shader::Create("assets/shaders/Renderer2D_Line.glsl"); + s_Data.LineVertexArray = VertexArray::Create(); + + s_Data.LineVertexBuffer = VertexBuffer::Create(s_Data.MaxLineVertices * sizeof(LineVertex)); + s_Data.LineVertexBuffer->SetLayout({ + { ShaderDataType::Float3, "a_Position" }, + { ShaderDataType::Float4, "a_Color" } + }); + s_Data.LineVertexArray->AddVertexBuffer(s_Data.LineVertexBuffer); + + s_Data.LineVertexBufferBase = new LineVertex[s_Data.MaxLineVertices]; + + uint32_t* lineIndices = new uint32_t[s_Data.MaxLineIndices]; + for (uint32_t i = 0; i < s_Data.MaxLineIndices; i++) + lineIndices[i] = i; + + Ref lineIB = IndexBuffer::Create(lineIndices, s_Data.MaxLineIndices); + s_Data.LineVertexArray->SetIndexBuffer(lineIB); + delete[] lineIndices; + } + + void Renderer2D::Shutdown() + { + } + + void Renderer2D::BeginScene(const glm::mat4& viewProj, bool depthTest) + { + s_Data.CameraViewProj = viewProj; + s_Data.DepthTest = depthTest; + + s_Data.TextureShader->Bind(); + s_Data.TextureShader->SetMat4("u_ViewProjection", viewProj); + + s_Data.QuadIndexCount = 0; + s_Data.QuadVertexBufferPtr = s_Data.QuadVertexBufferBase; + + s_Data.LineIndexCount = 0; + s_Data.LineVertexBufferPtr = s_Data.LineVertexBufferBase; + + s_Data.TextureSlotIndex = 1; + } + + void Renderer2D::EndScene() + { + uint32_t dataSize = (uint8_t*)s_Data.QuadVertexBufferPtr - (uint8_t*)s_Data.QuadVertexBufferBase; + if (dataSize) + { + s_Data.QuadVertexBuffer->SetData(s_Data.QuadVertexBufferBase, dataSize); + + s_Data.TextureShader->Bind(); + s_Data.TextureShader->SetMat4("u_ViewProjection", s_Data.CameraViewProj); + + for (uint32_t i = 0; i < s_Data.TextureSlotIndex; i++) + s_Data.TextureSlots[i]->Bind(i); + + s_Data.QuadVertexArray->Bind(); + Renderer::DrawIndexed(s_Data.QuadIndexCount, PrimitiveType::Triangles, s_Data.DepthTest); + s_Data.Stats.DrawCalls++; + } + + dataSize = (uint8_t*)s_Data.LineVertexBufferPtr - (uint8_t*)s_Data.LineVertexBufferBase; + if (dataSize) + { + s_Data.LineVertexBuffer->SetData(s_Data.LineVertexBufferBase, dataSize); + + s_Data.LineShader->Bind(); + s_Data.LineShader->SetMat4("u_ViewProjection", s_Data.CameraViewProj); + + s_Data.LineVertexArray->Bind(); + Renderer::SetLineThickness(2.0f); + Renderer::DrawIndexed(s_Data.LineIndexCount, PrimitiveType::Lines, s_Data.DepthTest); + s_Data.Stats.DrawCalls++; + } + +#if OLD + Flush(); +#endif + } + + void Renderer2D::Flush() + { +#if OLD + // Bind textures + for (uint32_t i = 0; i < s_Data.TextureSlotIndex; i++) + s_Data.TextureSlots[i]->Bind(i); + + s_Data.QuadVertexArray->Bind(); + Renderer::DrawIndexed(s_Data.QuadIndexCount, false); + s_Data.Stats.DrawCalls++; +#endif + } + + void Renderer2D::DrawQuad(const glm::vec2& position, const glm::vec2& size, const glm::vec4& color) + { + DrawQuad({ position.x, position.y, 0.0f }, size, color); + } + + void Renderer2D::DrawQuad(const glm::vec3& position, const glm::vec2& size, const glm::vec4& color) + { + if (s_Data.QuadIndexCount >= Renderer2DData::MaxIndices) + FlushAndReset(); + + const float textureIndex = 0.0f; // White Texture + const float tilingFactor = 1.0f; + + glm::mat4 transform = glm::translate(glm::mat4(1.0f), position) + * glm::scale(glm::mat4(1.0f), { size.x, size.y, 1.0f }); + + for (uint32_t i = 0; i < 4; i++) + { + s_Data.QuadVertexBufferPtr->Position = transform * s_Data.QuadVertexPositions[i]; + s_Data.QuadVertexBufferPtr->Color = color; + s_Data.QuadVertexBufferPtr->TexCoord = defaultTexCoords[i]; + s_Data.QuadVertexBufferPtr->TexIndex = textureIndex; + s_Data.QuadVertexBufferPtr->TilingFactor = tilingFactor; + s_Data.QuadVertexBufferPtr++; + } + + s_Data.QuadIndexCount += 6; + + s_Data.Stats.QuadCount++; + } + + void Renderer2D::DrawQuad(const glm::vec2& position, const glm::vec2& size, const Ref& texture, float tilingFactor, const glm::vec4& tintColor) + { + DrawQuad({ position.x, position.y, 0.0f }, size, texture, tilingFactor, tintColor); + } + + void Renderer2D::DrawQuad(const glm::vec3& position, const glm::vec2& size, const Ref& texture, float tilingFactor, const glm::vec4& tintColor) + { + if (s_Data.QuadIndexCount >= Renderer2DData::MaxIndices) + FlushAndReset(); + + constexpr glm::vec4 color = { 1.0f, 1.0f, 1.0f, 1.0f }; + + float textureIndex = 0.0f; + for (uint32_t i = 1; i < s_Data.TextureSlotIndex; i++) + { + if (*s_Data.TextureSlots[i].get() == *texture.get()) + { + textureIndex = (float)i; + break; + } + } + + if (textureIndex == 0.0f) + { + textureIndex = (float)s_Data.TextureSlotIndex; + s_Data.TextureSlots[s_Data.TextureSlotIndex] = texture; + s_Data.TextureSlotIndex++; + } + + glm::mat4 transform = glm::translate(glm::mat4(1.0f), position) + * glm::scale(glm::mat4(1.0f), { size.x, size.y, 1.0f }); + for (uint32_t i = 0; i < 4; i++) + { + s_Data.QuadVertexBufferPtr->Position = transform * s_Data.QuadVertexPositions[i]; + s_Data.QuadVertexBufferPtr->Color = color; + s_Data.QuadVertexBufferPtr->TexCoord = defaultTexCoords[i]; + s_Data.QuadVertexBufferPtr->TexIndex = textureIndex; + s_Data.QuadVertexBufferPtr->TilingFactor = tilingFactor; + s_Data.QuadVertexBufferPtr++; + } + + s_Data.QuadIndexCount += 6; + + s_Data.Stats.QuadCount++; + } + + void Renderer2D::DrawRotatedQuad(const glm::vec2& position, const glm::vec2& size, float rotation, const glm::vec4& color) + { + DrawRotatedQuad({ position.x, position.y, 0.0f }, size, rotation, color); + } + + void Renderer2D::DrawRotatedQuad(const glm::vec3& position, const glm::vec2& size, float rotation, const glm::vec4& color) + { + if (s_Data.QuadIndexCount >= Renderer2DData::MaxIndices) + FlushAndReset(); + + const float textureIndex = 0.0f; // White Texture + const float tilingFactor = 1.0f; + + glm::mat4 transform = glm::translate(glm::mat4(1.0f), position) + * glm::rotate(glm::mat4(1.0f), glm::radians(rotation), { 0.0f, 0.0f, 1.0f }) + * glm::scale(glm::mat4(1.0f), { size.x, size.y, 1.0f }); + + for (uint32_t i = 1; i < 4; i++) + { + s_Data.QuadVertexBufferPtr->Position = transform * s_Data.QuadVertexPositions[i]; + s_Data.QuadVertexBufferPtr->Color = color; + s_Data.QuadVertexBufferPtr->TexCoord = defaultTexCoords[i]; + s_Data.QuadVertexBufferPtr->TexIndex = textureIndex; + s_Data.QuadVertexBufferPtr->TilingFactor = tilingFactor; + s_Data.QuadVertexBufferPtr++; + } + + s_Data.QuadIndexCount += 6; + + s_Data.Stats.QuadCount++; + } + + void Renderer2D::DrawRotatedQuad(const glm::vec2& position, const glm::vec2& size, float rotation, const Ref& texture, float tilingFactor, const glm::vec4& tintColor) + { + DrawRotatedQuad({ position.x, position.y, 0.0f }, size, rotation, texture, tilingFactor, tintColor); + } + + void Renderer2D::DrawRotatedQuad(const glm::vec3& position, const glm::vec2& size, float rotation, const Ref& texture, float tilingFactor, const glm::vec4& tintColor) + { + if (s_Data.QuadIndexCount >= Renderer2DData::MaxIndices) + FlushAndReset(); + + constexpr glm::vec4 color = { 1.0f, 1.0f, 1.0f, 1.0f }; + + float textureIndex = 0.0f; + for (uint32_t i = 1; i < s_Data.TextureSlotIndex; i++) + { + if (*s_Data.TextureSlots[i].get() == *texture.get()) + { + textureIndex = (float)i; + break; + } + } + + if (textureIndex == 0.0f) + { + textureIndex = (float)s_Data.TextureSlotIndex; + s_Data.TextureSlots[s_Data.TextureSlotIndex] = texture; + s_Data.TextureSlotIndex++; + } + + glm::mat4 transform = glm::translate(glm::mat4(1.0f), position) + * glm::rotate(glm::mat4(1.0f), glm::radians(rotation), { 0.0f, 0.0f, 1.0f }) + * glm::scale(glm::mat4(1.0f), { size.x, size.y, 1.0f }); + + for (uint32_t i = 1; i < 4; i++) + { + s_Data.QuadVertexBufferPtr->Position = transform * s_Data.QuadVertexPositions[i]; + s_Data.QuadVertexBufferPtr->Color = color; + s_Data.QuadVertexBufferPtr->TexCoord = defaultTexCoords[i]; + s_Data.QuadVertexBufferPtr->TexIndex = textureIndex; + s_Data.QuadVertexBufferPtr->TilingFactor = tilingFactor; + s_Data.QuadVertexBufferPtr++; + } + + s_Data.QuadIndexCount += 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) + FlushAndResetLines(); + + s_Data.LineVertexBufferPtr->Position = p0; + s_Data.LineVertexBufferPtr->Color = color; + s_Data.LineVertexBufferPtr++; + + s_Data.LineVertexBufferPtr->Position = p1; + s_Data.LineVertexBufferPtr->Color = color; + s_Data.LineVertexBufferPtr++; + + s_Data.LineIndexCount += 2; + + s_Data.Stats.LineCount++; + } + + void Renderer2D::ResetStats() + { + memset(&s_Data.Stats, 0, sizeof(Statistics)); + } + + Renderer2D::Statistics Renderer2D::GetStats() + { + return s_Data.Stats; + } + + void Renderer2D::FlushAndReset() + { + EndScene(); + + s_Data.QuadIndexCount = 0; + s_Data.QuadVertexBufferPtr = s_Data.QuadVertexBufferBase; + + s_Data.TextureSlotIndex = 1; + } + + void Renderer2D::FlushAndResetLines() + { + } +} diff --git a/Prism/src/Prism/Renderer/Renderer2D.h b/Prism/src/Prism/Renderer/Renderer2D.h new file mode 100644 index 0000000..6ca6892 --- /dev/null +++ b/Prism/src/Prism/Renderer/Renderer2D.h @@ -0,0 +1,57 @@ +// +// Created by sfd on 25-12-1. +// + +#ifndef RENDERER2D_H +#define RENDERER2D_H + +#include + +#include "Texture.h" + +namespace Prism +{ + class PRISM_API Renderer2D + { + public: + static void Init(); + static void Shutdown(); + + static void BeginScene(const glm::mat4& viewProj, bool depthTest = true); + static void EndScene(); + static void Flush(); + + // Primitives + static void DrawQuad(const glm::vec2& position, const glm::vec2& size, const glm::vec4& color); + static void DrawQuad(const glm::vec3& position, const glm::vec2& size, const glm::vec4& color); + static void DrawQuad(const glm::vec2& position, const glm::vec2& size, const Ref& texture, 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& texture, float tilingFactor = 1.0f, const glm::vec4& tintColor = glm::vec4(1.0f)); + + static void DrawRotatedQuad(const glm::vec2& position, const glm::vec2& size, float rotation, const glm::vec4& color); + static void DrawRotatedQuad(const glm::vec3& position, const glm::vec2& size, float rotation, const glm::vec4& color); + 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 DrawLine(const glm::vec3& p0, const glm::vec3& p1, const glm::vec4& color = glm::vec4(1.0f)); + // Stats + struct Statistics + { + uint32_t DrawCalls = 0; + uint32_t QuadCount = 0; + uint32_t LineCount = 0; + + uint32_t GetTotalVertexCount() { return QuadCount * 4 + LineCount * 2; } + uint32_t GetTotalIndexCount() { return QuadCount * 6 + LineCount * 2; } + }; + static void ResetStats(); + static Statistics GetStats(); + private: + static void FlushAndReset(); + static void FlushAndResetLines(); + }; + +} + + + +#endif //RENDERER2D_H diff --git a/Prism/src/Prism/Renderer/RendererAPI.h b/Prism/src/Prism/Renderer/RendererAPI.h index a6b4092..f962fb5 100644 --- a/Prism/src/Prism/Renderer/RendererAPI.h +++ b/Prism/src/Prism/Renderer/RendererAPI.h @@ -16,14 +16,21 @@ namespace Prism OpenGL }; + // TODO: move into separate header + enum class PrimitiveType + { + None = 0, Triangles, Lines + }; + struct RenderAPICapabilities { std::string Vendor; std::string Renderer; std::string Version; - int MaxSamples; - float MaxAnisotropy; + int MaxSamples = 0; + float MaxAnisotropy = 0.0f; + int MaxTextureUnits = 0; }; class RendererAPI @@ -35,7 +42,8 @@ namespace Prism static void Clear(float r, float g, float b, float a); static void SetClearColor(float r, float g, float b, float a); - static void DrawIndexed(unsigned int count, bool depthTest = true); + static void DrawIndexed(uint32_t count,PrimitiveType type, bool depthTest = true); + static void SetLineThickness(float thickness); static RendererAPIType Current() { return s_CurrentRendererAPI; } static RenderAPICapabilities& GetCapabilities() diff --git a/Prism/src/Prism/Renderer/SceneRenderer.cpp b/Prism/src/Prism/Renderer/SceneRenderer.cpp index 480362a..add52cf 100644 --- a/Prism/src/Prism/Renderer/SceneRenderer.cpp +++ b/Prism/src/Prism/Renderer/SceneRenderer.cpp @@ -9,6 +9,7 @@ #include "Material.h" #include "Mesh.h" #include "Renderer.h" +#include "Renderer2D.h" #include "RenderPass.h" #include "glad/glad.h" @@ -42,6 +43,8 @@ namespace Prism // Grid Ref GridMaterial; + + SceneRendererOptions Options; }; static SceneRendererData s_Data; @@ -52,6 +55,7 @@ namespace Prism geoFramebufferSpec.Width = 1280; geoFramebufferSpec.Height = 720; geoFramebufferSpec.Format = FramebufferFormat::RGBA16F; + geoFramebufferSpec.Samples = 8; geoFramebufferSpec.ClearColor = { 0.1f, 0.1f, 0.1f, 1.0f }; RenderPassSpecification geoRenderPassSpec; @@ -68,7 +72,8 @@ namespace Prism compRenderPassSpec.TargetFramebuffer = FrameBuffer::Create(compFramebufferSpec); s_Data.CompositePass = RenderPass::Create(compRenderPassSpec); - s_Data.CompositeShader = Shader::Create("assets/shaders/hdr.glsl"); + s_Data.CompositeShader = Shader::Create("assets/shaders/SceneComposite.glsl"); + // s_Data.CompositeShader = Shader::Create("assets/shaders/hdr.glsl"); s_Data.BRDFLUT = Texture2D::Create("assets/textures/BRDF_LUT.tga"); @@ -178,11 +183,17 @@ namespace Prism { glBindImageTexture(0, irradianceMap->GetRendererID(), 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_RGBA16F); glDispatchCompute(irradianceMap->GetWidth() / 32, irradianceMap->GetHeight() / 32, 6); + glGenerateTextureMipmap(irradianceMap->GetRendererID()); }); return { envFiltered, irradianceMap }; } + Ref SceneRenderer::GetFinalRenderPass() + { + return s_Data.CompositePass; + } + Ref SceneRenderer::GetFinalColorBuffer() { PM_CORE_ASSERT(false, "Not implemented"); @@ -194,6 +205,11 @@ namespace Prism return s_Data.CompositePass->GetSpecification().TargetFramebuffer->GetColorAttachmentRendererID(); } + SceneRendererOptions& SceneRenderer::GetOptions() + { + return s_Data.Options; + } + void SceneRenderer::FlushDrawList() { PM_CORE_ASSERT(!s_Data.ActiveScene); @@ -209,7 +225,7 @@ namespace Prism { Renderer::BeginRenderPass(s_Data.GeoPass); - auto viewProjection = s_Data.SceneData.SceneCamera.GetProjectionMatrix() * s_Data.SceneData.SceneCamera.GetViewMatrix(); + const auto viewProjection = s_Data.SceneData.SceneCamera.GetViewProjection(); // Skybox auto skyboxShader = s_Data.SceneData.SkyboxMaterial->GetShader(); @@ -234,8 +250,20 @@ namespace Prism } // Grid - s_Data.GridMaterial->Set("u_ViewProjection", viewProjection); - Renderer::SubmitQuad(s_Data.GridMaterial, glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f)) * glm::scale(glm::mat4(1.0f), glm::vec3(16.0f))); + const auto option = GetOptions(); + if (option.ShowGrid) + { + s_Data.GridMaterial->Set("u_ViewProjection", viewProjection); + Renderer::SubmitQuad(s_Data.GridMaterial, glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f)) * glm::scale(glm::mat4(1.0f), glm::vec3(16.0f))); + } + + if (option.ShowBoundingBoxes) + { + Renderer2D::BeginScene(viewProjection); + for (auto& dc : s_Data.DrawList) + Renderer::DrawAABB(dc.mesh); + Renderer2D::EndScene(); + } Renderer::EndRenderPass(); } @@ -245,6 +273,7 @@ namespace Prism Renderer::BeginRenderPass(s_Data.CompositePass); s_Data.CompositeShader->Bind(); s_Data.CompositeShader->SetFloat("u_Exposure", s_Data.SceneData.SceneCamera.GetExposure()); + s_Data.CompositeShader->SetInt("u_TextureSamples", s_Data.GeoPass->GetSpecification().TargetFramebuffer->GetSpecification().Samples); s_Data.GeoPass->GetSpecification().TargetFramebuffer->BindTexture(); Renderer::SubmitFullscreenQuad(nullptr); Renderer::EndRenderPass(); diff --git a/Prism/src/Prism/Renderer/SceneRenderer.h b/Prism/src/Prism/Renderer/SceneRenderer.h index 861d546..224c2af 100644 --- a/Prism/src/Prism/Renderer/SceneRenderer.h +++ b/Prism/src/Prism/Renderer/SceneRenderer.h @@ -4,12 +4,19 @@ #ifndef SCENERENDERER_H #define SCENERENDERER_H +#include "RenderPass.h" #include "Texture.h" #include "Prism/Scene/Scene.h" namespace Prism { + struct SceneRendererOptions + { + bool ShowGrid = true; + bool ShowBoundingBoxes = false; + }; + class PRISM_API SceneRenderer { public: @@ -24,11 +31,14 @@ namespace Prism static std::pair, Ref> CreateEnvironmentMap(const std::string& filepath); + static Ref GetFinalRenderPass(); static Ref GetFinalColorBuffer(); // TODO: Temp static uint32_t GetFinalColorBufferRendererID(); + static SceneRendererOptions& GetOptions(); + private: static void FlushDrawList(); static void GeometryPass(); diff --git a/Prism/src/Prism/Renderer/Shader.h b/Prism/src/Prism/Renderer/Shader.h index f0620d8..9faa8f6 100644 --- a/Prism/src/Prism/Renderer/Shader.h +++ b/Prism/src/Prism/Renderer/Shader.h @@ -110,9 +110,12 @@ namespace Prism virtual void UploadUniformBuffer(const UniformBufferBase& uniformBuffer) = 0; virtual void SetFloat(const std::string& name, float value) = 0; + virtual void SetInt(const std::string& name, int value) = 0; virtual void SetMat4(const std::string& name, const glm::mat4& value) = 0; virtual void SetMat4FromRenderThread(const std::string& name, const glm::mat4& value, bool bind = true) = 0; + virtual void SetIntArray(const std::string& name, int* values, uint32_t size) = 0; + virtual const std::string& GetName() const = 0; virtual void SetVSMaterialUniformBuffer(Buffer buffer) = 0; diff --git a/Prism/src/Prism/Renderer/Texture.h b/Prism/src/Prism/Renderer/Texture.h index 4d893e5..e618d9f 100644 --- a/Prism/src/Prism/Renderer/Texture.h +++ b/Prism/src/Prism/Renderer/Texture.h @@ -43,6 +43,8 @@ namespace Prism static uint32_t GetBPP(TextureFormat format); static uint32_t CalculateMipMapCount(uint32_t width, uint32_t height); + + virtual bool operator==(const Texture& other) const = 0; }; class PRISM_API Texture2D : public Texture diff --git a/Prism/src/Prism/Renderer/VertexArray.h b/Prism/src/Prism/Renderer/VertexArray.h index 3ba357d..a092d8c 100644 --- a/Prism/src/Prism/Renderer/VertexArray.h +++ b/Prism/src/Prism/Renderer/VertexArray.h @@ -25,6 +25,7 @@ namespace Prism virtual const std::vector>& GetVertexBuffers() const = 0; virtual const Ref& GetIndexBuffer() const = 0; + virtual RendererID GetRendererID() const = 0; }; } diff --git a/Prism/src/Prism/Scene/Entity.cpp b/Prism/src/Prism/Scene/Entity.cpp index 976c50f..3337188 100644 --- a/Prism/src/Prism/Scene/Entity.cpp +++ b/Prism/src/Prism/Scene/Entity.cpp @@ -6,12 +6,12 @@ namespace Prism { - Entity::Entity() - : m_Transform(glm::mat4(1.0f)) - { - } - Entity::~Entity() { } + + Entity::Entity(const std::string& name) + : m_Name(name), m_Transform(glm::mat4(1.0f)) + { + } } diff --git a/Prism/src/Prism/Scene/Entity.h b/Prism/src/Prism/Scene/Entity.h index a357cb6..43fe888 100644 --- a/Prism/src/Prism/Scene/Entity.h +++ b/Prism/src/Prism/Scene/Entity.h @@ -13,7 +13,6 @@ namespace Prism class PRISM_API Entity { public: - Entity(); ~Entity(); // TODO: Move to Component @@ -25,12 +24,21 @@ namespace Prism const glm::mat4& GetTransform() const { return m_Transform; } glm::mat4& Transform() { return m_Transform; } + + + const std::string& GetName() const { return m_Name; } private: + Entity(const std::string& name); + private: + std::string m_Name; glm::mat4 m_Transform; // TODO: Temp Ref m_Mesh; Ref m_Material; + + private: + friend class Scene; }; } diff --git a/Prism/src/Prism/Scene/Scene.cpp b/Prism/src/Prism/Scene/Scene.cpp index bc020aa..886a423 100644 --- a/Prism/src/Prism/Scene/Scene.cpp +++ b/Prism/src/Prism/Scene/Scene.cpp @@ -35,8 +35,6 @@ namespace Prism void Scene::OnUpdate(TimeStep ts) { - m_Camera.Update(ts); - m_SkyboxMaterial->Set("u_TextureLod", m_SkyboxLod); // Update all entities @@ -59,6 +57,11 @@ namespace Prism SceneRenderer::EndScene(); } + void Scene::OnEvent(Event& e) + { + m_Camera.OnEvent(e); + } + void Scene::SetCamera(const Camera& camera) { m_Camera = camera; @@ -81,9 +84,12 @@ namespace Prism m_Entities.push_back(entity); } - Entity* Scene::CreateEntity() + static const std::string DefaultEntityName = "Entity"; + + Entity* Scene::CreateEntity(const std::string& name) { - const auto entity = new Entity(); + const std::string& entityName = name.empty() ? DefaultEntityName : name; + const auto entity = new Entity(entityName); AddEntity(entity); return entity; } diff --git a/Prism/src/Prism/Scene/Scene.h b/Prism/src/Prism/Scene/Scene.h index bfe747b..50a1827 100644 --- a/Prism/src/Prism/Scene/Scene.h +++ b/Prism/src/Prism/Scene/Scene.h @@ -5,6 +5,7 @@ #ifndef SCENE_H #define SCENE_H #include "Entity.h" +#include "Prism/Core/Events/Event.h" #include "Prism/Renderer/Camera.h" #include "Prism/Renderer/Material.h" @@ -28,6 +29,7 @@ namespace Prism void Init(); void OnUpdate(TimeStep ts); + void OnEvent(Event& e); void SetCamera(const Camera& camera); Camera& GetCamera() { return m_Camera; } @@ -38,7 +40,7 @@ namespace Prism float& GetSkyboxLod() { return m_SkyboxLod; } void AddEntity(Entity* entity); - Entity* CreateEntity(); + Entity* CreateEntity(const std::string& name = ""); private: std::string m_DebugName; diff --git a/Sandbox/Sandbox/Layer/TestLayer.cpp b/Sandbox/Sandbox/Layer/TestLayer.cpp index 260b65f..0c74545 100644 --- a/Sandbox/Sandbox/Layer/TestLayer.cpp +++ b/Sandbox/Sandbox/Layer/TestLayer.cpp @@ -142,68 +142,24 @@ static void EnableDockSpace(const bool enable) TestLayer::TestLayer() - :m_Camera(glm::perspectiveFov(glm::radians(45.0f), 1280.0f, 720.0f, 0.1f, 1000.0f)) { } void TestLayer::OnAttach() { - Prism::FramebufferSpecification geoFramebufferspec; - geoFramebufferspec.Width = 1280; - geoFramebufferspec.Height = 720; - geoFramebufferspec.Format = Prism::FramebufferFormat::RGBA16F; - geoFramebufferspec.ClearColor = {0.1f, 0.1f, 0.1f, 1.0f}; + auto environment = Prism::Environment::Load("assets/env/birchwood_4k.hdr"); + { + m_Scene = Prism::CreateRef("test Scene"); + m_Scene->SetCamera(Prism::Camera(glm::perspectiveFov(glm::radians(45.0f), 1280.0f, 720.0f, 0.1f, 10000.0f))); + m_Scene->SetEnvironment(environment); - Prism::RenderPassSpecification geoRenderPass; - geoRenderPass.TargetFramebuffer = Prism::FrameBuffer::Create(geoFramebufferspec); - m_GeoPass = Prism::RenderPass::Create(geoRenderPass); + m_MeshEntity = m_Scene->CreateEntity("test Entity"); - Prism::FramebufferSpecification finalFramebufferspec; - finalFramebufferspec.Width = 1280; - finalFramebufferspec.Height = 720; - finalFramebufferspec.Format = Prism::FramebufferFormat::RGBA8; - finalFramebufferspec.ClearColor = {0.1f, 0.1f, 0.1f, 1.0f}; + m_MeshEntity->SetMesh(Prism::CreateRef("assets/meshes/TestScene.fbx")); + m_MeshMaterial = m_MeshEntity->GetMesh()->GetMaterial(); - Prism::RenderPassSpecification finalRenderPass; - finalRenderPass.TargetFramebuffer = Prism::FrameBuffer::Create(finalFramebufferspec); - m_FinalPass = Prism::RenderPass::Create(finalRenderPass); + } - - static float QuadVertex[] = { - -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, - 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, - -1.0f, 1.0f, 0.0f, 0.0f, 1.0f - }; - - static uint32_t QuadIndices[] = { - 0, 1, 2, 2, 3, 0 - }; - - m_VertexArray = Prism::VertexArray::Create(); - auto quadVB = Prism::VertexBuffer::Create(QuadVertex, sizeof(QuadVertex) * sizeof(float)); - quadVB->SetLayout({ - { Prism::ShaderDataType::Float3, "a_Position" }, - { Prism::ShaderDataType::Float2, "a_TexCoord" } - }); - m_VertexArray->AddVertexBuffer(quadVB); - - auto ib = Prism::IndexBuffer::Create(QuadIndices, 6 * sizeof(uint32_t)); - m_VertexArray->SetIndexBuffer(ib); - - m_SkyBoxTextureCube.reset(Prism::TextureCube::Create("assets/textures/environments/Arches_E_PineTree_Radiance.tga")); - m_EnvironmentIrradiance.reset(Prism::TextureCube::Create("assets/textures/environments/Arches_E_PineTree_Irradiance.tga")); - - m_SkyBoxShader = Prism::Shader::Create("assets/shaders/quad.glsl"); - m_HDRShader = Prism::Shader::Create("assets/shaders/hdr.glsl"); - - m_Mesh = std::make_unique("assets/models/m1911/m1911.fbx"); - m_MeshMaterial = Prism::CreateRef(m_Mesh->GetMaterial()); - - m_BRDFLUT.reset(Prism::Texture2D::Create("assets/textures/BRDF_LUT.tga")); - - m_Light.Direction = {-0.5f, -0.5f, 1.0f}; - m_Light.Radiance = {1.0f, 1.0f, 1.0f}; } void TestLayer::OnDetach() @@ -213,78 +169,48 @@ void TestLayer::OnDetach() void TestLayer::OnUpdate(Prism::TimeStep deltaTime) { - m_Camera.Update(deltaTime); - auto viewProjection = m_Camera.GetProjectionMatrix() * m_Camera.GetViewMatrix(); - - Prism::Renderer::BeginRenderPass(m_GeoPass); - Prism::Renderer::Clear(m_clearColor[0], m_clearColor[1], m_clearColor[2], m_clearColor[3]); - - // SkyBox - m_SkyBoxShader->Bind(); - m_SkyBoxShader->SetMat4("u_InverseVP", inverse(viewProjection)); - m_SkyBoxTextureCube->Bind(0); - m_VertexArray->Bind(); - Prism::Renderer::DrawIndexed(m_VertexArray->GetIndexBuffer()->GetCount(), false); - - m_MeshMaterial->Set("u_AlbedoColor", m_AlbedoInput.Color); m_MeshMaterial->Set("u_Metalness", m_MetalnessInput.Value); m_MeshMaterial->Set("u_Roughness", m_RoughnessInput.Value); - m_MeshMaterial->Set("u_ViewProjectionMatrix", viewProjection); - m_MeshMaterial->Set("u_ModelMatrix", glm::scale(glm::mat4(1.0f), glm::vec3(m_MeshScale))); m_MeshMaterial->Set("lights", m_Light); - m_MeshMaterial->Set("u_CameraPosition", m_Camera.GetPosition()); - m_MeshMaterial->Set("u_RadiancePrefilter", m_RadiancePrefilter ? 1.0f : 0.0f); m_MeshMaterial->Set("u_AlbedoTexToggle", m_AlbedoInput.UseTexture ? 1.0f : 0.0f); m_MeshMaterial->Set("u_NormalTexToggle", m_NormalInput.UseTexture ? 1.0f : 0.0f); m_MeshMaterial->Set("u_MetalnessTexToggle", m_MetalnessInput.UseTexture ? 1.0f : 0.0f); m_MeshMaterial->Set("u_RoughnessTexToggle", m_RoughnessInput.UseTexture ? 1.0f : 0.0f); m_MeshMaterial->Set("u_EnvMapRotation", m_EnvMapRotation); - m_MeshMaterial->Set("u_EnvRadianceTex", m_SkyBoxTextureCube); - m_MeshMaterial->Set("u_EnvIrradianceTex", m_EnvironmentIrradiance); - m_MeshMaterial->Set("u_BRDFLUTTexture", m_BRDFLUT); - m_Mesh->Render(deltaTime, glm::mat4(1.0f), m_MeshMaterial); + if (m_AllowViewportCameraEvents) + m_Scene->GetCamera().OnUpdate(deltaTime); - Prism::Renderer::EndRenderPass(); - - - // HDR - Prism::Renderer::BeginRenderPass(m_FinalPass); - m_HDRShader->Bind(); - m_HDRShader->SetFloat("u_Exposure", m_Exposure); - m_GeoPass->GetSpecification().TargetFramebuffer->BindTexture(); - m_VertexArray->Bind(); - Prism::Renderer::DrawIndexed(m_VertexArray->GetIndexBuffer()->GetCount(), false); - Prism::Renderer::EndRenderPass(); + m_Scene->OnUpdate(deltaTime); } void TestLayer::OnImGuiRender() { EnableDockSpace(true); - ImGui::Begin("Settings"); - ImGui::ColorEdit4("ClearColor", glm::value_ptr(m_clearColor)); - ImGui::ColorEdit4("TriangleClearColor", glm::value_ptr(m_TriangleColor)); - ImGui::DragFloat("Exposure", &m_Exposure, 0.01f, 0.0f); - const auto& position = m_Camera.GetPosition(); - ImGui::Text("Camera: (%.2f, %.2f, %.2f)", position.x, position.y, position.z); - - - ImGui::End(); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); ImGui::Begin("Viewport"); auto viewportSize = ImGui::GetContentRegionAvail(); - m_GeoPass->GetSpecification().TargetFramebuffer->Resize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y); - m_FinalPass->GetSpecification().TargetFramebuffer->Resize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y); - m_Camera.SetProjectionMatrix(glm::perspectiveFov(glm::radians(45.0f), viewportSize.x, viewportSize.y, 0.1f, 10000.0f)); - ImGui::Image((ImTextureRef)m_FinalPass->GetSpecification().TargetFramebuffer->GetColorAttachmentRendererID(), viewportSize, {0, 1}, {1, 0}); + Prism::SceneRenderer::SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y); + m_Scene->GetCamera().SetProjectionMatrix(glm::perspectiveFov(glm::radians(45.0f), viewportSize.x, viewportSize.y, 0.1f, 10000.0f)); + m_Scene->GetCamera().SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y); + ImGui::Image((ImTextureRef)Prism::SceneRenderer::GetFinalColorBufferRendererID(), viewportSize, { 0, 1 }, { 1, 0 }); + + + auto windowSize = ImGui::GetWindowSize(); + ImVec2 minBound = ImGui::GetWindowPos(); + ImVec2 maxBound = { minBound.x + windowSize.x, minBound.y + windowSize.y }; + m_AllowViewportCameraEvents = ImGui::IsMouseHoveringRect(minBound, maxBound); + ImGui::End(); ImGui::PopStyleVar(); } void TestLayer::OnEvent(Prism::Event& e) { + if (m_AllowViewportCameraEvents) + m_Scene->GetCamera().OnEvent(e); } diff --git a/Sandbox/Sandbox/Layer/TestLayer.h b/Sandbox/Sandbox/Layer/TestLayer.h index 63c16b8..4c961c0 100644 --- a/Sandbox/Sandbox/Layer/TestLayer.h +++ b/Sandbox/Sandbox/Layer/TestLayer.h @@ -13,6 +13,7 @@ #include "Prism/Renderer/RenderPass.h" #include "Prism/Renderer/Shader.h" #include "Prism/Renderer/Texture.h" +#include "Prism/Scene/Scene.h" class TestLayer : public Prism::Layer @@ -29,16 +30,11 @@ private: glm::vec4 m_clearColor = glm::vec4(0.1f, 0.1f, 0.1f, 1.0f); glm::vec4 m_TriangleColor = glm::vec4(1.0f); - Prism::Ref m_GeoPass, m_FinalPass; + Prism::Ref m_Scene; + Prism::Entity* m_MeshEntity; + Prism::Ref m_MeshMaterial; - Prism::Ref m_VertexArray; - Prism::Ref m_SkyBoxTextureCube, m_EnvironmentIrradiance; - Prism::Ref m_HDRShader, m_SkyBoxShader; - Prism::Ref m_Mesh; - Prism::Ref m_MeshMaterial; - Prism::Ref m_BRDFLUT; - - Prism::Camera m_Camera; + bool m_AllowViewportCameraEvents = false; float m_Exposure = 1.0f;