add mouse picking, add more hdr environment maps

This commit is contained in:
2025-12-02 12:04:12 +08:00
parent c96eb34af5
commit 5251ae22fb
35 changed files with 488 additions and 269 deletions

View File

@ -149,7 +149,7 @@ namespace Prism
auto secondEntity = m_Scene->CreateEntity("Gun Entity"); 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}); secondEntity->Transform() = glm::translate(glm::mat4(1.0f), { 5, 5, 5 }) * glm::scale(glm::mat4(1.0f), {10, 10, 10});
mesh = CreateRef<Mesh>("assets/models/m1911/m1911.fbx"); mesh = CreateRef<Mesh>("assets/models/m1911/m1911Materials.fbx");
secondEntity->SetMesh(mesh); secondEntity->SetMesh(mesh);
} }
@ -208,9 +208,12 @@ namespace Prism
// Editor // Editor
m_CheckerboardTex = Texture2D::Create("assets/editor/Checkerboard.tga"); m_CheckerboardTex = Texture2D::Create("assets/editor/Checkerboard.tga");
// lights // set lights
m_Light.Direction = {-0.5f, -0.5f, 1.0f}; auto& light = m_Scene->GetLight();
m_Light.Radiance = {1.0f, 1.0f, 1.0f}; light.Direction = { -0.5f, -0.5f, 1.0f };
light.Radiance = { 1.0f, 1.0f, 1.0f };
m_CurrentlySelectedTransform = &m_MeshEntity->Transform();
} }
void EditorLayer::OnDetach() void EditorLayer::OnDetach()
@ -228,7 +231,6 @@ namespace Prism
m_MeshMaterial->Set("u_AlbedoColor", m_AlbedoInput.Color); m_MeshMaterial->Set("u_AlbedoColor", m_AlbedoInput.Color);
m_MeshMaterial->Set("u_Metalness", m_MetalnessInput.Value); m_MeshMaterial->Set("u_Metalness", m_MetalnessInput.Value);
m_MeshMaterial->Set("u_Roughness", m_RoughnessInput.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_AlbedoTexToggle", m_AlbedoInput.UseTexture ? 1.0f : 0.0f);
m_MeshMaterial->Set("u_NormalTexToggle", m_NormalInput.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_MetalnessTexToggle", m_MetalnessInput.UseTexture ? 1.0f : 0.0f);
@ -236,7 +238,8 @@ namespace Prism
m_MeshMaterial->Set("u_EnvMapRotation", m_EnvMapRotation); m_MeshMaterial->Set("u_EnvMapRotation", m_EnvMapRotation);
m_SphereBaseMaterial->Set("u_AlbedoColor", m_AlbedoInput.Color); 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_RadiancePrefilter", m_RadiancePrefilter ? 1.0f : 0.0f);
m_SphereBaseMaterial->Set("u_AlbedoTexToggle", m_AlbedoInput.UseTexture ? 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_NormalTexToggle", m_NormalInput.UseTexture ? 1.0f : 0.0f);
@ -264,8 +267,19 @@ namespace Prism
Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false); Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false);
auto viewProj = m_Scene->GetCamera().GetViewProjection(); auto viewProj = m_Scene->GetCamera().GetViewProjection();
Renderer2D::BeginScene(viewProj, false); 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(), m_MeshEntity->Transform());
Renderer::DrawAABB(m_MeshEntity->GetMesh());
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(); Renderer2D::EndScene();
Renderer::EndRenderPass(); Renderer::EndRenderPass();
} }
@ -441,9 +455,10 @@ namespace Prism
ImGui::Columns(2); ImGui::Columns(2);
ImGui::AlignTextToFramePadding(); ImGui::AlignTextToFramePadding();
Property("Light Direction", m_Light.Direction); auto& light = m_Scene->GetLight();
Property("Light Radiance", m_Light.Radiance, PropertyFlag::ColorProperty); Property("Light Direction", light.Direction);
Property("Light Multiplier", m_LightMultiplier, 0.0f, 5.0f); 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("Exposure", m_ActiveScene->GetCamera().GetExposure(), 0.0f, 5.0f);
Property("Radiance Prefiltering", m_RadiancePrefilter); Property("Radiance Prefiltering", m_RadiancePrefilter);
@ -642,6 +657,8 @@ namespace Prism
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
ImGui::Begin("Viewport"); ImGui::Begin("Viewport");
auto viewportOffset = ImGui::GetCursorPos(); // includes tab bar
auto viewportSize = ImGui::GetContentRegionAvail(); auto viewportSize = ImGui::GetContentRegionAvail();
SceneRenderer::SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y); 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().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 }); ImGui::Image((ImTextureRef)SceneRenderer::GetFinalColorBufferRendererID(), viewportSize, { 0, 1 }, { 1, 0 });
static int counter = 0;
auto windowSize = ImGui::GetWindowSize(); auto windowSize = ImGui::GetWindowSize();
ImVec2 minBound = ImGui::GetWindowPos(); ImVec2 minBound = ImGui::GetWindowPos();
minBound.x += viewportOffset.x;
minBound.y += viewportOffset.y;
ImVec2 maxBound = { minBound.x + windowSize.x, minBound.y + windowSize.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); m_AllowViewportCameraEvents = ImGui::IsMouseHoveringRect(minBound, maxBound);
// ImGuizmo // ImGuizmo
if (m_GizmoType != -1) if (m_GizmoType != -1 && m_CurrentlySelectedTransform)
{ {
const auto rw = (float)ImGui::GetWindowWidth(); const auto rw = (float)ImGui::GetWindowWidth();
const auto rh = (float)ImGui::GetWindowHeight(); const auto rh = (float)ImGui::GetWindowHeight();
@ -663,7 +686,15 @@ namespace Prism
ImGuizmo::SetDrawlist(); ImGuizmo::SetDrawlist();
ImGuizmo::SetRect(ImGui::GetWindowPos().x, ImGui::GetWindowPos().y, rw, rh); ImGuizmo::SetRect(ImGui::GetWindowPos().x, ImGui::GetWindowPos().y, rw, rh);
const auto& camera = m_ActiveScene->GetCamera(); 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(); ImGui::End();
@ -678,6 +709,7 @@ namespace Prism
EventDispatcher dispatcher(e); EventDispatcher dispatcher(e);
dispatcher.Dispatch<KeyPressedEvent>(PM_BIND_EVENT_FN(EditorLayer::OnKeyPressedEvent)); dispatcher.Dispatch<KeyPressedEvent>(PM_BIND_EVENT_FN(EditorLayer::OnKeyPressedEvent));
dispatcher.Dispatch<MouseButtonPressedEvent>(PM_BIND_EVENT_FN(EditorLayer::OnMouseButtonPressedEvent));
} }
bool EditorLayer::OnKeyPressedEvent(KeyPressedEvent& e) bool EditorLayer::OnKeyPressedEvent(KeyPressedEvent& e)
@ -714,9 +746,85 @@ namespace Prism
return false; 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<float>::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) void EditorLayer::ShowBoundingBoxes(bool show, bool onTop)
{ {
SceneRenderer::GetOptions().ShowBoundingBoxes = show && !onTop; SceneRenderer::GetOptions().ShowBoundingBoxes = show && !onTop;
m_DrawOnTopBoundingBoxes = show && onTop; m_DrawOnTopBoundingBoxes = show && onTop;
} }
std::pair<float, float> 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<glm::vec3, glm::vec3> 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 };
}
} }

View File

@ -24,9 +24,14 @@ namespace Prism
private: private:
bool OnKeyPressedEvent(KeyPressedEvent& e); bool OnKeyPressedEvent(KeyPressedEvent& e);
bool OnMouseButtonPressedEvent(MouseButtonPressedEvent& e);
void ShowBoundingBoxes(bool show, bool onTop = false); void ShowBoundingBoxes(bool show, bool onTop = false);
private:
std::pair<float, float> GetMouseViewportSpace() const;
std::pair<glm::vec3, glm::vec3> CastRay(float mx, float my) const;
private: private:
Scope<SceneHierarchyPanel> m_SceneHierarchyPanel; Scope<SceneHierarchyPanel> m_SceneHierarchyPanel;
@ -36,25 +41,27 @@ namespace Prism
Entity* m_MeshEntity = nullptr; Entity* m_MeshEntity = nullptr;
Ref<Shader> m_BrushShader;
Ref<Mesh> m_PlaneMesh; Ref<Mesh> m_PlaneMesh;
Ref<Material> m_SphereBaseMaterial; Ref<Material> m_SphereBaseMaterial;
Ref<Material> m_MeshMaterial; Ref<Material> m_MeshMaterial;
Ref<RenderPass> m_GeoPass, m_CompositePass;
Ref<MaterialInstance> m_GridMaterial;
std::vector<Ref<MaterialInstance>> m_MetalSphereMaterialInstances; std::vector<Ref<MaterialInstance>> m_MetalSphereMaterialInstances;
std::vector<Ref<MaterialInstance>> m_DielectricSphereMaterialInstances; std::vector<Ref<MaterialInstance>> m_DielectricSphereMaterialInstances;
float m_GridScale = 16.025f, m_GridSize = 0.025f;
float m_MeshScale = 1.0f;
// Imguizmo // Imguizmo
glm::vec2 m_ViewportBounds[2];
int m_GizmoType = -1; // -1 = no gizmo int m_GizmoType = -1; // -1 = no gizmo
float m_SnapValue = 0.5f;
struct SelectedSubmesh
{
Submesh* Mesh;
float Distance;
};
std::vector<SelectedSubmesh> m_SelectedSubmeshes;
glm::mat4* m_CurrentlySelectedTransform = nullptr;
// configure button // configure button
bool m_AllowViewportCameraEvents = false; bool m_AllowViewportCameraEvents = false;
@ -97,14 +104,6 @@ namespace Prism
RoughnessInput m_RoughnessInput; RoughnessInput m_RoughnessInput;
struct Light
{
glm::vec3 Direction;
glm::vec3 Radiance;
};
Light m_Light;
float m_LightMultiplier = 0.3f;
// PBR params // PBR params
bool m_RadiancePrefilter = false; bool m_RadiancePrefilter = false;

BIN
Editor/assets/env/pink_sunrise_4k.hdr vendored Normal file

Binary file not shown.

BIN
Editor/assets/env/rooitou_park_4k.hdr vendored Normal file

Binary file not shown.

BIN
Editor/assets/env/venice_dawn_1_4k.hdr vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -46,7 +46,7 @@ void main()
vec4 localPosition = boneTransform * vec4(a_Position, 1.0); vec4 localPosition = boneTransform * vec4(a_Position, 1.0);
vs_Output.WorldPosition = vec3(u_Transform * 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.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.WorldNormals = mat3(u_Transform) * mat3(a_Tangent, a_Binormal, a_Normal);
vs_Output.Binormal = mat3(boneTransform) * a_Binormal; vs_Output.Binormal = mat3(boneTransform) * a_Binormal;
@ -68,6 +68,7 @@ const vec3 Fdielectric = vec3(0.04);
struct Light { struct Light {
vec3 Direction; vec3 Direction;
vec3 Radiance; vec3 Radiance;
float Multiplier;
}; };
in VertexOutput in VertexOutput
@ -256,7 +257,7 @@ vec3 Lighting(vec3 F0)
for(int i = 0; i < LightCount; i++) for(int i = 0; i < LightCount; i++)
{ {
vec3 Li = -lights.Direction; vec3 Li = -lights.Direction;
vec3 Lradiance = lights.Radiance; vec3 Lradiance = lights.Radiance * lights.Multiplier;
vec3 Lh = normalize(Li + m_Params.View); vec3 Lh = normalize(Li + m_Params.View);
// Calculate angles between surface normal and various light vectors. // 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); int u_EnvRadianceTexLevels = textureQueryLevels(u_EnvRadianceTex);
float NoV = clamp(m_Params.NdotV, 0.0, 1.0); 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 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 // 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; 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 // Fresnel reflectance, metals use albedo
vec3 F0 = mix(Fdielectric, m_Params.Albedo, m_Params.Metalness); 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); vec3 iblContribution = IBL(F0, Lr);
color = vec4(lightContribution + iblContribution, 1.0); color = vec4(lightContribution + iblContribution, 1.0);

View File

@ -57,6 +57,7 @@ const vec3 Fdielectric = vec3(0.04);
struct Light { struct Light {
vec3 Direction; vec3 Direction;
vec3 Radiance; vec3 Radiance;
float Multiplier;
}; };
in VertexOutput in VertexOutput
@ -246,7 +247,7 @@ vec3 Lighting(vec3 F0)
for(int i = 0; i < LightCount; i++) for(int i = 0; i < LightCount; i++)
{ {
vec3 Li = -lights.Direction; vec3 Li = -lights.Direction;
vec3 Lradiance = lights.Radiance; vec3 Lradiance = lights.Radiance * lights.Multiplier;
vec3 Lh = normalize(Li + m_Params.View); vec3 Lh = normalize(Li + m_Params.View);
// Calculate angles between surface normal and various light vectors. // Calculate angles between surface normal and various light vectors.
@ -271,15 +272,15 @@ vec3 Lighting(vec3 F0)
vec3 IBL(vec3 F0, vec3 Lr) vec3 IBL(vec3 F0, vec3 Lr)
{ {
vec3 irradiance = texture(u_EnvIrradianceTex, m_Params.Normal).rgb; 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 F = fresnelSchlickR(F0, m_Params.NdotV);
vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness); vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness);
vec3 diffuseIBL = m_Params.Albedo * irradiance; vec3 diffuseIBL = m_Params.Albedo * irradiance;
int u_EnvRadianceTexLevels = textureQueryLevels(u_EnvRadianceTex); int u_EnvRadianceTexLevels = textureQueryLevels(u_EnvRadianceTex);
float NoV = clamp(m_Params.NdotV, 0.0, 1.0); 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 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 // 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; 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); vec3 iblContribution = IBL(F0, Lr);
color = vec4(lightContribution + iblContribution, 1.0); color = vec4(lightContribution + iblContribution, 1.0);
color = vec4(iblContribution, 1.0); // color = vec4(iblContribution, 1.0);
} }

View File

@ -14,6 +14,10 @@
#include "Prism/Core/Events/KeyEvent.h" #include "Prism/Core/Events/KeyEvent.h"
#include "Prism/Core/Events/MouseEvent.h" #include "Prism/Core/Events/MouseEvent.h"
#include "Prism/Core/Math/AABB.h"
#include "Prism/Core/Math/Ray.h"
// ImGui // ImGui
#include "imgui.h" #include "imgui.h"

View File

@ -15,6 +15,7 @@ namespace Prism
static bool IsMouseButtonPressed(int button); static bool IsMouseButtonPressed(int button);
static float GetMouseX(); static float GetMouseX();
static float GetMouseY(); static float GetMouseY();
static std::pair<float, float> GetMousePosition();
}; };
} }

View File

@ -129,4 +129,7 @@
#define PM_KEY_RIGHT_SUPER 347 #define PM_KEY_RIGHT_SUPER 347
#define PM_KEY_MENU 348 #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 #endif //KEYCODES_H

View File

@ -0,0 +1,25 @@
//
// Created by sfd on 25-12-2.
//
#ifndef PRISM_AABB_H
#define PRISM_AABB_H
#include <glm/glm.hpp>
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

View File

@ -0,0 +1,76 @@
//
// Created by sfd on 25-12-2.
//
#ifndef RAY_H
#define RAY_H
#include <glm/glm.hpp>
#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

View File

@ -36,8 +36,9 @@ namespace Prism
virtual void OnUpdate() = 0; virtual void OnUpdate() = 0;
virtual void SetEventCallback(const EventCallbackFn& callback) = 0; virtual void SetEventCallback(const EventCallbackFn& callback) = 0;
virtual unsigned int GetWidth() const = 0; virtual uint32_t GetWidth() const = 0;
virtual unsigned int GetHeight() const = 0; virtual uint32_t GetHeight() const = 0;
virtual std::pair<uint32_t, uint32_t> GetSize() const = 0;
virtual std::pair<float, float> GetWindowPos() const = 0; virtual std::pair<float, float> GetWindowPos() const = 0;
virtual void SetVSync(bool enable) = 0; virtual void SetVSync(bool enable) = 0;

View File

@ -132,11 +132,13 @@ namespace Prism
{ {
glm::mat4 localTransform = Mat4FromAssimpMat4(node->mTransformation); glm::mat4 localTransform = Mat4FromAssimpMat4(node->mTransformation);
glm::mat4 transform = parentTransform * localTransform; glm::mat4 transform = parentTransform * localTransform;
/*
for (uint32_t i = 0; i < node->mNumMeshes; i++) for (uint32_t i = 0; i < node->mNumMeshes; i++)
{ {
uint32_t meshIndex = node->mMeshes[i]; uint32_t meshIndex = node->mMeshes[i];
mesh->m_Submeshes[meshIndex].Transform = transform; mesh->m_Submeshes[meshIndex].Transform = transform;
} }
*/
if (ImGui::TreeNode(node->mName.C_Str())) if (ImGui::TreeNode(node->mName.C_Str()))
{ {

View File

@ -13,7 +13,7 @@ namespace Prism
OpenGLFrameBuffer::OpenGLFrameBuffer(const FramebufferSpecification& spec) OpenGLFrameBuffer::OpenGLFrameBuffer(const FramebufferSpecification& spec)
: m_Specification(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; return;
m_Specification.Width = width; m_Specification.Width = width;

View File

@ -18,7 +18,7 @@ namespace Prism
void Bind() const override; void Bind() const override;
void Unbind() 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; void BindTexture(uint32_t slot) const override;

View File

@ -71,10 +71,7 @@ namespace Prism
{ {
case GL_DEBUG_SEVERITY_HIGH: case GL_DEBUG_SEVERITY_HIGH:
PM_CORE_ERROR("[OpenGL HIGH] Source: {0}, Type: {1}, ID: {2}\nMessage: {3}", sourceStr, typeStr, id, message); 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);
{
PM_CORE_ASSERT(false, "ERROR");
}
break; break;
case GL_DEBUG_SEVERITY_MEDIUM: case GL_DEBUG_SEVERITY_MEDIUM:

View File

@ -59,7 +59,8 @@ namespace Prism
void OpenGLVertexArray::AddVertexBuffer(const Ref<VertexBuffer>& vertexBuffer) void OpenGLVertexArray::AddVertexBuffer(const Ref<VertexBuffer>& 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(); Bind();
vertexBuffer->Bind(); vertexBuffer->Bind();

View File

@ -26,23 +26,21 @@ namespace Prism
float Input::GetMouseX() float Input::GetMouseX()
{ {
const auto& window = dynamic_cast<WindowsWindow&>(Application::Get().GetWindow()); return GetMousePosition().first;
double xpos, ypos;
glfwGetCursorPos(static_cast<GLFWwindow*>(window.GetNativeWindow()), &xpos, &ypos);
return static_cast<float>(xpos);
} }
float Input::GetMouseY() float Input::GetMouseY()
{
return GetMousePosition().second;
}
std::pair<float, float> Input::GetMousePosition()
{ {
const auto& window = dynamic_cast<WindowsWindow&>(Application::Get().GetWindow()); const auto& window = dynamic_cast<WindowsWindow&>(Application::Get().GetWindow());
double xpos, ypos; double xpos, ypos;
glfwGetCursorPos(static_cast<GLFWwindow*>(window.GetNativeWindow()), &xpos, &ypos); glfwGetCursorPos(static_cast<GLFWwindow*>(window.GetNativeWindow()), &xpos, &ypos);
return static_cast<float>(ypos); return {xpos, ypos};
} }
} }

View File

@ -197,6 +197,14 @@ namespace Prism
m_ImGuiMouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); // FIXME: GLFW doesn't have this. 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_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); // FIXME: GLFW doesn't have this.
m_ImGuiMouseCursors[ImGuiMouseCursor_Hand] = glfwCreateStandardCursor(GLFW_HAND_CURSOR); 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() void WindowsWindow::Shutdown()

View File

@ -24,6 +24,7 @@ namespace Prism
inline void SetEventCallback(const EventCallbackFn& callback) override { m_Data.EventCallback = callback; } inline void SetEventCallback(const EventCallbackFn& callback) override { m_Data.EventCallback = callback; }
bool const IsVSync() const override { return m_Data.VSync; } bool const IsVSync() const override { return m_Data.VSync; }
void SetVSync(bool enable) override; void SetVSync(bool enable) override;
virtual std::pair<uint32_t, uint32_t> GetSize() const override { return { m_Data.Width, m_Data.Height }; }
virtual std::pair<float, float> GetWindowPos() const override; virtual std::pair<float, float> GetWindowPos() const override;
inline void* GetNativeWindow() const { return m_Window; } inline void* GetNativeWindow() const { return m_Window; }

View File

@ -24,14 +24,17 @@ namespace Prism
Camera::Camera(const glm::mat4& projectionMatrix) Camera::Camera(const glm::mat4& projectionMatrix)
: m_ProjectionMatrix(projectionMatrix) : m_ProjectionMatrix(projectionMatrix)
{ {
m_Position = { 0, 0, 10 };
m_Rotation = glm::vec3(90.0f, 0.0f, 0.0f); m_Rotation = glm::vec3(90.0f, 0.0f, 0.0f);
m_FocalPoint = glm::vec3(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_Yaw = 3.0f * (float)M_PI / 4.0f;
m_Pitch = M_PI / 4.0f; m_Pitch = M_PI / 4.0f;
UpdateCameraView();
} }
void Camera::Focus() void Camera::Focus()
@ -56,13 +59,7 @@ namespace Prism
MouseZoom(delta.y); MouseZoom(delta.y);
} }
m_Position = CalculatePosition(); UpdateCameraView();
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);
} }
void Camera::OnEvent(Event& e) void Camera::OnEvent(Event& e)
@ -86,6 +83,16 @@ namespace Prism
return glm::rotate(GetOrientation(), glm::vec3(0.0f, 0.0f, -1.0f)); 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) bool Camera::OnMouseScroll(MouseScrolledEvent& e)
{ {
const float delta = e.GetOffsetY() * 0.1f; const float delta = e.GetOffsetY() * 0.1f;

View File

@ -43,6 +43,8 @@ namespace Prism
public: public:
inline void SetViewportSize(const uint32_t width, const uint32_t height) { m_ViewportWidth = width; m_ViewportHeight = height; } inline void SetViewportSize(const uint32_t width, const uint32_t height) { m_ViewportWidth = width; m_ViewportHeight = height; }
private: private:
void UpdateCameraView();
bool OnMouseScroll(MouseScrolledEvent& e); bool OnMouseScroll(MouseScrolledEvent& e);
void MousePan(const glm::vec2& delta); void MousePan(const glm::vec2& delta);
void MouseRotate(const glm::vec2& delta); void MouseRotate(const glm::vec2& delta);

View File

@ -40,7 +40,7 @@ namespace Prism
virtual void Bind() const = 0; virtual void Bind() const = 0;
virtual void Unbind() 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; virtual void BindTexture(uint32_t slot = 0) const = 0;

View File

@ -20,6 +20,13 @@
namespace Prism 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 = constexpr unsigned int s_ImportFlags =
aiProcess_CalcTangentSpace | // Create binormals/tangents just in case aiProcess_CalcTangentSpace | // Create binormals/tangents just in case
aiProcess_Triangulate | // Make sure we're triangles aiProcess_Triangulate | // Make sure we're triangles
@ -104,9 +111,7 @@ namespace Prism
if (!scene || !scene->HasMeshes()) if (!scene || !scene->HasMeshes())
PM_CORE_ERROR("Failed to load mesh file: {0}", filename); PM_CORE_ERROR("Failed to load mesh file: {0}", filename);
//double factor; m_Scene = scene;
//scene->mMetaData->Get("UnitScaleFactor", factor);
//PM_CORE_INFO("FBX Scene Scale: {0}", factor);
m_IsAnimated = scene->mAnimations != nullptr; m_IsAnimated = scene->mAnimations != nullptr;
m_MeshShader = m_IsAnimated ? Renderer::GetShaderLibrary()->Get("PBRShader_Anim") : Renderer::GetShaderLibrary()->Get("PBRShader_Static"); m_MeshShader = m_IsAnimated ? Renderer::GetShaderLibrary()->Get("PBRShader_Anim") : Renderer::GetShaderLibrary()->Get("PBRShader_Static");
@ -117,16 +122,17 @@ namespace Prism
uint32_t indexCount = 0; uint32_t indexCount = 0;
m_Submeshes.reserve(scene->mNumMeshes); 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]; aiMesh* mesh = scene->mMeshes[m];
Submesh submesh; Submesh& submesh = m_Submeshes.emplace_back();
submesh.BaseVertex = vertexCount; submesh.BaseVertex = vertexCount;
submesh.BaseIndex = indexCount; submesh.BaseIndex = indexCount;
submesh.MaterialIndex = mesh->mMaterialIndex; submesh.MaterialIndex = mesh->mMaterialIndex;
submesh.IndexCount = mesh->mNumFaces * 3; submesh.IndexCount = mesh->mNumFaces * 3;
m_Submeshes.push_back(submesh); // m_Submeshes.push_back(submesh);
submesh.MeshName = mesh->mName.C_Str();
vertexCount += mesh->mNumVertices; vertexCount += mesh->mNumVertices;
indexCount += submesh.IndexCount; indexCount += submesh.IndexCount;
@ -155,8 +161,10 @@ namespace Prism
} }
}else }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++) 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.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 }; 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); aabb.Min.x = glm::min(vertex.Position.x, aabb.Min.x);
submesh.Min.y = glm::min(vertex.Position.y, submesh.Min.y); aabb.Min.y = glm::min(vertex.Position.y, aabb.Min.y);
submesh.Min.z = glm::min(vertex.Position.z, submesh.Min.z); aabb.Min.z = glm::min(vertex.Position.z, aabb.Min.z);
submesh.Max.x = glm::max(vertex.Position.x, submesh.Max.x); aabb.Max.x = glm::max(vertex.Position.x, aabb.Max.x);
submesh.Max.y = glm::max(vertex.Position.y, submesh.Max.y); aabb.Max.y = glm::max(vertex.Position.y, aabb.Max.y);
submesh.Max.z = glm::max(vertex.Position.z, submesh.Max.z); aabb.Max.z = glm::max(vertex.Position.z, aabb.Max.z);
if (mesh->HasTangentsAndBitangents()) if (mesh->HasTangentsAndBitangents())
@ -189,7 +197,11 @@ namespace Prism
for (size_t i = 0; i < mesh->mNumFaces; i++) for (size_t i = 0; i < mesh->mNumFaces; i++)
{ {
PM_CORE_ASSERT(mesh->mFaces[i].mNumIndices == 3, "Must have 3 indices."); 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 // Material
if (scene->HasMaterials()) if (scene->HasMaterials())
{ {
PM_CORE_INFO("---- Materials - {0} ----", filename);
m_Textures.resize(scene->mNumMaterials); m_Textures.resize(scene->mNumMaterials);
m_Materials.resize(scene->mNumMaterials); m_Materials.resize(scene->mNumMaterials);
for (uint32_t i = 0; i < scene->mNumMaterials; i++) for (uint32_t i = 0; i < scene->mNumMaterials; i++)
@ -248,16 +262,26 @@ namespace Prism
auto mi = CreateRef<MaterialInstance>(m_BaseMaterial); auto mi = CreateRef<MaterialInstance>(m_BaseMaterial);
m_Materials[i] = mi; 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; aiString aiTexPath;
uint32_t textureCount = aiMaterial->GetTextureCount(aiTextureType_DIFFUSE); uint32_t textureCount = aiMaterial->GetTextureCount(aiTextureType_DIFFUSE);
PM_CORE_TRACE(" TextureCount = {0}", textureCount); PM_MESH_LOG(" TextureCount = {0}", textureCount);
aiColor3D aiColor; aiColor3D aiColor;
aiMaterial->Get(AI_MATKEY_COLOR_DIFFUSE, aiColor); aiMaterial->Get(AI_MATKEY_COLOR_DIFFUSE, aiColor);
PM_CORE_TRACE("COLOR = {0}, {1}, {2}", aiColor.r, aiColor.g, aiColor.b); 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 // TODO: Temp - this should be handled by Hazel's filesystem
std::filesystem::path path = filename; std::filesystem::path path = filename;
@ -265,27 +289,25 @@ namespace Prism
parentPath /= std::string(aiTexPath.data); parentPath /= std::string(aiTexPath.data);
std::string texturePath = parentPath.string(); std::string texturePath = parentPath.string();
PM_MESH_LOG(" Albedo map path = {0}", texturePath);
auto texture = Texture2D::Create(texturePath, true); auto texture = Texture2D::Create(texturePath, true);
if (texture->Loaded()) if (texture->Loaded())
{ {
m_Textures[i] = texture; m_Textures[i] = texture;
PM_CORE_TRACE(" Texture Path = {0}", texturePath);
mi->Set("u_AlbedoTexture", m_Textures[i]); mi->Set("u_AlbedoTexture", m_Textures[i]);
mi->Set("u_AlbedoTexToggle", 1.0f); mi->Set("u_AlbedoTexToggle", 1.0f);
} }
else else
{ {
PM_CORE_ERROR("Could not load texture: {0}", texturePath); 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 }); mi->Set("u_AlbedoColor", glm::vec3{ aiColor.r, aiColor.g, aiColor.b });
} }
} }
else else
{ {
mi->Set("u_AlbedoTexToggle", 0.0f);
mi->Set("u_AlbedoColor", glm::vec3 { aiColor.r, aiColor.g, aiColor.b }); mi->Set("u_AlbedoColor", glm::vec3 { aiColor.r, aiColor.g, aiColor.b });
PM_MESH_LOG(" No albedo map");
PM_CORE_INFO("Mesh has no albedo map");
} }
// Normal Maps // Normal Maps
@ -299,21 +321,21 @@ namespace Prism
parentPath /= std::string(aiTexPath.data); parentPath /= std::string(aiTexPath.data);
std::string texturePath = parentPath.string(); std::string texturePath = parentPath.string();
PM_MESH_LOG(" Normal map path = {0}", texturePath);
auto texture = Texture2D::Create(texturePath); auto texture = Texture2D::Create(texturePath);
if (texture->Loaded()) if (texture->Loaded())
{ {
PM_CORE_TRACE(" Normal map path = {0}", texturePath);
mi->Set("u_NormalTexture", texture); mi->Set("u_NormalTexture", texture);
mi->Set("u_NormalTexToggle", 1.0f); mi->Set("u_NormalTexToggle", 1.0f);
} }
else else
{ {
PM_CORE_ERROR("Could not load texture: {0}", texturePath); PM_CORE_ERROR(" Could not load texture: {0}", texturePath);
} }
} }
else else
{ {
PM_CORE_TRACE("Mesh has no normal map"); PM_MESH_LOG(" no normal map");
} }
// Roughness map // Roughness map
@ -327,6 +349,7 @@ namespace Prism
parentPath /= std::string(aiTexPath.data); parentPath /= std::string(aiTexPath.data);
std::string texturePath = parentPath.string(); std::string texturePath = parentPath.string();
PM_MESH_LOG(" Roughness map path = {0}", texturePath);
auto texture = Texture2D::Create(texturePath); auto texture = Texture2D::Create(texturePath);
if (texture->Loaded()) if (texture->Loaded())
{ {
@ -336,14 +359,17 @@ namespace Prism
} }
else else
{ {
PM_CORE_ERROR("Could not load texture: {0}", texturePath); PM_CORE_ERROR(" Could not load texture: {0}", texturePath);
} }
} }
else else
{ {
PM_CORE_TRACE("Mesh has no roughness texture"); PM_MESH_LOG(" no roughness texture");
mi->Set("u_Roughness", roughness);
} }
#if 0
// Metalness map // Metalness map
// mi->Set("u_Metalness", 0.0f); // mi->Set("u_Metalness", 0.0f);
// mi->Set("u_MetalnessTexToggle", 0.0f); // mi->Set("u_MetalnessTexToggle", 0.0f);
@ -358,7 +384,7 @@ namespace Prism
auto texture = Texture2D::Create(texturePath); auto texture = Texture2D::Create(texturePath);
if (texture->Loaded()) 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_MetalnessTexture", texture);
mi->Set("u_MetalnessTexToggle", 1.0f); mi->Set("u_MetalnessTexToggle", 1.0f);
} }
@ -369,169 +395,82 @@ namespace Prism
} }
else else
{ {
PM_CORE_TRACE("Mesh has no metalness texture"); PM_MESH_LOG(" no metalness texture");
mi->Set("u_Metalness", metalness);
} }
continue; continue;
#endif
bool metalnessTextureFound = false;
for (uint32_t i = 0; i < aiMaterial->mNumProperties; i++) for (uint32_t i = 0; i < aiMaterial->mNumProperties; i++)
{ {
auto prop = aiMaterial->mProperties[i]; auto prop = aiMaterial->mProperties[i];
PM_CORE_TRACE("Material Property:"); PM_CORE_TRACE("Material Property:");
PM_CORE_TRACE(" Name = {0}", prop->mKey.data); PM_CORE_TRACE(" Name = {0}", prop->mKey.data);
float data = *(float*)prop->mData;
PM_MESH_LOG(" Value = {0}", data);
switch (prop->mSemantic) switch (prop->mSemantic)
{ {
case aiTextureType_NONE: case aiTextureType_NONE: PM_MESH_LOG(" Semantic = aiTextureType_NONE"); break;
PM_CORE_TRACE(" Semantic = aiTextureType_NONE"); case aiTextureType_DIFFUSE: PM_MESH_LOG(" Semantic = aiTextureType_DIFFUSE"); break;
break; case aiTextureType_SPECULAR: PM_MESH_LOG(" Semantic = aiTextureType_SPECULAR"); break;
case aiTextureType_DIFFUSE: case aiTextureType_AMBIENT: PM_MESH_LOG(" Semantic = aiTextureType_AMBIENT"); break;
PM_CORE_TRACE(" Semantic = aiTextureType_DIFFUSE"); case aiTextureType_EMISSIVE: PM_MESH_LOG(" Semantic = aiTextureType_EMISSIVE"); break;
break; case aiTextureType_HEIGHT: PM_MESH_LOG(" Semantic = aiTextureType_HEIGHT"); break;
case aiTextureType_SPECULAR: case aiTextureType_NORMALS: PM_MESH_LOG(" Semantic = aiTextureType_NORMALS"); break;
PM_CORE_TRACE(" Semantic = aiTextureType_SPECULAR"); case aiTextureType_SHININESS: PM_MESH_LOG(" Semantic = aiTextureType_SHININESS"); break;
break; case aiTextureType_OPACITY: PM_MESH_LOG(" Semantic = aiTextureType_OPACITY"); break;
case aiTextureType_AMBIENT: case aiTextureType_DISPLACEMENT:PM_MESH_LOG(" Semantic = aiTextureType_DISPLACEMENT"); break;
PM_CORE_TRACE(" Semantic = aiTextureType_AMBIENT"); case aiTextureType_LIGHTMAP: PM_MESH_LOG(" Semantic = aiTextureType_LIGHTMAP"); break;
break; case aiTextureType_REFLECTION: PM_MESH_LOG(" Semantic = aiTextureType_REFLECTION"); break;
case aiTextureType_EMISSIVE: case aiTextureType_UNKNOWN: PM_MESH_LOG(" Semantic = aiTextureType_UNKNOWN"); break;
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;
} }
if (prop->mType == aiPTI_String) if (prop->mType == aiPTI_String)
{ {
uint32_t strLength = *(uint32_t*)prop->mData; uint32_t strLength = *(uint32_t*)prop->mData;
std::string str(prop->mData + 4, strLength); std::string str(prop->mData + 4, strLength);
PM_CORE_TRACE(" Value = {0}", str);
std::string key = prop->mKey.data; std::string key = prop->mKey.data;
if (key == "$raw.ReflectionFactor|file") if (key == "$raw.ReflectionFactor|file")
{ {
metalnessTextureFound = true;
// TODO: Temp - this should be handled by Hazel's filesystem // TODO: Temp - this should be handled by Hazel's filesystem
std::filesystem::path path = filename; std::filesystem::path path = filename;
auto parentPath = path.parent_path(); auto parentPath = path.parent_path();
parentPath /= str; parentPath /= str;
std::string texturePath = parentPath.string(); std::string texturePath = parentPath.string();
PM_MESH_LOG(" Metalness map path = {0}", texturePath);
auto texture = Texture2D::Create(texturePath); auto texture = Texture2D::Create(texturePath);
if (texture->Loaded()) if (texture->Loaded())
{ {
PM_CORE_TRACE(" Metalness map path = {0}", texturePath);
mi->Set("u_MetalnessTexture", texture); mi->Set("u_MetalnessTexture", texture);
mi->Set("u_MetalnessTexToggle", 1.0f); mi->Set("u_MetalnessTexToggle", 1.0f);
} }
else else
{ {
PM_CORE_ERROR("Could not load texture: {0}", texturePath); PM_CORE_ERROR(" Could not load texture: {0}", texturePath);
mi->Set("u_Metalness", 0.5f); mi->Set("u_Metalness", metalness);
mi->Set("u_MetalnessTexToggle", 1.0f); mi->Set("u_MetalnessTexToggle", 0.0f);
} }
break;
} }
} }
} }
if (!metalnessTextureFound)
{
PM_MESH_LOG(" No metalness map");
/* mi->Set("u_Metalness", metalness);
// Normal maps mi->Set("u_MetalnessTexToggle", 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);
//mi->Set("u_AlbedoTexToggle", 0.0f);
// mi->Set("u_AlbedoColor", glm::vec3{ color.r, color.g, color.b });
} }
} }
PM_MESH_LOG("------------------------");
// 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);
}
}
*/
}
} }
m_VertexArray = VertexArray::Create(); m_VertexArray = VertexArray::Create();
@ -564,7 +503,6 @@ namespace Prism
auto ib = IndexBuffer::Create(m_Indices.data(), (uint32_t)m_Indices.size() * sizeof(Index)); auto ib = IndexBuffer::Create(m_Indices.data(), (uint32_t)m_Indices.size() * sizeof(Index));
m_VertexArray->SetIndexBuffer(ib); m_VertexArray->SetIndexBuffer(ib);
m_Scene = scene;
} }
Mesh::~Mesh() = default; Mesh::~Mesh() = default;
@ -591,37 +529,37 @@ namespace Prism
void Mesh::DumpVertexBuffer() void Mesh::DumpVertexBuffer()
{ {
// TODO: Convert to ImGui // TODO: Convert to ImGui
PM_CORE_TRACE("------------------------------------------------------"); PM_MESH_LOG("------------------------------------------------------");
PM_CORE_TRACE("Vertex Buffer Dump"); PM_MESH_LOG("Vertex Buffer Dump");
PM_CORE_TRACE("Mesh: {0}", m_FilePath); PM_MESH_LOG("Mesh: {0}", m_FilePath);
if (m_IsAnimated) if (m_IsAnimated)
{ {
for (size_t i = 0; i < m_AnimatedVertices.size(); i++) for (size_t i = 0; i < m_AnimatedVertices.size(); i++)
{ {
auto& vertex = m_AnimatedVertices[i]; auto& vertex = m_AnimatedVertices[i];
PM_CORE_TRACE("Vertex: {0}", i); PM_MESH_LOG("Vertex: {0}", i);
PM_CORE_TRACE("Position: {0}, {1}, {2}", vertex.Position.x, vertex.Position.y, vertex.Position.z); PM_MESH_LOG("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_MESH_LOG("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_MESH_LOG("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_MESH_LOG("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_MESH_LOG("TexCoord: {0}, {1}", vertex.Texcoord.x, vertex.Texcoord.y);
PM_CORE_TRACE("--"); PM_MESH_LOG("--");
} }
}else }else
{ {
for (size_t i = 0; i < m_StaticVertices.size(); i++) for (size_t i = 0; i < m_StaticVertices.size(); i++)
{ {
auto& vertex = m_StaticVertices[i]; auto& vertex = m_StaticVertices[i];
PM_CORE_TRACE("Vertex: {0}", i); PM_MESH_LOG("Vertex: {0}", i);
PM_CORE_TRACE("Position: {0}, {1}, {2}", vertex.Position.x, vertex.Position.y, vertex.Position.z); PM_MESH_LOG("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_MESH_LOG("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_MESH_LOG("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_MESH_LOG("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_MESH_LOG("TexCoord: {0}, {1}", vertex.Texcoord.x, vertex.Texcoord.y);
PM_CORE_TRACE("--"); PM_MESH_LOG("--");
} }
} }
PM_CORE_TRACE("------------------------------------------------------"); PM_MESH_LOG("------------------------------------------------------");
} }
void Mesh::BoneTransform(float time) void Mesh::BoneTransform(float time)
@ -679,7 +617,9 @@ namespace Prism
for (uint32_t i = 0; i < node->mNumMeshes; i++) for (uint32_t i = 0; i < node->mNumMeshes; i++)
{ {
const uint32_t mesh = node->mMeshes[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++) for (uint32_t i = 0; i < node->mNumChildren; i++)

View File

@ -7,11 +7,11 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include "Buffer.h"
#include "Material.h" #include "Material.h"
#include "Shader.h" #include "Shader.h"
#include "VertexArray.h" #include "VertexArray.h"
#include "Prism/Core/TimeStep.h" #include "Prism/Core/TimeStep.h"
#include "Prism/Core/Math/AABB.h"
struct aiNode; struct aiNode;
struct aiAnimation; struct aiAnimation;
@ -78,6 +78,14 @@ namespace Prism
void AddBoneData(uint32_t BoneID, float Weight); 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 class Submesh
{ {
public: public:
@ -87,7 +95,9 @@ namespace Prism
uint32_t IndexCount; uint32_t IndexCount;
glm::mat4 Transform; glm::mat4 Transform;
glm::vec3 Min, Max; //TODO: AABB AABB BoundingBox;
std::string NodeName, MeshName;
}; };
class PRISM_API Mesh class PRISM_API Mesh
@ -101,11 +111,16 @@ namespace Prism
void OnUpdate(TimeStep deltaTime); void OnUpdate(TimeStep deltaTime);
void DumpVertexBuffer(); void DumpVertexBuffer();
std::vector<Submesh>& GetSubmeshes() { return m_Submeshes; }
const std::vector<Submesh>& GetSubmeshes() const { return m_Submeshes; }
inline Ref<Shader> GetMeshShader() { return m_MeshShader; } inline Ref<Shader> GetMeshShader() { return m_MeshShader; }
inline Ref<Material> GetMaterial() { return m_BaseMaterial; } inline Ref<Material> GetMaterial() { return m_BaseMaterial; }
std::vector<Ref<MaterialInstance>> GetMaterials() { return m_Materials; } std::vector<Ref<MaterialInstance>> GetMaterials() { return m_Materials; }
const std::vector<Ref<Texture2D>>& GetTextures() const { return m_Textures; } const std::vector<Ref<Texture2D>>& GetTextures() const { return m_Textures; }
const std::string& GetFilePath() const { return m_FilePath; } const std::string& GetFilePath() const { return m_FilePath; }
const std::vector<Triangle> GetTriangleCache(uint32_t index) const { return m_TriangleCache.at(index); }
private: private:
void BoneTransform(float time); void BoneTransform(float time);
void ReadNodeHierarchy(float AnimationTime, const aiNode* pNode, const glm::mat4& ParentTransform); void ReadNodeHierarchy(float AnimationTime, const aiNode* pNode, const glm::mat4& ParentTransform);
@ -146,6 +161,8 @@ namespace Prism
std::vector<Ref<Texture2D>> m_NormalMaps; std::vector<Ref<Texture2D>> m_NormalMaps;
std::vector<Ref<MaterialInstance>> m_Materials; std::vector<Ref<MaterialInstance>> m_Materials;
std::unordered_map<uint32_t, std::vector<Triangle>> m_TriangleCache;
// Animation // Animation
bool m_IsAnimated = false; bool m_IsAnimated = false;
float m_AnimationTime = 0.0f; float m_AnimationTime = 0.0f;

View File

@ -195,23 +195,32 @@ namespace Prism
} }
} }
void Renderer::DrawAABB(const Ref<Mesh>& mesh, const glm::vec4& color) void Renderer::DrawAABB(const Ref<Mesh>& 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 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] = const glm::vec4 corners[8] =
{ {
transform * glm::vec4 { submesh.Min.x, submesh.Min.y, submesh.Max.z, 1.0f }, transform * glm::vec4 { aabb.Min.x, aabb.Min.y, aabb.Max.z, 1.0f },
transform * glm::vec4 { submesh.Min.x, submesh.Max.y, submesh.Max.z, 1.0f }, transform * glm::vec4 { aabb.Min.x, aabb.Max.y, aabb.Max.z, 1.0f },
transform * glm::vec4 { submesh.Max.x, submesh.Max.y, submesh.Max.z, 1.0f }, transform * glm::vec4 { aabb.Max.x, aabb.Max.y, aabb.Max.z, 1.0f },
transform * glm::vec4 { submesh.Max.x, submesh.Min.y, submesh.Max.z, 1.0f }, transform * glm::vec4 { aabb.Max.x, aabb.Min.y, aabb.Max.z, 1.0f },
transform * glm::vec4 { submesh.Min.x, submesh.Min.y, submesh.Min.z, 1.0f }, transform * glm::vec4 { aabb.Min.x, aabb.Min.y, aabb.Min.z, 1.0f },
transform * glm::vec4 { submesh.Min.x, submesh.Max.y, submesh.Min.z, 1.0f }, transform * glm::vec4 { aabb.Min.x, aabb.Max.y, aabb.Min.z, 1.0f },
transform * glm::vec4 { submesh.Max.x, submesh.Max.y, submesh.Min.z, 1.0f }, transform * glm::vec4 { aabb.Max.x, aabb.Max.y, aabb.Min.z, 1.0f },
transform * glm::vec4 { submesh.Max.x, submesh.Min.y, submesh.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++) for (uint32_t i = 0; i < 4; i++)
@ -223,7 +232,6 @@ namespace Prism
for (uint32_t i = 0; i < 4; i++) for (uint32_t i = 0; i < 4; i++)
Renderer2D::DrawLine(corners[i], corners[i + 4], color); Renderer2D::DrawLine(corners[i], corners[i + 4], color);
} }
}
RenderCommandQueue& Renderer::GetRenderCommandQueue() RenderCommandQueue& Renderer::GetRenderCommandQueue()
{ {

View File

@ -56,7 +56,8 @@ namespace Prism
static void SubmitFullscreenQuad(const Ref<MaterialInstance>& material); static void SubmitFullscreenQuad(const Ref<MaterialInstance>& material);
static void SubmitMesh(const Ref<Mesh>& mesh, const glm::mat4& transform, const Ref<MaterialInstance>& overrideMaterial = nullptr); static void SubmitMesh(const Ref<Mesh>& mesh, const glm::mat4& transform, const Ref<MaterialInstance>& overrideMaterial = nullptr);
static void DrawAABB(const Ref<Mesh>& 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>& mesh,const glm::mat4& transform, const glm::vec4& color = glm::vec4(1.0f));
private: private:
static RenderCommandQueue& GetRenderCommandQueue(); static RenderCommandQueue& GetRenderCommandQueue();
}; };

View File

@ -194,7 +194,7 @@ namespace Prism
s_Data.LineShader->SetMat4("u_ViewProjection", s_Data.CameraViewProj); s_Data.LineShader->SetMat4("u_ViewProjection", s_Data.CameraViewProj);
s_Data.LineVertexArray->Bind(); s_Data.LineVertexArray->Bind();
Renderer::SetLineThickness(2.0f); Renderer::SetLineThickness(1.0f);
Renderer::DrawIndexed(s_Data.LineIndexCount, PrimitiveType::Lines, s_Data.DepthTest); Renderer::DrawIndexed(s_Data.LineIndexCount, PrimitiveType::Lines, s_Data.DepthTest);
s_Data.Stats.DrawCalls++; s_Data.Stats.DrawCalls++;
} }

View File

@ -25,6 +25,7 @@ namespace Prism
// Resources // Resources
Ref<MaterialInstance> SkyboxMaterial; Ref<MaterialInstance> SkyboxMaterial;
Environment SceneEnvironment; Environment SceneEnvironment;
Light ActiveLight;
} SceneData; } SceneData;
Ref<Texture2D> BRDFLUT; Ref<Texture2D> BRDFLUT;
@ -101,6 +102,7 @@ namespace Prism
s_Data.SceneData.SceneCamera = scene->m_Camera; s_Data.SceneData.SceneCamera = scene->m_Camera;
s_Data.SceneData.SkyboxMaterial = scene->m_SkyboxMaterial; s_Data.SceneData.SkyboxMaterial = scene->m_SkyboxMaterial;
s_Data.SceneData.SceneEnvironment = scene->m_Environment; s_Data.SceneData.SceneEnvironment = scene->m_Environment;
s_Data.SceneData.ActiveLight = scene->m_Light;
} }
void SceneRenderer::EndScene() void SceneRenderer::EndScene()
@ -128,8 +130,8 @@ namespace Prism
std::pair<Ref<TextureCube>, Ref<TextureCube>> SceneRenderer::CreateEnvironmentMap(const std::string& filepath) std::pair<Ref<TextureCube>, Ref<TextureCube>> SceneRenderer::CreateEnvironmentMap(const std::string& filepath)
{ {
const uint32_t cubemapSize = 2048; constexpr uint32_t cubemapSize = 2048;
const uint32_t irradianceMapSize = 32; constexpr uint32_t irradianceMapSize = 32;
Ref<TextureCube> envUnfiltered = TextureCube::Create(TextureFormat::Float16, cubemapSize, cubemapSize); Ref<TextureCube> envUnfiltered = TextureCube::Create(TextureFormat::Float16, cubemapSize, cubemapSize);
if (!equirectangularConversionShader) if (!equirectangularConversionShader)
@ -245,6 +247,9 @@ namespace Prism
baseMaterial->Set("u_EnvIrradianceTex", s_Data.SceneData.SceneEnvironment.IrradianceMap); baseMaterial->Set("u_EnvIrradianceTex", s_Data.SceneData.SceneEnvironment.IrradianceMap);
baseMaterial->Set("u_BRDFLUTTexture", s_Data.BRDFLUT); 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; auto overrideMaterial = nullptr; // dc.Material;
Renderer::SubmitMesh(dc.mesh, dc.Transform, overrideMaterial); Renderer::SubmitMesh(dc.mesh, dc.Transform, overrideMaterial);
} }
@ -261,7 +266,7 @@ namespace Prism
{ {
Renderer2D::BeginScene(viewProjection); Renderer2D::BeginScene(viewProjection);
for (auto& dc : s_Data.DrawList) for (auto& dc : s_Data.DrawList)
Renderer::DrawAABB(dc.mesh); Renderer::DrawAABB(dc.mesh, dc.Transform);
Renderer2D::EndScene(); Renderer2D::EndScene();
} }

View File

@ -21,6 +21,14 @@ namespace Prism
static Environment Load(const std::string& filepath); static Environment Load(const std::string& filepath);
}; };
struct Light
{
glm::vec3 Direction;
glm::vec3 Radiance;
float Multiplier = 1.0f;
};
class PRISM_API Scene{ class PRISM_API Scene{
public: public:
Scene(const std::string& debugName = "Scene"); Scene(const std::string& debugName = "Scene");
@ -37,6 +45,7 @@ namespace Prism
void SetEnvironment(const Environment& environment); void SetEnvironment(const Environment& environment);
void SetSkybox(const Ref<TextureCube>& skybox); void SetSkybox(const Ref<TextureCube>& skybox);
Light& GetLight() { return m_Light; }
float& GetSkyboxLod() { return m_SkyboxLod; } float& GetSkyboxLod() { return m_SkyboxLod; }
void AddEntity(Entity* entity); void AddEntity(Entity* entity);
@ -47,12 +56,16 @@ namespace Prism
std::vector<Entity*> m_Entities; std::vector<Entity*> m_Entities;
Camera m_Camera; Camera m_Camera;
Light m_Light;
float m_LightMultiplier = 0.3f;
Environment m_Environment; Environment m_Environment;
Ref<TextureCube> m_SkyboxTexture; Ref<TextureCube> m_SkyboxTexture;
Ref<MaterialInstance> m_SkyboxMaterial; Ref<MaterialInstance> m_SkyboxMaterial;
float m_SkyboxLod = 1.0f; float m_SkyboxLod = 1.0f;
private:
friend class SceneRenderer; friend class SceneRenderer;
friend class SceneHierarchyPanel; friend class SceneHierarchyPanel;
}; };