diff --git a/Editor/Editor/EditorLayer.cpp b/Editor/Editor/EditorLayer.cpp index a3d5b50..60f4504 100644 --- a/Editor/Editor/EditorLayer.cpp +++ b/Editor/Editor/EditorLayer.cpp @@ -149,7 +149,7 @@ namespace Prism 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"); + mesh = CreateRef("assets/models/m1911/m1911Materials.fbx"); secondEntity->SetMesh(mesh); } @@ -208,9 +208,12 @@ namespace Prism // Editor m_CheckerboardTex = Texture2D::Create("assets/editor/Checkerboard.tga"); - // lights - m_Light.Direction = {-0.5f, -0.5f, 1.0f}; - m_Light.Radiance = {1.0f, 1.0f, 1.0f}; + // set lights + auto& light = m_Scene->GetLight(); + light.Direction = { -0.5f, -0.5f, 1.0f }; + light.Radiance = { 1.0f, 1.0f, 1.0f }; + + m_CurrentlySelectedTransform = &m_MeshEntity->Transform(); } void EditorLayer::OnDetach() @@ -228,7 +231,6 @@ namespace Prism 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); @@ -236,7 +238,8 @@ namespace Prism m_MeshMaterial->Set("u_EnvMapRotation", m_EnvMapRotation); m_SphereBaseMaterial->Set("u_AlbedoColor", m_AlbedoInput.Color); - m_SphereBaseMaterial->Set("lights", m_Light); + // m_SphereBaseMaterial->Set("lights", m_Light); + m_SphereBaseMaterial->Set("lights", m_Scene->GetLight()); 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); @@ -264,8 +267,19 @@ namespace Prism 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()); + Renderer::DrawAABB(m_MeshEntity->GetMesh(), m_MeshEntity->Transform()); + + Renderer2D::EndScene(); + Renderer::EndRenderPass(); + } + + if (!m_SelectedSubmeshes.empty()) + { + Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false); + const auto viewProj = m_Scene->GetCamera().GetViewProjection(); + Renderer2D::BeginScene(viewProj, false); + const auto& submesh = m_SelectedSubmeshes[0]; + Renderer::DrawAABB(submesh.Mesh->BoundingBox, m_MeshEntity->GetTransform() * submesh.Mesh->Transform); Renderer2D::EndScene(); Renderer::EndRenderPass(); } @@ -441,9 +455,10 @@ namespace Prism ImGui::Columns(2); ImGui::AlignTextToFramePadding(); - Property("Light Direction", m_Light.Direction); - Property("Light Radiance", m_Light.Radiance, PropertyFlag::ColorProperty); - Property("Light Multiplier", m_LightMultiplier, 0.0f, 5.0f); + auto& light = m_Scene->GetLight(); + Property("Light Direction", light.Direction); + Property("Light Radiance", light.Radiance, PropertyFlag::ColorProperty); + Property("Light Multiplier", light.Multiplier, 0.0f, 5.0f); Property("Exposure", m_ActiveScene->GetCamera().GetExposure(), 0.0f, 5.0f); Property("Radiance Prefiltering", m_RadiancePrefilter); @@ -642,6 +657,8 @@ namespace Prism ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); ImGui::Begin("Viewport"); + + auto viewportOffset = ImGui::GetCursorPos(); // includes tab bar 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)); @@ -649,13 +666,19 @@ namespace Prism ImGui::Image((ImTextureRef)SceneRenderer::GetFinalColorBufferRendererID(), viewportSize, { 0, 1 }, { 1, 0 }); + static int counter = 0; auto windowSize = ImGui::GetWindowSize(); ImVec2 minBound = ImGui::GetWindowPos(); + minBound.x += viewportOffset.x; + minBound.y += viewportOffset.y; + ImVec2 maxBound = { minBound.x + windowSize.x, minBound.y + windowSize.y }; + m_ViewportBounds[0] = { minBound.x, minBound.y }; + m_ViewportBounds[1] = { maxBound.x, maxBound.y }; m_AllowViewportCameraEvents = ImGui::IsMouseHoveringRect(minBound, maxBound); // ImGuizmo - if (m_GizmoType != -1) + if (m_GizmoType != -1 && m_CurrentlySelectedTransform) { const auto rw = (float)ImGui::GetWindowWidth(); const auto rh = (float)ImGui::GetWindowHeight(); @@ -663,7 +686,15 @@ namespace Prism ImGuizmo::SetDrawlist(); ImGuizmo::SetRect(ImGui::GetWindowPos().x, ImGui::GetWindowPos().y, rw, rh); const auto& camera = m_ActiveScene->GetCamera(); - ImGuizmo::Manipulate(glm::value_ptr(camera.GetViewMatrix()), glm::value_ptr(camera.GetProjectionMatrix()), (ImGuizmo::OPERATION)m_GizmoType, ImGuizmo::LOCAL, glm::value_ptr(m_MeshEntity->Transform())); + + bool snap = Input::IsKeyPressed(PM_KEY_LEFT_CONTROL); + ImGuizmo::Manipulate(glm::value_ptr(camera.GetViewMatrix()), + glm::value_ptr(camera.GetProjectionMatrix()), + (ImGuizmo::OPERATION)m_GizmoType, + ImGuizmo::LOCAL, + glm::value_ptr(m_MeshEntity->Transform()), + nullptr, + snap ? &m_SnapValue : nullptr); } ImGui::End(); @@ -678,6 +709,7 @@ namespace Prism EventDispatcher dispatcher(e); dispatcher.Dispatch(PM_BIND_EVENT_FN(EditorLayer::OnKeyPressedEvent)); + dispatcher.Dispatch(PM_BIND_EVENT_FN(EditorLayer::OnMouseButtonPressedEvent)); } bool EditorLayer::OnKeyPressedEvent(KeyPressedEvent& e) @@ -714,9 +746,85 @@ namespace Prism return false; } + bool EditorLayer::OnMouseButtonPressedEvent(MouseButtonPressedEvent& e) + { + auto [mx, my] = Input::GetMousePosition(); + if (e.GetMouseButton() == PM_MOUSE_BUTTON_LEFT && !Input::IsKeyPressed(PM_KEY_LEFT_ALT) && !ImGuizmo::IsOver()) + { + auto [mouseX, mouseY] = GetMouseViewportSpace(); + if (mouseX > -1.0f && mouseX < 1.0f && mouseY > -1.0f && mouseY < 1.0f) + { + auto [origin, direction] = CastRay(mouseX, mouseY); + + m_SelectedSubmeshes.clear(); + const auto mesh = m_MeshEntity->GetMesh(); + auto& submeshes = mesh->GetSubmeshes(); + float lastT = std::numeric_limits::max(); + for (uint32_t i = 0; i < submeshes.size(); i++) + { + auto& submesh = submeshes[i]; + Ray ray = { + glm::inverse(m_MeshEntity->GetTransform() * submesh.Transform) * glm::vec4(origin, 1.0f), + glm::inverse(glm::mat3(m_MeshEntity->GetTransform()) * glm::mat3(submesh.Transform)) * direction + }; + + float t; + bool intersects = ray.IntersectsAABB(submesh.BoundingBox, t); + if (intersects) + { + const auto& triangleCache = mesh->GetTriangleCache(i); + for (const auto& triangle : triangleCache) + { + if (ray.IntersectsTriangle(triangle.V0.Position, triangle.V1.Position, triangle.V2.Position, t)) + { + PM_CLIENT_WARN("INTERSECTION: {0}, t={1}", submesh.NodeName, t); + m_SelectedSubmeshes.push_back({ &submesh, t }); + break; + } + } + } + } + std::sort(m_SelectedSubmeshes.begin(), m_SelectedSubmeshes.end(), [](auto& a, auto& b) { return a.Distance < b.Distance; }); + + // TODO: Handle mesh being deleted, etc. + if (!m_SelectedSubmeshes.empty()) + m_CurrentlySelectedTransform = &m_SelectedSubmeshes[0].Mesh->Transform; + else + m_CurrentlySelectedTransform = &m_MeshEntity->Transform(); + + } + } + return false; + } + void EditorLayer::ShowBoundingBoxes(bool show, bool onTop) { SceneRenderer::GetOptions().ShowBoundingBoxes = show && !onTop; m_DrawOnTopBoundingBoxes = show && onTop; } + + std::pair EditorLayer::GetMouseViewportSpace() const + { + auto [mx, my] = ImGui::GetMousePos(); // Input::GetMousePosition(); + mx -= m_ViewportBounds[0].x; + my -= m_ViewportBounds[0].y; + const auto viewportWidth = m_ViewportBounds[1].x - m_ViewportBounds[0].x; + const auto viewportHeight = m_ViewportBounds[1].y - m_ViewportBounds[0].y; + + return { (mx / viewportWidth) * 2.0f - 1.0f, ((my / viewportHeight) * 2.0f - 1.0f) * -1.0f }; + } + + std::pair EditorLayer::CastRay(const float mx, const float my) const + { + glm::vec4 mouseClipPos = { mx, my, -1.0f, 1.0f }; + + const auto inverseProj = glm::inverse(m_Scene->GetCamera().GetProjectionMatrix()); + const auto inverseView = glm::inverse(glm::mat3(m_Scene->GetCamera().GetViewMatrix())); + + const glm::vec4 ray = inverseProj * mouseClipPos; + glm::vec3 rayPos = m_Scene->GetCamera().GetPosition(); + glm::vec3 rayDir = inverseView * glm::vec3(ray); + + return { rayPos, rayDir }; + } } diff --git a/Editor/Editor/EditorLayer.h b/Editor/Editor/EditorLayer.h index 4bd7b26..82a5a72 100644 --- a/Editor/Editor/EditorLayer.h +++ b/Editor/Editor/EditorLayer.h @@ -24,9 +24,14 @@ namespace Prism private: bool OnKeyPressedEvent(KeyPressedEvent& e); + bool OnMouseButtonPressedEvent(MouseButtonPressedEvent& e); void ShowBoundingBoxes(bool show, bool onTop = false); + private: + std::pair GetMouseViewportSpace() const; + std::pair CastRay(float mx, float my) const; + private: Scope m_SceneHierarchyPanel; @@ -36,25 +41,27 @@ namespace Prism Entity* m_MeshEntity = nullptr; - Ref m_BrushShader; Ref m_PlaneMesh; Ref m_SphereBaseMaterial; Ref m_MeshMaterial; - Ref m_GeoPass, m_CompositePass; - - Ref m_GridMaterial; - std::vector> m_MetalSphereMaterialInstances; std::vector> m_DielectricSphereMaterialInstances; - float m_GridScale = 16.025f, m_GridSize = 0.025f; - float m_MeshScale = 1.0f; - // Imguizmo + glm::vec2 m_ViewportBounds[2]; int m_GizmoType = -1; // -1 = no gizmo + float m_SnapValue = 0.5f; + + struct SelectedSubmesh + { + Submesh* Mesh; + float Distance; + }; + std::vector m_SelectedSubmeshes; + glm::mat4* m_CurrentlySelectedTransform = nullptr; // configure button bool m_AllowViewportCameraEvents = false; @@ -97,14 +104,6 @@ namespace Prism RoughnessInput m_RoughnessInput; - struct Light - { - glm::vec3 Direction; - glm::vec3 Radiance; - }; - Light m_Light; - float m_LightMultiplier = 0.3f; - // PBR params bool m_RadiancePrefilter = false; diff --git a/Editor/assets/env/pink_sunrise_4k.hdr b/Editor/assets/env/pink_sunrise_4k.hdr new file mode 100644 index 0000000..f95283a Binary files /dev/null and b/Editor/assets/env/pink_sunrise_4k.hdr differ diff --git a/Editor/assets/env/rooitou_park_4k.hdr b/Editor/assets/env/rooitou_park_4k.hdr new file mode 100644 index 0000000..a2aeae5 Binary files /dev/null and b/Editor/assets/env/rooitou_park_4k.hdr differ diff --git a/Editor/assets/env/venice_dawn_1_4k.hdr b/Editor/assets/env/venice_dawn_1_4k.hdr new file mode 100644 index 0000000..d852cb1 Binary files /dev/null and b/Editor/assets/env/venice_dawn_1_4k.hdr differ diff --git a/Editor/assets/meshes/TestScene.blend b/Editor/assets/meshes/TestScene.blend new file mode 100644 index 0000000..bf09bc8 Binary files /dev/null and b/Editor/assets/meshes/TestScene.blend differ diff --git a/Editor/assets/meshes/TestScene.fbx b/Editor/assets/meshes/TestScene.fbx index e6808db..faa367a 100644 Binary files a/Editor/assets/meshes/TestScene.fbx and b/Editor/assets/meshes/TestScene.fbx differ diff --git a/Editor/assets/models/m1911/M1911.blend b/Editor/assets/models/m1911/M1911.blend index c800949..435c960 100644 Binary files a/Editor/assets/models/m1911/M1911.blend and b/Editor/assets/models/m1911/M1911.blend differ diff --git a/Editor/assets/models/m1911/M1911Materials.fbx b/Editor/assets/models/m1911/M1911Materials.fbx index 2c23887..c23e7d6 100644 Binary files a/Editor/assets/models/m1911/M1911Materials.fbx and b/Editor/assets/models/m1911/M1911Materials.fbx differ diff --git a/Editor/assets/shaders/PBRShader_Anim.glsl b/Editor/assets/shaders/PBRShader_Anim.glsl index 2cbcf39..a195cec 100644 --- a/Editor/assets/shaders/PBRShader_Anim.glsl +++ b/Editor/assets/shaders/PBRShader_Anim.glsl @@ -46,7 +46,7 @@ void main() vec4 localPosition = boneTransform * vec4(a_Position, 1.0); vs_Output.WorldPosition = vec3(u_Transform * boneTransform * vec4(a_Position, 1.0)); - vs_Output.Normal = mat3(boneTransform) * a_Normal; + vs_Output.Normal = mat3(u_Transform) * mat3(boneTransform) * 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.Binormal = mat3(boneTransform) * a_Binormal; @@ -68,6 +68,7 @@ const vec3 Fdielectric = vec3(0.04); struct Light { vec3 Direction; vec3 Radiance; + float Multiplier; }; in VertexOutput @@ -256,7 +257,7 @@ vec3 Lighting(vec3 F0) for(int i = 0; i < LightCount; i++) { vec3 Li = -lights.Direction; - vec3 Lradiance = lights.Radiance; + vec3 Lradiance = lights.Radiance * lights.Multiplier; vec3 Lh = normalize(Li + m_Params.View); // Calculate angles between surface normal and various light vectors. @@ -288,7 +289,7 @@ vec3 IBL(vec3 F0, vec3 Lr) int u_EnvRadianceTexLevels = textureQueryLevels(u_EnvRadianceTex); float NoV = clamp(m_Params.NdotV, 0.0, 1.0); vec3 R = 2.0 * dot(m_Params.View, m_Params.Normal) * m_Params.Normal - m_Params.View; - vec3 specularIrradiance = textureLod(u_EnvRadianceTex, RotateVectorAboutY(u_EnvMapRotation, Lr), (m_Params.Roughness * m_Params.Roughness) * u_EnvRadianceTexLevels).rgb; + vec3 specularIrradiance = textureLod(u_EnvRadianceTex, RotateVectorAboutY(u_EnvMapRotation, Lr), (m_Params.Roughness) * u_EnvRadianceTexLevels).rgb; // Sample BRDF Lut, 1.0 - roughness for y-coord because texture was generated (in Sparky) for gloss model vec2 specularBRDF = texture(u_BRDFLUTTexture, vec2(m_Params.NdotV, 1.0 - m_Params.Roughness)).rg; @@ -322,7 +323,7 @@ void main() // Fresnel reflectance, metals use albedo vec3 F0 = mix(Fdielectric, m_Params.Albedo, m_Params.Metalness); - vec3 lightContribution = vec3(0.0);//Lighting(F0); + vec3 lightContribution = Lighting(F0); vec3 iblContribution = IBL(F0, Lr); color = vec4(lightContribution + iblContribution, 1.0); diff --git a/Editor/assets/shaders/PBRShader_Static.glsl b/Editor/assets/shaders/PBRShader_Static.glsl index d46a0a3..8255708 100644 --- a/Editor/assets/shaders/PBRShader_Static.glsl +++ b/Editor/assets/shaders/PBRShader_Static.glsl @@ -57,6 +57,7 @@ const vec3 Fdielectric = vec3(0.04); struct Light { vec3 Direction; vec3 Radiance; + float Multiplier; }; in VertexOutput @@ -246,7 +247,7 @@ vec3 Lighting(vec3 F0) for(int i = 0; i < LightCount; i++) { vec3 Li = -lights.Direction; - vec3 Lradiance = lights.Radiance; + vec3 Lradiance = lights.Radiance * lights.Multiplier; vec3 Lh = normalize(Li + m_Params.View); // Calculate angles between surface normal and various light vectors. @@ -271,15 +272,15 @@ 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 = fresnelSchlick(F0, m_Params.NdotV); + vec3 F = fresnelSchlickRoughness(F0, m_Params.NdotV, m_Params.Roughness); +// vec3 F = fresnelSchlickR(F0, m_Params.NdotV); vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness); vec3 diffuseIBL = m_Params.Albedo * irradiance; int u_EnvRadianceTexLevels = textureQueryLevels(u_EnvRadianceTex); float NoV = clamp(m_Params.NdotV, 0.0, 1.0); vec3 R = 2.0 * dot(m_Params.View, m_Params.Normal) * m_Params.Normal - m_Params.View; - vec3 specularIrradiance = textureLod(u_EnvRadianceTex, RotateVectorAboutY(u_EnvMapRotation, Lr), (m_Params.Roughness * m_Params.Roughness) * u_EnvRadianceTexLevels).rgb; + vec3 specularIrradiance = textureLod(u_EnvRadianceTex, RotateVectorAboutY(u_EnvMapRotation, Lr), (m_Params.Roughness) * u_EnvRadianceTexLevels).rgb; // Sample BRDF Lut, 1.0 - roughness for y-coord because texture was generated (in Sparky) for gloss model vec2 specularBRDF = texture(u_BRDFLUTTexture, vec2(m_Params.NdotV, 1.0 - m_Params.Roughness)).rg; @@ -317,5 +318,5 @@ void main() vec3 iblContribution = IBL(F0, Lr); color = vec4(lightContribution + iblContribution, 1.0); - color = vec4(iblContribution, 1.0); +// color = vec4(iblContribution, 1.0); } diff --git a/Prism/src/Prism.h b/Prism/src/Prism.h index ca349ec..fd7f5e7 100644 --- a/Prism/src/Prism.h +++ b/Prism/src/Prism.h @@ -14,6 +14,10 @@ #include "Prism/Core/Events/KeyEvent.h" #include "Prism/Core/Events/MouseEvent.h" + +#include "Prism/Core/Math/AABB.h" +#include "Prism/Core/Math/Ray.h" + // ImGui #include "imgui.h" diff --git a/Prism/src/Prism/Core/Input.h b/Prism/src/Prism/Core/Input.h index 74366df..bb0c09a 100644 --- a/Prism/src/Prism/Core/Input.h +++ b/Prism/src/Prism/Core/Input.h @@ -15,6 +15,7 @@ namespace Prism static bool IsMouseButtonPressed(int button); static float GetMouseX(); static float GetMouseY(); + static std::pair GetMousePosition(); }; } diff --git a/Prism/src/Prism/Core/KeyCodes.h b/Prism/src/Prism/Core/KeyCodes.h index 4fd1451..090fa28 100644 --- a/Prism/src/Prism/Core/KeyCodes.h +++ b/Prism/src/Prism/Core/KeyCodes.h @@ -129,4 +129,7 @@ #define PM_KEY_RIGHT_SUPER 347 #define PM_KEY_MENU 348 +#define PM_MOUSE_BUTTON_LEFT 0 +#define PM_MOUSE_BUTTON_RIGHT 1 +#define PM_MOUSE_BUTTON_MIDDLE 2 #endif //KEYCODES_H diff --git a/Prism/src/Prism/Core/Math/AABB.h b/Prism/src/Prism/Core/Math/AABB.h new file mode 100644 index 0000000..073653b --- /dev/null +++ b/Prism/src/Prism/Core/Math/AABB.h @@ -0,0 +1,25 @@ +// +// Created by sfd on 25-12-2. +// + +#ifndef PRISM_AABB_H +#define PRISM_AABB_H + +#include + +namespace Prism +{ + struct AABB + { + glm::vec3 Min, Max; + + AABB() + : Min(0.0f), Max(0.0f) {} + + AABB(const glm::vec3& min, const glm::vec3& max) + : Min(min), Max(max) {} + + }; +} + +#endif //PRISM_AABB_H diff --git a/Prism/src/Prism/Core/Math/Ray.h b/Prism/src/Prism/Core/Math/Ray.h new file mode 100644 index 0000000..ff47510 --- /dev/null +++ b/Prism/src/Prism/Core/Math/Ray.h @@ -0,0 +1,76 @@ +// +// Created by sfd on 25-12-2. +// + +#ifndef RAY_H +#define RAY_H + +#include + +#include "AABB.h" + +namespace Prism +{ + struct PRISM_API Ray + { + glm::vec3 Origin, Direction; + + bool IntersectsAABB(const AABB& aabb, float& t) const + { + glm::vec3 dirfrac; + // r.dir is unit direction vector of ray + dirfrac.x = 1.0f / Direction.x; + dirfrac.y = 1.0f / Direction.y; + dirfrac.z = 1.0f / Direction.z; + // lb is the corner of AABB with minimal coordinates - left bottom, rt is maximal corner + // r.org is origin of ray + const glm::vec3& lb = aabb.Min; + const glm::vec3& rt = aabb.Max; + const float t1 = (lb.x - Origin.x) * dirfrac.x; + const float t2 = (rt.x - Origin.x) * dirfrac.x; + const float t3 = (lb.y - Origin.y) * dirfrac.y; + const float t4 = (rt.y - Origin.y) * dirfrac.y; + const float t5 = (lb.z - Origin.z) * dirfrac.z; + const float t6 = (rt.z - Origin.z) * dirfrac.z; + + const float tmin = glm::max(glm::max(glm::min(t1, t2), glm::min(t3, t4)), glm::min(t5, t6)); + const float tmax = glm::min(glm::min(glm::max(t1, t2), glm::max(t3, t4)), glm::max(t5, t6)); + + // if tmax < 0, ray (line) is intersecting AABB, but the whole AABB is behind us + if (tmax < 0) + { + t = tmax; + return false; + } + + // if tmin > tmax, ray doesn't intersect AABB + if (tmin > tmax) + { + t = tmax; + return false; + } + + t = tmin; + return true; + } + + bool IntersectsTriangle(const glm::vec3& A, const glm::vec3& B, const glm::vec3& C, float& t) const + { + const glm::vec3 E1 = B - A; + const glm::vec3 E2 = C - A; + const glm::vec3 N = cross(E1, E2); + const float det = -glm::dot(Direction, N); + const float invdet = 1.0f / det; + const glm::vec3 AO = Origin - A; + const glm::vec3 DAO = glm::cross(AO, Direction); + const float u = glm::dot(E2, DAO) * invdet; + const float v = -glm::dot(E1, DAO) * invdet; + t = glm::dot(AO, N) * invdet; + return (det >= 1e-6 && t >= 0.0 && u >= 0.0 && v >= 0.0 && (u + v) <= 1.0); + } + + }; +} + + +#endif //RAY_H diff --git a/Prism/src/Prism/Core/Window.h b/Prism/src/Prism/Core/Window.h index 37af47b..c3ee2f1 100644 --- a/Prism/src/Prism/Core/Window.h +++ b/Prism/src/Prism/Core/Window.h @@ -36,8 +36,9 @@ namespace Prism virtual void OnUpdate() = 0; virtual void SetEventCallback(const EventCallbackFn& callback) = 0; - virtual unsigned int GetWidth() const = 0; - virtual unsigned int GetHeight() const = 0; + virtual uint32_t GetWidth() const = 0; + virtual uint32_t GetHeight() const = 0; + virtual std::pair GetSize() const = 0; virtual std::pair GetWindowPos() const = 0; virtual void SetVSync(bool enable) = 0; diff --git a/Prism/src/Prism/Editor/SceneHierachyPanel.cpp b/Prism/src/Prism/Editor/SceneHierachyPanel.cpp index 495bac8..8ab6950 100644 --- a/Prism/src/Prism/Editor/SceneHierachyPanel.cpp +++ b/Prism/src/Prism/Editor/SceneHierachyPanel.cpp @@ -132,11 +132,13 @@ namespace Prism { glm::mat4 localTransform = Mat4FromAssimpMat4(node->mTransformation); glm::mat4 transform = parentTransform * localTransform; + /* for (uint32_t i = 0; i < node->mNumMeshes; i++) { uint32_t meshIndex = node->mMeshes[i]; mesh->m_Submeshes[meshIndex].Transform = transform; } + */ if (ImGui::TreeNode(node->mName.C_Str())) { diff --git a/Prism/src/Prism/Platform/OpenGL/OpenGLFrameBuffer.cpp b/Prism/src/Prism/Platform/OpenGL/OpenGLFrameBuffer.cpp index 9243e75..6ed574c 100644 --- a/Prism/src/Prism/Platform/OpenGL/OpenGLFrameBuffer.cpp +++ b/Prism/src/Prism/Platform/OpenGL/OpenGLFrameBuffer.cpp @@ -13,7 +13,7 @@ namespace Prism OpenGLFrameBuffer::OpenGLFrameBuffer(const FramebufferSpecification& spec) : m_Specification(spec) { - OpenGLFrameBuffer::Resize(spec.Width, spec.Height); + OpenGLFrameBuffer::Resize(spec.Width, spec.Height, true); } @@ -39,9 +39,9 @@ namespace Prism }); } - void OpenGLFrameBuffer::Resize(const uint32_t width, const uint32_t height) + void OpenGLFrameBuffer::Resize(const uint32_t width, const uint32_t height, const bool forceReCreate) { - if (m_Specification.Width == width && m_Specification.Height == height) + if (!forceReCreate && (m_Specification.Width == width && m_Specification.Height == height)) return; m_Specification.Width = width; diff --git a/Prism/src/Prism/Platform/OpenGL/OpenGLFrameBuffer.h b/Prism/src/Prism/Platform/OpenGL/OpenGLFrameBuffer.h index 59826a5..30ffc35 100644 --- a/Prism/src/Prism/Platform/OpenGL/OpenGLFrameBuffer.h +++ b/Prism/src/Prism/Platform/OpenGL/OpenGLFrameBuffer.h @@ -18,7 +18,7 @@ namespace Prism void Bind() const override; void Unbind() const override; - void Resize(uint32_t width, uint32_t height) override; + void Resize(uint32_t width, uint32_t height, bool forceReCreate) override; void BindTexture(uint32_t slot) const override; diff --git a/Prism/src/Prism/Platform/OpenGL/OpenGLRendererAPI.cpp b/Prism/src/Prism/Platform/OpenGL/OpenGLRendererAPI.cpp index 14747bf..4b0b5b4 100644 --- a/Prism/src/Prism/Platform/OpenGL/OpenGLRendererAPI.cpp +++ b/Prism/src/Prism/Platform/OpenGL/OpenGLRendererAPI.cpp @@ -71,10 +71,7 @@ namespace Prism { 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_ASSERT(false, "ERROR"); - } + PM_CORE_ASSERT(false); break; case GL_DEBUG_SEVERITY_MEDIUM: diff --git a/Prism/src/Prism/Platform/OpenGL/OpenGLVertexArray.cpp b/Prism/src/Prism/Platform/OpenGL/OpenGLVertexArray.cpp index b937d9c..51c5386 100644 --- a/Prism/src/Prism/Platform/OpenGL/OpenGLVertexArray.cpp +++ b/Prism/src/Prism/Platform/OpenGL/OpenGLVertexArray.cpp @@ -59,7 +59,8 @@ namespace Prism void OpenGLVertexArray::AddVertexBuffer(const Ref& vertexBuffer) { - PM_CORE_ASSERT(vertexBuffer->GetLayout().GetElements().size(), "Vertex Buffer has no layout!"); + const auto size = vertexBuffer->GetLayout().GetElements().size(); + PM_CORE_ASSERT(size, "Vertex Buffer has no layout!"); Bind(); vertexBuffer->Bind(); diff --git a/Prism/src/Prism/Platform/Windows/WindowsInput.cpp b/Prism/src/Prism/Platform/Windows/WindowsInput.cpp index dc6edeb..b09d6f1 100644 --- a/Prism/src/Prism/Platform/Windows/WindowsInput.cpp +++ b/Prism/src/Prism/Platform/Windows/WindowsInput.cpp @@ -26,23 +26,21 @@ namespace Prism float Input::GetMouseX() { - const auto& window = dynamic_cast(Application::Get().GetWindow()); - - double xpos, ypos; - glfwGetCursorPos(static_cast(window.GetNativeWindow()), &xpos, &ypos); - - return static_cast(xpos); + return GetMousePosition().first; } float Input::GetMouseY() + { + return GetMousePosition().second; + } + + std::pair Input::GetMousePosition() { const auto& window = dynamic_cast(Application::Get().GetWindow()); double xpos, ypos; glfwGetCursorPos(static_cast(window.GetNativeWindow()), &xpos, &ypos); - return static_cast(ypos); + return {xpos, ypos}; } - - } diff --git a/Prism/src/Prism/Platform/Windows/WindowsWindow.cpp b/Prism/src/Prism/Platform/Windows/WindowsWindow.cpp index 134f7e4..24a7495 100644 --- a/Prism/src/Prism/Platform/Windows/WindowsWindow.cpp +++ b/Prism/src/Prism/Platform/Windows/WindowsWindow.cpp @@ -197,6 +197,14 @@ namespace Prism m_ImGuiMouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); // FIXME: GLFW doesn't have this. m_ImGuiMouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); // FIXME: GLFW doesn't have this. m_ImGuiMouseCursors[ImGuiMouseCursor_Hand] = glfwCreateStandardCursor(GLFW_HAND_CURSOR); + + // Update window size to actual size + { + int width, height; + glfwGetWindowSize(m_Window, &width, &height); + m_Data.Width = width; + m_Data.Height= height; + } } void WindowsWindow::Shutdown() diff --git a/Prism/src/Prism/Platform/Windows/WindowsWindow.h b/Prism/src/Prism/Platform/Windows/WindowsWindow.h index 47e11bd..af41bf7 100644 --- a/Prism/src/Prism/Platform/Windows/WindowsWindow.h +++ b/Prism/src/Prism/Platform/Windows/WindowsWindow.h @@ -24,6 +24,7 @@ namespace Prism inline void SetEventCallback(const EventCallbackFn& callback) override { m_Data.EventCallback = callback; } bool const IsVSync() const override { return m_Data.VSync; } void SetVSync(bool enable) override; + virtual std::pair GetSize() const override { return { m_Data.Width, m_Data.Height }; } virtual std::pair GetWindowPos() const override; inline void* GetNativeWindow() const { return m_Window; } diff --git a/Prism/src/Prism/Renderer/Camera.cpp b/Prism/src/Prism/Renderer/Camera.cpp index 2ce80de..3a36392 100644 --- a/Prism/src/Prism/Renderer/Camera.cpp +++ b/Prism/src/Prism/Renderer/Camera.cpp @@ -24,14 +24,17 @@ namespace Prism Camera::Camera(const glm::mat4& projectionMatrix) : m_ProjectionMatrix(projectionMatrix) { - m_Position = { 0, 0, 10 }; m_Rotation = glm::vec3(90.0f, 0.0f, 0.0f); m_FocalPoint = glm::vec3(0.0f); - m_Distance = glm::distance(m_Position, m_FocalPoint); + + glm::vec3 position = { -5, 5, 5}; + m_Distance = glm::distance(position, m_FocalPoint); m_Yaw = 3.0f * (float)M_PI / 4.0f; m_Pitch = M_PI / 4.0f; + + UpdateCameraView(); } void Camera::Focus() @@ -56,13 +59,7 @@ namespace Prism MouseZoom(delta.y); } - m_Position = CalculatePosition(); - - glm::quat orientation = GetOrientation(); - m_Rotation = glm::eulerAngles(orientation) * (180.0f / (float)M_PI); - m_ViewMatrix = glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, 1)) * glm::toMat4(glm::conjugate(orientation)) * glm::translate(glm::mat4(1.0f), -m_Position); - m_ViewMatrix = glm::translate(glm::mat4(1.0f), m_Position) * glm::toMat4(orientation); - m_ViewMatrix = glm::inverse(m_ViewMatrix); + UpdateCameraView(); } void Camera::OnEvent(Event& e) @@ -86,6 +83,16 @@ namespace Prism return glm::rotate(GetOrientation(), glm::vec3(0.0f, 0.0f, -1.0f)); } + void Camera::UpdateCameraView() + { + m_Position = CalculatePosition(); + + const glm::quat orientation = GetOrientation(); + m_Rotation = glm::eulerAngles(orientation) * (180.0f / (float)M_PI); + m_ViewMatrix = glm::translate(glm::mat4(1.0f), m_Position) * glm::toMat4(orientation); + m_ViewMatrix = glm::inverse(m_ViewMatrix); + } + bool Camera::OnMouseScroll(MouseScrolledEvent& e) { const float delta = e.GetOffsetY() * 0.1f; diff --git a/Prism/src/Prism/Renderer/Camera.h b/Prism/src/Prism/Renderer/Camera.h index 4042726..7ec10e2 100644 --- a/Prism/src/Prism/Renderer/Camera.h +++ b/Prism/src/Prism/Renderer/Camera.h @@ -43,6 +43,8 @@ namespace Prism public: inline void SetViewportSize(const uint32_t width, const uint32_t height) { m_ViewportWidth = width; m_ViewportHeight = height; } private: + void UpdateCameraView(); + bool OnMouseScroll(MouseScrolledEvent& e); void MousePan(const glm::vec2& delta); void MouseRotate(const glm::vec2& delta); diff --git a/Prism/src/Prism/Renderer/FrameBuffer.h b/Prism/src/Prism/Renderer/FrameBuffer.h index 46dc016..7640f58 100644 --- a/Prism/src/Prism/Renderer/FrameBuffer.h +++ b/Prism/src/Prism/Renderer/FrameBuffer.h @@ -40,7 +40,7 @@ namespace Prism virtual void Bind() const = 0; virtual void Unbind() const = 0; - virtual void Resize(uint32_t width, uint32_t height) = 0; + virtual void Resize(uint32_t width, uint32_t height, bool forceReCreate = false) = 0; virtual void BindTexture(uint32_t slot = 0) const = 0; diff --git a/Prism/src/Prism/Renderer/Mesh.cpp b/Prism/src/Prism/Renderer/Mesh.cpp index 29d95f5..224c918 100644 --- a/Prism/src/Prism/Renderer/Mesh.cpp +++ b/Prism/src/Prism/Renderer/Mesh.cpp @@ -20,6 +20,13 @@ namespace Prism { +#define MESH_DEBUG_LOG 1 +#ifdef MESH_DEBUG_LOG + #define PM_MESH_LOG(...) PM_CORE_TRACE(__VA_ARGS__) +#elif + #define PM_MESH_LOG(...) +#endif + constexpr unsigned int s_ImportFlags = aiProcess_CalcTangentSpace | // Create binormals/tangents just in case aiProcess_Triangulate | // Make sure we're triangles @@ -104,9 +111,7 @@ namespace Prism if (!scene || !scene->HasMeshes()) PM_CORE_ERROR("Failed to load mesh file: {0}", filename); - //double factor; - //scene->mMetaData->Get("UnitScaleFactor", factor); - //PM_CORE_INFO("FBX Scene Scale: {0}", factor); + m_Scene = scene; m_IsAnimated = scene->mAnimations != nullptr; m_MeshShader = m_IsAnimated ? Renderer::GetShaderLibrary()->Get("PBRShader_Anim") : Renderer::GetShaderLibrary()->Get("PBRShader_Static"); @@ -117,16 +122,17 @@ namespace Prism uint32_t indexCount = 0; m_Submeshes.reserve(scene->mNumMeshes); - for (size_t m = 0; m < scene->mNumMeshes; m++) + for (uint32_t m = 0; m < scene->mNumMeshes; m++) { aiMesh* mesh = scene->mMeshes[m]; - Submesh submesh; + Submesh& submesh = m_Submeshes.emplace_back(); submesh.BaseVertex = vertexCount; submesh.BaseIndex = indexCount; submesh.MaterialIndex = mesh->mMaterialIndex; submesh.IndexCount = mesh->mNumFaces * 3; - m_Submeshes.push_back(submesh); + // m_Submeshes.push_back(submesh); + submesh.MeshName = mesh->mName.C_Str(); vertexCount += mesh->mNumVertices; indexCount += submesh.IndexCount; @@ -155,8 +161,10 @@ namespace Prism } }else { - submesh.Min = { FLT_MAX, FLT_MAX, FLT_MAX }; - submesh.Max = { -FLT_MAX, -FLT_MAX, -FLT_MAX }; + + auto& aabb = submesh.BoundingBox; + aabb.Min = { FLT_MAX, FLT_MAX, FLT_MAX }; + aabb.Max = { -FLT_MAX, -FLT_MAX, -FLT_MAX }; for (size_t i = 0; i < mesh->mNumVertices; i++) { @@ -164,12 +172,12 @@ namespace Prism 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); + aabb.Min.x = glm::min(vertex.Position.x, aabb.Min.x); + aabb.Min.y = glm::min(vertex.Position.y, aabb.Min.y); + aabb.Min.z = glm::min(vertex.Position.z, aabb.Min.z); + aabb.Max.x = glm::max(vertex.Position.x, aabb.Max.x); + aabb.Max.y = glm::max(vertex.Position.y, aabb.Max.y); + aabb.Max.z = glm::max(vertex.Position.z, aabb.Max.z); if (mesh->HasTangentsAndBitangents()) @@ -189,7 +197,11 @@ namespace Prism for (size_t i = 0; i < mesh->mNumFaces; i++) { PM_CORE_ASSERT(mesh->mFaces[i].mNumIndices == 3, "Must have 3 indices."); - m_Indices.push_back({ mesh->mFaces[i].mIndices[0], mesh->mFaces[i].mIndices[1], mesh->mFaces[i].mIndices[2] }); + Index index = { mesh->mFaces[i].mIndices[0], mesh->mFaces[i].mIndices[1], mesh->mFaces[i].mIndices[2] }; + m_Indices.push_back(index); + + if (!m_IsAnimated) + m_TriangleCache[m].emplace_back(m_StaticVertices[index.V1 + submesh.BaseVertex], m_StaticVertices[index.V2 + submesh.BaseVertex], m_StaticVertices[index.V3 + submesh.BaseVertex]); } } @@ -238,6 +250,8 @@ namespace Prism // Material if (scene->HasMaterials()) { + PM_CORE_INFO("---- Materials - {0} ----", filename); + m_Textures.resize(scene->mNumMaterials); m_Materials.resize(scene->mNumMaterials); for (uint32_t i = 0; i < scene->mNumMaterials; i++) @@ -248,16 +262,26 @@ namespace Prism auto mi = CreateRef(m_BaseMaterial); m_Materials[i] = mi; - PM_CORE_INFO("Material Name = {0}; Index = {1}", aiMaterialName.data, i); + PM_MESH_LOG(" {0} (Index = {1})", aiMaterialName.data, i); aiString aiTexPath; uint32_t textureCount = aiMaterial->GetTextureCount(aiTextureType_DIFFUSE); - PM_CORE_TRACE(" TextureCount = {0}", textureCount); + PM_MESH_LOG(" TextureCount = {0}", textureCount); aiColor3D aiColor; aiMaterial->Get(AI_MATKEY_COLOR_DIFFUSE, aiColor); PM_CORE_TRACE("COLOR = {0}, {1}, {2}", aiColor.r, aiColor.g, aiColor.b); - if (aiMaterial->GetTexture(aiTextureType_DIFFUSE, 0, &aiTexPath) == AI_SUCCESS) + float shininess, metalness; + aiMaterial->Get(AI_MATKEY_SHININESS, shininess); + aiMaterial->Get(AI_MATKEY_REFLECTIVITY, metalness); + + // float roughness = 1.0f - shininess * 0.01f; + // roughness *= roughness; + float roughness = 1.0f - glm::sqrt(shininess / 100.0f); + PM_MESH_LOG(" COLOR = {0}, {1}, {2}", aiColor.r, aiColor.g, aiColor.b); + PM_MESH_LOG(" ROUGHNESS = {0}", roughness); + bool hasAlbedoMap = aiMaterial->GetTexture(aiTextureType_DIFFUSE, 0, &aiTexPath) == AI_SUCCESS; + if (hasAlbedoMap) { // TODO: Temp - this should be handled by Hazel's filesystem std::filesystem::path path = filename; @@ -265,27 +289,25 @@ namespace Prism parentPath /= std::string(aiTexPath.data); std::string texturePath = parentPath.string(); + PM_MESH_LOG(" Albedo map path = {0}", texturePath); auto texture = Texture2D::Create(texturePath, true); if (texture->Loaded()) { m_Textures[i] = texture; - PM_CORE_TRACE(" Texture Path = {0}", texturePath); mi->Set("u_AlbedoTexture", m_Textures[i]); mi->Set("u_AlbedoTexToggle", 1.0f); } else { PM_CORE_ERROR("Could not load texture: {0}", texturePath); - //mi->Set("u_AlbedoTexToggle", 0.0f); + // fallback to u_AlbedoColor mi->Set("u_AlbedoColor", glm::vec3{ aiColor.r, aiColor.g, aiColor.b }); } } else { - 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"); + PM_MESH_LOG(" No albedo map"); } // Normal Maps @@ -299,21 +321,21 @@ namespace Prism parentPath /= std::string(aiTexPath.data); std::string texturePath = parentPath.string(); + PM_MESH_LOG(" Normal map path = {0}", texturePath); 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); + PM_CORE_ERROR(" Could not load texture: {0}", texturePath); } } else { - PM_CORE_TRACE("Mesh has no normal map"); + PM_MESH_LOG(" no normal map"); } // Roughness map @@ -327,23 +349,27 @@ namespace Prism parentPath /= std::string(aiTexPath.data); std::string texturePath = parentPath.string(); + PM_MESH_LOG(" Roughness map path = {0}", texturePath); auto texture = Texture2D::Create(texturePath); if (texture->Loaded()) { - PM_CORE_TRACE(" Roughness map path = {0}", texturePath); + 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); + PM_CORE_ERROR(" Could not load texture: {0}", texturePath); } } else { - PM_CORE_TRACE("Mesh has no roughness texture"); + PM_MESH_LOG(" no roughness texture"); + mi->Set("u_Roughness", roughness); } + +#if 0 // Metalness map // mi->Set("u_Metalness", 0.0f); // mi->Set("u_MetalnessTexToggle", 0.0f); @@ -358,7 +384,7 @@ namespace Prism auto texture = Texture2D::Create(texturePath); if (texture->Loaded()) { - PM_CORE_TRACE(" Metalness map path = {0}", texturePath); + PM_MESH_LOG(" Metalness map path = {0}", texturePath); mi->Set("u_MetalnessTexture", texture); mi->Set("u_MetalnessTexToggle", 1.0f); } @@ -369,169 +395,82 @@ namespace Prism } else { - PM_CORE_TRACE("Mesh has no metalness texture"); + PM_MESH_LOG(" no metalness texture"); + mi->Set("u_Metalness", metalness); } continue; - - +#endif + bool metalnessTextureFound = false; for (uint32_t i = 0; i < aiMaterial->mNumProperties; i++) { auto prop = aiMaterial->mProperties[i]; PM_CORE_TRACE("Material Property:"); PM_CORE_TRACE(" Name = {0}", prop->mKey.data); + float data = *(float*)prop->mData; + PM_MESH_LOG(" Value = {0}", data); switch (prop->mSemantic) { - case aiTextureType_NONE: - PM_CORE_TRACE(" Semantic = aiTextureType_NONE"); - break; - case aiTextureType_DIFFUSE: - PM_CORE_TRACE(" Semantic = aiTextureType_DIFFUSE"); - break; - case aiTextureType_SPECULAR: - PM_CORE_TRACE(" Semantic = aiTextureType_SPECULAR"); - break; - case aiTextureType_AMBIENT: - PM_CORE_TRACE(" Semantic = aiTextureType_AMBIENT"); - break; - case aiTextureType_EMISSIVE: - PM_CORE_TRACE(" Semantic = aiTextureType_EMISSIVE"); - break; - case aiTextureType_HEIGHT: - PM_CORE_TRACE(" Semantic = aiTextureType_HEIGHT"); - break; - case aiTextureType_NORMALS: - PM_CORE_TRACE(" Semantic = aiTextureType_NORMALS"); - break; - case aiTextureType_SHININESS: - PM_CORE_TRACE(" Semantic = aiTextureType_SHININESS"); - break; - case aiTextureType_OPACITY: - PM_CORE_TRACE(" Semantic = aiTextureType_OPACITY"); - break; - case aiTextureType_DISPLACEMENT: - PM_CORE_TRACE(" Semantic = aiTextureType_DISPLACEMENT"); - break; - case aiTextureType_LIGHTMAP: - PM_CORE_TRACE(" Semantic = aiTextureType_LIGHTMAP"); - break; - case aiTextureType_REFLECTION: - PM_CORE_TRACE(" Semantic = aiTextureType_REFLECTION"); - break; - case aiTextureType_UNKNOWN: - PM_CORE_TRACE(" Semantic = aiTextureType_UNKNOWN"); - break; + case aiTextureType_NONE: PM_MESH_LOG(" Semantic = aiTextureType_NONE"); break; + case aiTextureType_DIFFUSE: PM_MESH_LOG(" Semantic = aiTextureType_DIFFUSE"); break; + case aiTextureType_SPECULAR: PM_MESH_LOG(" Semantic = aiTextureType_SPECULAR"); break; + case aiTextureType_AMBIENT: PM_MESH_LOG(" Semantic = aiTextureType_AMBIENT"); break; + case aiTextureType_EMISSIVE: PM_MESH_LOG(" Semantic = aiTextureType_EMISSIVE"); break; + case aiTextureType_HEIGHT: PM_MESH_LOG(" Semantic = aiTextureType_HEIGHT"); break; + case aiTextureType_NORMALS: PM_MESH_LOG(" Semantic = aiTextureType_NORMALS"); break; + case aiTextureType_SHININESS: PM_MESH_LOG(" Semantic = aiTextureType_SHININESS"); break; + case aiTextureType_OPACITY: PM_MESH_LOG(" Semantic = aiTextureType_OPACITY"); break; + case aiTextureType_DISPLACEMENT:PM_MESH_LOG(" Semantic = aiTextureType_DISPLACEMENT"); break; + case aiTextureType_LIGHTMAP: PM_MESH_LOG(" Semantic = aiTextureType_LIGHTMAP"); break; + case aiTextureType_REFLECTION: PM_MESH_LOG(" Semantic = aiTextureType_REFLECTION"); break; + case aiTextureType_UNKNOWN: PM_MESH_LOG(" Semantic = aiTextureType_UNKNOWN"); break; } if (prop->mType == aiPTI_String) { uint32_t strLength = *(uint32_t*)prop->mData; std::string str(prop->mData + 4, strLength); - PM_CORE_TRACE(" Value = {0}", str); std::string key = prop->mKey.data; if (key == "$raw.ReflectionFactor|file") { + metalnessTextureFound = true; + // TODO: Temp - this should be handled by Hazel's filesystem std::filesystem::path path = filename; auto parentPath = path.parent_path(); parentPath /= str; std::string texturePath = parentPath.string(); + + PM_MESH_LOG(" Metalness map path = {0}", texturePath); 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); - mi->Set("u_Metalness", 0.5f); - mi->Set("u_MetalnessTexToggle", 1.0f); + PM_CORE_ERROR(" Could not load texture: {0}", texturePath); + mi->Set("u_Metalness", metalness); + mi->Set("u_MetalnessTexToggle", 0.0f); } + break; } } } - - /* - // Normal maps - if (aiMaterial->GetTexture(aiTextureType_NORMALS, 0, &aiTexPath) == AI_SUCCESS) + if (!metalnessTextureFound) { - // 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(); + PM_MESH_LOG(" No metalness map"); - 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); - //mi->Set("u_AlbedoTexToggle", 0.0f); - // mi->Set("u_AlbedoColor", glm::vec3{ color.r, color.g, color.b }); - } + mi->Set("u_Metalness", metalness); + mi->Set("u_MetalnessTexToggle", 0.0f); } - - // Roughness map - 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); - mi->Set("u_RoughnessTexToggle", 1.0f); - mi->Set("u_Roughness", 0.5f); - } - } - - // Metalness map - 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); - mi->Set("u_Metalness", 0.5f); - mi->Set("u_MetalnessTexToggle", 1.0f); - } - } - */ - } + PM_MESH_LOG("------------------------"); } m_VertexArray = VertexArray::Create(); @@ -564,7 +503,6 @@ namespace Prism auto ib = IndexBuffer::Create(m_Indices.data(), (uint32_t)m_Indices.size() * sizeof(Index)); m_VertexArray->SetIndexBuffer(ib); - m_Scene = scene; } Mesh::~Mesh() = default; @@ -591,37 +529,37 @@ namespace Prism void Mesh::DumpVertexBuffer() { // TODO: Convert to ImGui - PM_CORE_TRACE("------------------------------------------------------"); - PM_CORE_TRACE("Vertex Buffer Dump"); - PM_CORE_TRACE("Mesh: {0}", m_FilePath); + PM_MESH_LOG("------------------------------------------------------"); + PM_MESH_LOG("Vertex Buffer Dump"); + PM_MESH_LOG("Mesh: {0}", m_FilePath); if (m_IsAnimated) { for (size_t i = 0; i < m_AnimatedVertices.size(); i++) { auto& vertex = m_AnimatedVertices[i]; - PM_CORE_TRACE("Vertex: {0}", i); - PM_CORE_TRACE("Position: {0}, {1}, {2}", vertex.Position.x, vertex.Position.y, vertex.Position.z); - PM_CORE_TRACE("Normal: {0}, {1}, {2}", vertex.Normal.x, vertex.Normal.y, vertex.Normal.z); - PM_CORE_TRACE("Binormal: {0}, {1}, {2}", vertex.Binormal.x, vertex.Binormal.y, vertex.Binormal.z); - PM_CORE_TRACE("Tangent: {0}, {1}, {2}", vertex.Tangent.x, vertex.Tangent.y, vertex.Tangent.z); - PM_CORE_TRACE("TexCoord: {0}, {1}", vertex.Texcoord.x, vertex.Texcoord.y); - PM_CORE_TRACE("--"); + PM_MESH_LOG("Vertex: {0}", i); + PM_MESH_LOG("Position: {0}, {1}, {2}", vertex.Position.x, vertex.Position.y, vertex.Position.z); + PM_MESH_LOG("Normal: {0}, {1}, {2}", vertex.Normal.x, vertex.Normal.y, vertex.Normal.z); + PM_MESH_LOG("Binormal: {0}, {1}, {2}", vertex.Binormal.x, vertex.Binormal.y, vertex.Binormal.z); + PM_MESH_LOG("Tangent: {0}, {1}, {2}", vertex.Tangent.x, vertex.Tangent.y, vertex.Tangent.z); + PM_MESH_LOG("TexCoord: {0}, {1}", vertex.Texcoord.x, vertex.Texcoord.y); + PM_MESH_LOG("--"); } }else { for (size_t i = 0; i < m_StaticVertices.size(); i++) { auto& vertex = m_StaticVertices[i]; - PM_CORE_TRACE("Vertex: {0}", i); - PM_CORE_TRACE("Position: {0}, {1}, {2}", vertex.Position.x, vertex.Position.y, vertex.Position.z); - PM_CORE_TRACE("Normal: {0}, {1}, {2}", vertex.Normal.x, vertex.Normal.y, vertex.Normal.z); - PM_CORE_TRACE("Binormal: {0}, {1}, {2}", vertex.Binormal.x, vertex.Binormal.y, vertex.Binormal.z); - PM_CORE_TRACE("Tangent: {0}, {1}, {2}", vertex.Tangent.x, vertex.Tangent.y, vertex.Tangent.z); - PM_CORE_TRACE("TexCoord: {0}, {1}", vertex.Texcoord.x, vertex.Texcoord.y); - PM_CORE_TRACE("--"); + PM_MESH_LOG("Vertex: {0}", i); + PM_MESH_LOG("Position: {0}, {1}, {2}", vertex.Position.x, vertex.Position.y, vertex.Position.z); + PM_MESH_LOG("Normal: {0}, {1}, {2}", vertex.Normal.x, vertex.Normal.y, vertex.Normal.z); + PM_MESH_LOG("Binormal: {0}, {1}, {2}", vertex.Binormal.x, vertex.Binormal.y, vertex.Binormal.z); + PM_MESH_LOG("Tangent: {0}, {1}, {2}", vertex.Tangent.x, vertex.Tangent.y, vertex.Tangent.z); + PM_MESH_LOG("TexCoord: {0}, {1}", vertex.Texcoord.x, vertex.Texcoord.y); + PM_MESH_LOG("--"); } } - PM_CORE_TRACE("------------------------------------------------------"); + PM_MESH_LOG("------------------------------------------------------"); } void Mesh::BoneTransform(float time) @@ -679,7 +617,9 @@ namespace Prism for (uint32_t i = 0; i < node->mNumMeshes; i++) { const uint32_t mesh = node->mMeshes[i]; - m_Submeshes[mesh].Transform = transform; + auto& submesh = m_Submeshes[mesh]; + submesh.NodeName = node->mName.C_Str(); + submesh.Transform = transform; } for (uint32_t i = 0; i < node->mNumChildren; i++) diff --git a/Prism/src/Prism/Renderer/Mesh.h b/Prism/src/Prism/Renderer/Mesh.h index 12c1cbc..0f0f5c1 100644 --- a/Prism/src/Prism/Renderer/Mesh.h +++ b/Prism/src/Prism/Renderer/Mesh.h @@ -7,11 +7,11 @@ #include -#include "Buffer.h" #include "Material.h" #include "Shader.h" #include "VertexArray.h" #include "Prism/Core/TimeStep.h" +#include "Prism/Core/Math/AABB.h" struct aiNode; struct aiAnimation; @@ -78,6 +78,14 @@ namespace Prism void AddBoneData(uint32_t BoneID, float Weight); }; + struct Triangle + { + Vertex V0, V1, V2; + + Triangle(const Vertex& v0, const Vertex& v1, const Vertex& v2) + : V0(v0), V1(v1), V2(v2) {} + }; + class Submesh { public: @@ -87,7 +95,9 @@ namespace Prism uint32_t IndexCount; glm::mat4 Transform; - glm::vec3 Min, Max; //TODO: AABB + AABB BoundingBox; + + std::string NodeName, MeshName; }; class PRISM_API Mesh @@ -101,11 +111,16 @@ namespace Prism void OnUpdate(TimeStep deltaTime); void DumpVertexBuffer(); + std::vector& GetSubmeshes() { return m_Submeshes; } + const std::vector& GetSubmeshes() const { return m_Submeshes; } + inline Ref GetMeshShader() { return m_MeshShader; } inline Ref GetMaterial() { return m_BaseMaterial; } std::vector> GetMaterials() { return m_Materials; } const std::vector>& GetTextures() const { return m_Textures; } const std::string& GetFilePath() const { return m_FilePath; } + + const std::vector GetTriangleCache(uint32_t index) const { return m_TriangleCache.at(index); } private: void BoneTransform(float time); void ReadNodeHierarchy(float AnimationTime, const aiNode* pNode, const glm::mat4& ParentTransform); @@ -146,6 +161,8 @@ namespace Prism std::vector> m_NormalMaps; std::vector> m_Materials; + std::unordered_map> m_TriangleCache; + // Animation bool m_IsAnimated = false; float m_AnimationTime = 0.0f; diff --git a/Prism/src/Prism/Renderer/Renderer.cpp b/Prism/src/Prism/Renderer/Renderer.cpp index b4aa61b..1cad566 100644 --- a/Prism/src/Prism/Renderer/Renderer.cpp +++ b/Prism/src/Prism/Renderer/Renderer.cpp @@ -195,36 +195,44 @@ namespace Prism } } - void Renderer::DrawAABB(const Ref& mesh, const glm::vec4& color) + void Renderer::DrawAABB(const Ref& mesh, const glm::mat4& transform, const glm::vec4& color) { - for (Submesh& submesh : mesh->m_Submeshes) + for (const 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); + const auto& aabb = submesh.BoundingBox; + auto aabbTransform = transform * submesh.Transform; + DrawAABB(aabb, aabbTransform, color); } } + void Renderer::DrawAABB(const AABB& aabb, const glm::mat4& transform, const glm::vec4& color) + { + glm::vec4 min = { aabb.Min.x, aabb.Min.y, aabb.Min.z, 1.0f }; + glm::vec4 max = { aabb.Max.x, aabb.Max.y, aabb.Max.z, 1.0f }; + + const glm::vec4 corners[8] = + { + transform * glm::vec4 { aabb.Min.x, aabb.Min.y, aabb.Max.z, 1.0f }, + transform * glm::vec4 { aabb.Min.x, aabb.Max.y, aabb.Max.z, 1.0f }, + transform * glm::vec4 { aabb.Max.x, aabb.Max.y, aabb.Max.z, 1.0f }, + transform * glm::vec4 { aabb.Max.x, aabb.Min.y, aabb.Max.z, 1.0f }, + + transform * glm::vec4 { aabb.Min.x, aabb.Min.y, aabb.Min.z, 1.0f }, + transform * glm::vec4 { aabb.Min.x, aabb.Max.y, aabb.Min.z, 1.0f }, + transform * glm::vec4 { aabb.Max.x, aabb.Max.y, aabb.Min.z, 1.0f }, + transform * glm::vec4 { aabb.Max.x, aabb.Min.y, aabb.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 7571ba2..da2dc98 100644 --- a/Prism/src/Prism/Renderer/Renderer.h +++ b/Prism/src/Prism/Renderer/Renderer.h @@ -56,7 +56,8 @@ namespace Prism 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)); + static void DrawAABB(const AABB& aabb, const glm::mat4& transform, const glm::vec4& color = glm::vec4(1.0f)); + static void DrawAABB(const Ref& mesh,const glm::mat4& transform, 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 index b40d901..d9e80dd 100644 --- a/Prism/src/Prism/Renderer/Renderer2D.cpp +++ b/Prism/src/Prism/Renderer/Renderer2D.cpp @@ -194,7 +194,7 @@ namespace Prism s_Data.LineShader->SetMat4("u_ViewProjection", s_Data.CameraViewProj); s_Data.LineVertexArray->Bind(); - Renderer::SetLineThickness(2.0f); + Renderer::SetLineThickness(1.0f); Renderer::DrawIndexed(s_Data.LineIndexCount, PrimitiveType::Lines, s_Data.DepthTest); s_Data.Stats.DrawCalls++; } diff --git a/Prism/src/Prism/Renderer/SceneRenderer.cpp b/Prism/src/Prism/Renderer/SceneRenderer.cpp index add52cf..8d2d945 100644 --- a/Prism/src/Prism/Renderer/SceneRenderer.cpp +++ b/Prism/src/Prism/Renderer/SceneRenderer.cpp @@ -25,6 +25,7 @@ namespace Prism // Resources Ref SkyboxMaterial; Environment SceneEnvironment; + Light ActiveLight; } SceneData; Ref BRDFLUT; @@ -101,6 +102,7 @@ namespace Prism s_Data.SceneData.SceneCamera = scene->m_Camera; s_Data.SceneData.SkyboxMaterial = scene->m_SkyboxMaterial; s_Data.SceneData.SceneEnvironment = scene->m_Environment; + s_Data.SceneData.ActiveLight = scene->m_Light; } void SceneRenderer::EndScene() @@ -128,8 +130,8 @@ namespace Prism std::pair, Ref> SceneRenderer::CreateEnvironmentMap(const std::string& filepath) { - const uint32_t cubemapSize = 2048; - const uint32_t irradianceMapSize = 32; + constexpr uint32_t cubemapSize = 2048; + constexpr uint32_t irradianceMapSize = 32; Ref envUnfiltered = TextureCube::Create(TextureFormat::Float16, cubemapSize, cubemapSize); if (!equirectangularConversionShader) @@ -245,6 +247,9 @@ namespace Prism baseMaterial->Set("u_EnvIrradianceTex", s_Data.SceneData.SceneEnvironment.IrradianceMap); baseMaterial->Set("u_BRDFLUTTexture", s_Data.BRDFLUT); + // Set lights (TODO: move to light environment and don't do per mesh) + baseMaterial->Set("lights", s_Data.SceneData.ActiveLight); + auto overrideMaterial = nullptr; // dc.Material; Renderer::SubmitMesh(dc.mesh, dc.Transform, overrideMaterial); } @@ -261,7 +266,7 @@ namespace Prism { Renderer2D::BeginScene(viewProjection); for (auto& dc : s_Data.DrawList) - Renderer::DrawAABB(dc.mesh); + Renderer::DrawAABB(dc.mesh, dc.Transform); Renderer2D::EndScene(); } diff --git a/Prism/src/Prism/Scene/Scene.h b/Prism/src/Prism/Scene/Scene.h index 50a1827..a582472 100644 --- a/Prism/src/Prism/Scene/Scene.h +++ b/Prism/src/Prism/Scene/Scene.h @@ -21,6 +21,14 @@ namespace Prism static Environment Load(const std::string& filepath); }; + struct Light + { + glm::vec3 Direction; + glm::vec3 Radiance; + + float Multiplier = 1.0f; + }; + class PRISM_API Scene{ public: Scene(const std::string& debugName = "Scene"); @@ -37,6 +45,7 @@ namespace Prism void SetEnvironment(const Environment& environment); void SetSkybox(const Ref& skybox); + Light& GetLight() { return m_Light; } float& GetSkyboxLod() { return m_SkyboxLod; } void AddEntity(Entity* entity); @@ -47,12 +56,16 @@ namespace Prism std::vector m_Entities; Camera m_Camera; + Light m_Light; + float m_LightMultiplier = 0.3f; + Environment m_Environment; Ref m_SkyboxTexture; Ref m_SkyboxMaterial; float m_SkyboxLod = 1.0f; + private: friend class SceneRenderer; friend class SceneHierarchyPanel; };