add directional light component and skylight component, add PCSS and hard shadow
This commit is contained in:
@ -161,7 +161,7 @@ namespace Prism
|
|||||||
}
|
}
|
||||||
|
|
||||||
EditorLayer::EditorLayer()
|
EditorLayer::EditorLayer()
|
||||||
: m_SceneType(SceneType::Model), m_EditorCamera(glm::perspectiveFov(glm::radians(45.0f), 1280.0f, 720.0f, 0.1f, 10000.0f))
|
: m_SceneType(SceneType::Model), m_EditorCamera(glm::perspectiveFov(glm::radians(45.0f), 1280.0f, 720.0f, 0.1f, 1000.0f))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,12 +175,12 @@ namespace Prism
|
|||||||
m_CheckerboardTex = Texture2D::Create("assets/editor/Checkerboard.tga");
|
m_CheckerboardTex = Texture2D::Create("assets/editor/Checkerboard.tga");
|
||||||
m_PlayButtonTex = Texture2D::Create("assets/editor/PlayButton.png");
|
m_PlayButtonTex = Texture2D::Create("assets/editor/PlayButton.png");
|
||||||
|
|
||||||
m_EditorScene = Ref<Scene>::Create("untitled Scene", true);
|
|
||||||
ScriptEngine::SetSceneContext(m_EditorScene);
|
|
||||||
m_SceneHierarchyPanel = CreateScope<SceneHierarchyPanel>(m_EditorScene);
|
m_SceneHierarchyPanel = CreateScope<SceneHierarchyPanel>(m_EditorScene);
|
||||||
m_SceneHierarchyPanel->SetSelectionChangedCallback(std::bind(&EditorLayer::SelectEntity, this, std::placeholders::_1));
|
m_SceneHierarchyPanel->SetSelectionChangedCallback(std::bind(&EditorLayer::SelectEntity, this, std::placeholders::_1));
|
||||||
m_SceneHierarchyPanel->SetEntityDeletedCallback(std::bind(&EditorLayer::OnEntityDeleted, this, std::placeholders::_1));
|
m_SceneHierarchyPanel->SetEntityDeletedCallback(std::bind(&EditorLayer::OnEntityDeleted, this, std::placeholders::_1));
|
||||||
UpdateWindowTitle("untitled Scene");
|
UpdateWindowTitle("untitled Scene");
|
||||||
|
|
||||||
|
OpenScene("assets/scenes/FPSDemo.scene");
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorLayer::OnDetach()
|
void EditorLayer::OnDetach()
|
||||||
@ -190,6 +190,10 @@ namespace Prism
|
|||||||
|
|
||||||
void EditorLayer::OnUpdate(const TimeStep deltaTime)
|
void EditorLayer::OnUpdate(const TimeStep deltaTime)
|
||||||
{
|
{
|
||||||
|
auto [x, y] = GetMouseViewportSpace();
|
||||||
|
|
||||||
|
SceneRenderer::SetFocusPoint({ x * 0.5f + 0.5f, y * 0.5f + 0.5f });
|
||||||
|
|
||||||
switch (m_SceneState)
|
switch (m_SceneState)
|
||||||
{
|
{
|
||||||
case SceneState::Edit:
|
case SceneState::Edit:
|
||||||
@ -330,9 +334,11 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
if (ImGui::BeginMenu("file"))
|
if (ImGui::BeginMenu("file"))
|
||||||
{
|
{
|
||||||
if (ImGui::MenuItem("New Scene"))
|
if (ImGui::MenuItem("New Scene", "Ctrl+N"))
|
||||||
{
|
{
|
||||||
|
NewScene();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::MenuItem("Open Scene...", "Ctrl+O"))
|
if (ImGui::MenuItem("Open Scene...", "Ctrl+O"))
|
||||||
{
|
{
|
||||||
OpenScene();
|
OpenScene();
|
||||||
@ -390,6 +396,8 @@ namespace Prism
|
|||||||
|
|
||||||
m_SceneHierarchyPanel->OnImGuiRender();
|
m_SceneHierarchyPanel->OnImGuiRender();
|
||||||
PhysicsSettingsWindow::OnImGuiRender(m_ShowPhysicsSettings);
|
PhysicsSettingsWindow::OnImGuiRender(m_ShowPhysicsSettings);
|
||||||
|
SceneRenderer::OnImGuiRender();
|
||||||
|
// m_EditorCamera.OnImGuiRender();
|
||||||
|
|
||||||
ImGui::Begin("Materials");
|
ImGui::Begin("Materials");
|
||||||
|
|
||||||
@ -475,6 +483,7 @@ namespace Prism
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
// Normals
|
// Normals
|
||||||
|
|
||||||
if (ImGui::CollapsingHeader("Normals", nullptr, ImGuiTreeNodeFlags_DefaultOpen))
|
if (ImGui::CollapsingHeader("Normals", nullptr, ImGuiTreeNodeFlags_DefaultOpen))
|
||||||
{
|
{
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(10, 10));
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(10, 10));
|
||||||
@ -606,13 +615,6 @@ namespace Prism
|
|||||||
ImGui::Begin("Model");
|
ImGui::Begin("Model");
|
||||||
ImGui::Begin("Environment");
|
ImGui::Begin("Environment");
|
||||||
|
|
||||||
if (ImGui::Button("Load Environment Map"))
|
|
||||||
{
|
|
||||||
std::string filename = Application::Get().OpenFile("*.hdr");
|
|
||||||
if (!filename.empty())
|
|
||||||
m_EditorScene->SetEnvironment(Environment::Load(filename));
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::SliderFloat("Skybox LOD", &m_EditorScene->GetSkyboxLod(), 0.0f, 11.0f);
|
ImGui::SliderFloat("Skybox LOD", &m_EditorScene->GetSkyboxLod(), 0.0f, 11.0f);
|
||||||
|
|
||||||
|
|
||||||
@ -623,7 +625,6 @@ namespace Prism
|
|||||||
Property("Light Direction", light.Direction, PropertyFlag::SliderProperty);
|
Property("Light Direction", light.Direction, PropertyFlag::SliderProperty);
|
||||||
Property("Light Radiance", light.Radiance, PropertyFlag::ColorProperty);
|
Property("Light Radiance", light.Radiance, PropertyFlag::ColorProperty);
|
||||||
Property("Light Multiplier", light.Multiplier, 0.0f, 5.0f, PropertyFlag::SliderProperty);
|
Property("Light Multiplier", light.Multiplier, 0.0f, 5.0f, PropertyFlag::SliderProperty);
|
||||||
Property("Exposure", m_EditorCamera.GetExposure(), 0.0f, 5.0f, PropertyFlag::SliderProperty);
|
|
||||||
|
|
||||||
Property("Radiance Prefiltering", m_RadiancePrefilter);
|
Property("Radiance Prefiltering", m_RadiancePrefilter);
|
||||||
Property("Env Map Rotation", m_EnvMapRotation, -360.0f, 360.0f, PropertyFlag::SliderProperty);
|
Property("Env Map Rotation", m_EnvMapRotation, -360.0f, 360.0f, PropertyFlag::SliderProperty);
|
||||||
@ -758,7 +759,7 @@ namespace Prism
|
|||||||
m_EditorScene->SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
|
m_EditorScene->SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
|
||||||
if (m_RuntimeScene)
|
if (m_RuntimeScene)
|
||||||
m_RuntimeScene->SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
|
m_RuntimeScene->SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
|
||||||
m_EditorCamera.SetProjectionMatrix(glm::perspectiveFov(glm::radians(45.0f), viewportSize.x, viewportSize.y, 0.1f, 10000.0f));
|
m_EditorCamera.SetProjectionMatrix(glm::perspectiveFov(glm::radians(45.0f), viewportSize.x, viewportSize.y, 0.1f, 1000.0f));
|
||||||
m_EditorCamera.SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
|
m_EditorCamera.SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
|
||||||
ImGui::Image((ImTextureRef)SceneRenderer::GetFinalColorBufferRendererID(), viewportSize, { 0, 1 }, { 1, 0 });
|
ImGui::Image((ImTextureRef)SceneRenderer::GetFinalColorBufferRendererID(), viewportSize, { 0, 1 }, { 1, 0 });
|
||||||
|
|
||||||
@ -846,7 +847,7 @@ namespace Prism
|
|||||||
|
|
||||||
bool EditorLayer::OnKeyPressedEvent(KeyPressedEvent& e)
|
bool EditorLayer::OnKeyPressedEvent(KeyPressedEvent& e)
|
||||||
{
|
{
|
||||||
if (m_ViewportPanelFocused)
|
if (m_ViewportPanelHovered)
|
||||||
{
|
{
|
||||||
switch (e.GetKeyCode())
|
switch (e.GetKeyCode())
|
||||||
{
|
{
|
||||||
@ -862,6 +863,11 @@ namespace Prism
|
|||||||
case KeyCode::R:
|
case KeyCode::R:
|
||||||
m_GizmoType = ImGuizmo::OPERATION::SCALE;
|
m_GizmoType = ImGuizmo::OPERATION::SCALE;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (e.GetKeyCode())
|
||||||
|
{
|
||||||
case KeyCode::DELETE:
|
case KeyCode::DELETE:
|
||||||
if (m_SelectionContext.size())
|
if (m_SelectionContext.size())
|
||||||
{
|
{
|
||||||
@ -873,7 +879,6 @@ namespace Prism
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (Input::IsKeyPressed(KeyCode::LEFT_CONTROL))
|
if (Input::IsKeyPressed(KeyCode::LEFT_CONTROL))
|
||||||
{
|
{
|
||||||
@ -888,7 +893,9 @@ namespace Prism
|
|||||||
case KeyCode::S:
|
case KeyCode::S:
|
||||||
SaveScene();
|
SaveScene();
|
||||||
break;
|
break;
|
||||||
|
case KeyCode::N:
|
||||||
|
NewScene();
|
||||||
|
break;
|
||||||
case KeyCode::B:
|
case KeyCode::B:
|
||||||
// Toggle bounding boxes
|
// Toggle bounding boxes
|
||||||
m_UIShowBoundingBoxes = !m_UIShowBoundingBoxes;
|
m_UIShowBoundingBoxes = !m_UIShowBoundingBoxes;
|
||||||
@ -998,10 +1005,8 @@ namespace Prism
|
|||||||
SelectedSubmesh selection;
|
SelectedSubmesh selection;
|
||||||
if (entity.HasComponent<MeshComponent>())
|
if (entity.HasComponent<MeshComponent>())
|
||||||
{
|
{
|
||||||
if (auto& meshComp = entity.GetComponent<MeshComponent>(); meshComp.Mesh)
|
if (auto mesh = entity.GetComponent<MeshComponent>().Mesh)
|
||||||
{
|
selection.Mesh = &mesh->GetSubmeshes()[0];
|
||||||
selection.Mesh = &meshComp.Mesh->GetSubmeshes()[0];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
selection.Entity = entity;
|
selection.Entity = entity;
|
||||||
m_SelectionContext.clear();
|
m_SelectionContext.clear();
|
||||||
@ -1068,34 +1073,57 @@ namespace Prism
|
|||||||
return Ray::Zero();
|
return Ray::Zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditorLayer::NewScene()
|
||||||
|
{
|
||||||
|
m_EditorScene = Ref<Scene>::Create("Untitled Scene", true);
|
||||||
|
m_SceneHierarchyPanel->SetContext(m_EditorScene);
|
||||||
|
ScriptEngine::SetSceneContext(m_EditorScene);
|
||||||
|
UpdateWindowTitle("Untitled Scene");
|
||||||
|
m_SceneFilePath = std::string();
|
||||||
|
|
||||||
|
m_EditorCamera = EditorCamera(glm::perspectiveFov(glm::radians(45.0f), 1280.0f, 720.0f, 0.1f, 1000.0f));
|
||||||
|
m_SelectionContext.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void EditorLayer::OpenScene()
|
void EditorLayer::OpenScene()
|
||||||
{
|
{
|
||||||
const auto& app = Application::Get();
|
const auto& app = Application::Get();
|
||||||
const std::string filepath = app.OpenFile("Prism Scene (*.hsc)\0*.hsc\0");
|
const std::string filepath = app.OpenFile("Hazel Scene (*.hsc)\0*.hsc\0");
|
||||||
if (!filepath.empty())
|
if (!filepath.empty())
|
||||||
|
OpenScene(filepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorLayer::OpenScene(const std::string& filepath)
|
||||||
{
|
{
|
||||||
const Ref<Scene> newScene = Ref<Scene>::Create("EditorScene", true);
|
const std::string fileName = std::filesystem::path(filepath).filename().string();
|
||||||
|
UpdateWindowTitle(fileName);
|
||||||
|
|
||||||
|
const Ref<Scene> newScene = Ref<Scene>::Create(fileName, true);
|
||||||
SceneSerializer serializer(newScene);
|
SceneSerializer serializer(newScene);
|
||||||
serializer.Deserialize(filepath);
|
serializer.Deserialize(filepath);
|
||||||
m_EditorScene = newScene;
|
m_EditorScene = newScene;
|
||||||
const std::filesystem::path path = filepath;
|
m_SceneFilePath = filepath;
|
||||||
UpdateWindowTitle(path.filename().string());
|
|
||||||
m_SceneHierarchyPanel->SetContext(m_EditorScene);
|
m_SceneHierarchyPanel->SetContext(m_EditorScene);
|
||||||
ScriptEngine::SetSceneContext(m_EditorScene);
|
ScriptEngine::SetSceneContext(m_EditorScene);
|
||||||
|
|
||||||
m_EditorScene->SetSelectedEntity({});
|
m_EditorScene->SetSelectedEntity({});
|
||||||
m_SelectionContext.clear();
|
m_SelectionContext.clear();
|
||||||
|
|
||||||
m_SceneFilePath = filepath;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorLayer::SaveScene()
|
void EditorLayer::SaveScene()
|
||||||
|
{
|
||||||
|
if (!m_SceneFilePath.empty())
|
||||||
{
|
{
|
||||||
PM_CLIENT_INFO("Saving scene to: {0}", m_SceneFilePath);
|
PM_CLIENT_INFO("Saving scene to: {0}", m_SceneFilePath);
|
||||||
SceneSerializer serializer(m_EditorScene);
|
SceneSerializer serializer(m_EditorScene);
|
||||||
serializer.Serialize(m_SceneFilePath);
|
serializer.Serialize(m_SceneFilePath);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SaveSceneAs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EditorLayer::SaveSceneAs()
|
void EditorLayer::SaveSceneAs()
|
||||||
{
|
{
|
||||||
@ -1110,6 +1138,9 @@ namespace Prism
|
|||||||
std::filesystem::path path = filepath;
|
std::filesystem::path path = filepath;
|
||||||
UpdateWindowTitle(path.filename().string());
|
UpdateWindowTitle(path.filename().string());
|
||||||
m_SceneFilePath = filepath;
|
m_SceneFilePath = filepath;
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
PM_CLIENT_INFO("cancelled");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1140,8 +1171,6 @@ namespace Prism
|
|||||||
m_SelectionContext.clear();
|
m_SelectionContext.clear();
|
||||||
ScriptEngine::SetSceneContext(m_EditorScene);
|
ScriptEngine::SetSceneContext(m_EditorScene);
|
||||||
m_SceneHierarchyPanel->SetContext(m_EditorScene);
|
m_SceneHierarchyPanel->SetContext(m_EditorScene);
|
||||||
|
|
||||||
Input::SetCursorMode(CursorMode::Normal);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float EditorLayer::GetSnapValue()
|
float EditorLayer::GetSnapValue()
|
||||||
|
|||||||
@ -44,7 +44,9 @@ namespace Prism
|
|||||||
void OnEntityDeleted(Entity e);
|
void OnEntityDeleted(Entity e);
|
||||||
Ray CastMouseRay();
|
Ray CastMouseRay();
|
||||||
|
|
||||||
|
void NewScene();
|
||||||
void OpenScene();
|
void OpenScene();
|
||||||
|
void OpenScene(const std::string& filepath);
|
||||||
void SaveScene();
|
void SaveScene();
|
||||||
void SaveSceneAs();
|
void SaveSceneAs();
|
||||||
|
|
||||||
|
|||||||
@ -1,155 +0,0 @@
|
|||||||
Scene: Scene Name
|
|
||||||
Environment:
|
|
||||||
AssetPath: assets/env/pink_sunrise_4k.hdr
|
|
||||||
Light:
|
|
||||||
Direction: [-0.787, -0.73299998, 1]
|
|
||||||
Radiance: [1, 1, 1]
|
|
||||||
Multiplier: 0.514999986
|
|
||||||
Entities:
|
|
||||||
- Entity: 12498244675852797835
|
|
||||||
TagComponent:
|
|
||||||
Tag: Box
|
|
||||||
TransformComponent:
|
|
||||||
Position: [-12.0348625, 6.59647179, 9.60061925e-07]
|
|
||||||
Rotation: [1, 0, 0, 0]
|
|
||||||
Scale: [3.00000024, 0.300000012, 1]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 0
|
|
||||||
Mass: 1
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [1.5, 0.150000006]
|
|
||||||
Density: 1
|
|
||||||
Friction: 1
|
|
||||||
- Entity: 5178862374589434728
|
|
||||||
TagComponent:
|
|
||||||
Tag: Camera
|
|
||||||
TransformComponent:
|
|
||||||
Position: [-21.7406311, 9.70659542, 15]
|
|
||||||
Rotation: [0.999910355, -0.0133911213, 0, 0]
|
|
||||||
Scale: [1, 1, 1]
|
|
||||||
ScriptComponent:
|
|
||||||
ModuleName: Example.BasicController
|
|
||||||
StoredFields:
|
|
||||||
- Name: Speed
|
|
||||||
Type: 1
|
|
||||||
Data: 12
|
|
||||||
CameraComponent:
|
|
||||||
Camera: some camera data...
|
|
||||||
Primary: true
|
|
||||||
- Entity: 1289165777996378215
|
|
||||||
TagComponent:
|
|
||||||
Tag: Cube
|
|
||||||
TransformComponent:
|
|
||||||
Position: [500, 0, 0]
|
|
||||||
Rotation: [1, 0, 0, 0]
|
|
||||||
Scale: [1200, 1, 5]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 0
|
|
||||||
Mass: 1
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [600, 0.5]
|
|
||||||
Density: 1
|
|
||||||
Friction: 2
|
|
||||||
- Entity: 14057422478420564497
|
|
||||||
TagComponent:
|
|
||||||
Tag: Player
|
|
||||||
TransformComponent:
|
|
||||||
Position: [-23.6932545, 1.59184527, -1.96369365e-06]
|
|
||||||
Rotation: [1, 0, 0, 0]
|
|
||||||
Scale: [1, 1, 1]
|
|
||||||
ScriptComponent:
|
|
||||||
ModuleName: Example.PlayerCube
|
|
||||||
StoredFields:
|
|
||||||
- Name: HorizontalForce
|
|
||||||
Type: 1
|
|
||||||
Data: 0.5
|
|
||||||
- Name: MaxSpeed
|
|
||||||
Type: 5
|
|
||||||
Data: [7, 10]
|
|
||||||
- Name: JumpForce
|
|
||||||
Type: 1
|
|
||||||
Data: 3
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Sphere1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 1
|
|
||||||
Mass: 29.2000008
|
|
||||||
CircleCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Radius: 0.5
|
|
||||||
Density: 1
|
|
||||||
Friction: 1
|
|
||||||
- Entity: 1352995477042327524
|
|
||||||
TagComponent:
|
|
||||||
Tag: Box
|
|
||||||
TransformComponent:
|
|
||||||
Position: [-29.6808929, 29.7597198, 0]
|
|
||||||
Rotation: [0.707106769, 0, 0, 0.707106769]
|
|
||||||
Scale: [58.4179001, 4.47999144, 4.48000002]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 0
|
|
||||||
Mass: 3
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [29.7000008, 2.24000001]
|
|
||||||
Density: 1
|
|
||||||
Friction: 1
|
|
||||||
- Entity: 15223077898852293773
|
|
||||||
TagComponent:
|
|
||||||
Tag: Box
|
|
||||||
TransformComponent:
|
|
||||||
Position: [6.12674046, 45.5617676, 0]
|
|
||||||
Rotation: [0.977883637, 0, 0, -0.209149584]
|
|
||||||
Scale: [4.47999668, 4.47999668, 4.48000002]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 1
|
|
||||||
Mass: 1
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [2.24000001, 2.24000001]
|
|
||||||
Density: 1
|
|
||||||
Friction: 1
|
|
||||||
- Entity: 5421735812495444456
|
|
||||||
TagComponent:
|
|
||||||
Tag: Box
|
|
||||||
TransformComponent:
|
|
||||||
Position: [-20.766222, 2.29431438, 0]
|
|
||||||
Rotation: [1, 0, 0, 0]
|
|
||||||
Scale: [3.00000024, 0.300000012, 1]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 0
|
|
||||||
Mass: 1
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [1.5, 0.150000006]
|
|
||||||
Density: 1
|
|
||||||
Friction: 1
|
|
||||||
- Entity: 2842299641876190180
|
|
||||||
TagComponent:
|
|
||||||
Tag: Box
|
|
||||||
TransformComponent:
|
|
||||||
Position: [-16.6143265, 4.39151001, 6.43359499e-09]
|
|
||||||
Rotation: [1, 0, 0, 0]
|
|
||||||
Scale: [3.00000024, 0.300000012, 1]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 0
|
|
||||||
Mass: 1
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [1.5, 0.150000006]
|
|
||||||
Density: 1
|
|
||||||
Friction: 1
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
Scene: Scene Name
|
Scene: Scene Name
|
||||||
Environment:
|
Environment:
|
||||||
AssetPath: assets/env/pink_sunrise_4k.hdr
|
AssetPath: assets\env\birchwood_4k.hdr
|
||||||
Light:
|
Light:
|
||||||
Direction: [-0.787, -0.733, 1]
|
Direction: [-0.787, -0.733, 1]
|
||||||
Radiance: [1, 1, 1]
|
Radiance: [1, 1, 1]
|
||||||
@ -51,6 +51,7 @@ Entities:
|
|||||||
Bounciness: 0.1
|
Bounciness: 0.1
|
||||||
MeshColliderComponent:
|
MeshColliderComponent:
|
||||||
AssetPath: assets/meshes/Capsule.fbx
|
AssetPath: assets/meshes/Capsule.fbx
|
||||||
|
IsConvex: true
|
||||||
IsTrigger: false
|
IsTrigger: false
|
||||||
- Entity: 11149966982516343187
|
- Entity: 11149966982516343187
|
||||||
TagComponent:
|
TagComponent:
|
||||||
@ -79,6 +80,7 @@ Entities:
|
|||||||
Bounciness: 0.1
|
Bounciness: 0.1
|
||||||
MeshColliderComponent:
|
MeshColliderComponent:
|
||||||
AssetPath: assets/meshes/Sphere1m.fbx
|
AssetPath: assets/meshes/Sphere1m.fbx
|
||||||
|
IsConvex: true
|
||||||
IsTrigger: false
|
IsTrigger: false
|
||||||
- Entity: 10169503531257462571
|
- Entity: 10169503531257462571
|
||||||
TagComponent:
|
TagComponent:
|
||||||
@ -176,6 +178,17 @@ Entities:
|
|||||||
Offset: [0, 0, 0]
|
Offset: [0, 0, 0]
|
||||||
Size: [1, 1, 1]
|
Size: [1, 1, 1]
|
||||||
IsTrigger: false
|
IsTrigger: false
|
||||||
|
- Entity: 2025484417758554619
|
||||||
|
TagComponent:
|
||||||
|
Tag: Sky Light
|
||||||
|
TransformComponent:
|
||||||
|
Position: [0, 0, 0]
|
||||||
|
Rotation: [0, 0, 0]
|
||||||
|
Scale: [1, 1, 1]
|
||||||
|
SkyLightComponent:
|
||||||
|
EnvironmentAssetPath: assets\env\birchwood_4k.hdr
|
||||||
|
Intensity: 1
|
||||||
|
Angle: 0
|
||||||
PhysicsLayers:
|
PhysicsLayers:
|
||||||
- Name: Box
|
- Name: Box
|
||||||
CollidesWith:
|
CollidesWith:
|
||||||
|
|||||||
@ -1,174 +0,0 @@
|
|||||||
Scene: Scene Name
|
|
||||||
Environment:
|
|
||||||
AssetPath: assets/env/pink_sunrise_4k.hdr
|
|
||||||
Light:
|
|
||||||
Direction: [-0.787, -0.73299998, 1]
|
|
||||||
Radiance: [1, 1, 1]
|
|
||||||
Multiplier: 0.514999986
|
|
||||||
Entities:
|
|
||||||
- Entity: 15861629587505754
|
|
||||||
TagComponent:
|
|
||||||
Tag: Box
|
|
||||||
TransformComponent:
|
|
||||||
Position: [-18.2095661, 39.2518234, 0]
|
|
||||||
Rotation: [0.967056513, 0, 0, -0.254561812]
|
|
||||||
Scale: [4.47999525, 4.47999525, 4.48000002]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 1
|
|
||||||
Mass: 1
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [2.24000001, 2.24000001]
|
|
||||||
- Entity: 15223077898852293773
|
|
||||||
TagComponent:
|
|
||||||
Tag: Box
|
|
||||||
TransformComponent:
|
|
||||||
Position: [5.37119865, 43.8762894, 0]
|
|
||||||
Rotation: [0.977883637, 0, 0, -0.209149718]
|
|
||||||
Scale: [4.47999668, 4.47999668, 4.48000002]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 1
|
|
||||||
Mass: 1
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [2.24000001, 2.24000001]
|
|
||||||
- Entity: 2157107598622182863
|
|
||||||
TagComponent:
|
|
||||||
Tag: Box
|
|
||||||
TransformComponent:
|
|
||||||
Position: [-7.60411549, 44.1442184, 0]
|
|
||||||
Rotation: [0.989285827, 0, 0, 0.145991713]
|
|
||||||
Scale: [4.47999287, 4.47999287, 4.48000002]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 1
|
|
||||||
Mass: 0.5
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [2.24000001, 2.24000001]
|
|
||||||
- Entity: 8080964283681139153
|
|
||||||
TagComponent:
|
|
||||||
Tag: Box
|
|
||||||
TransformComponent:
|
|
||||||
Position: [-0.739211679, 37.7653275, 0]
|
|
||||||
Rotation: [0.956475914, 0, 0, -0.291811317]
|
|
||||||
Scale: [5, 2, 2]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 1
|
|
||||||
Mass: 0.25
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [2.5, 1]
|
|
||||||
- Entity: 1352995477042327524
|
|
||||||
TagComponent:
|
|
||||||
Tag: Box
|
|
||||||
TransformComponent:
|
|
||||||
Position: [-8.32969856, 30.4078159, 0]
|
|
||||||
Rotation: [0.781595349, 0, 0, 0.623785794]
|
|
||||||
Scale: [14.000001, 4.47999334, 4.48000002]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 1
|
|
||||||
Mass: 3
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [7, 2.24000001]
|
|
||||||
- Entity: 935615878363259513
|
|
||||||
TagComponent:
|
|
||||||
Tag: Box
|
|
||||||
TransformComponent:
|
|
||||||
Position: [6.88031197, 31.942337, 0]
|
|
||||||
Rotation: [0.986578286, 0, 0, 0.163288936]
|
|
||||||
Scale: [4.47999954, 4.47999954, 4.48000002]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 1
|
|
||||||
Mass: 1
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [2.24000001, 2.24000001]
|
|
||||||
- Entity: 14057422478420564497
|
|
||||||
TagComponent:
|
|
||||||
Tag: Player
|
|
||||||
TransformComponent:
|
|
||||||
Position: [0, 22.774044, 0]
|
|
||||||
Rotation: [0.942591429, 0, 0, -0.333948225]
|
|
||||||
Scale: [6.00000048, 6.00000048, 4.48000002]
|
|
||||||
ScriptComponent:
|
|
||||||
ModuleName: Example.PlayerCube
|
|
||||||
StoredFields:
|
|
||||||
- Name: HorizontalForce
|
|
||||||
Type: 1
|
|
||||||
Data: 10
|
|
||||||
- Name: VerticalForce
|
|
||||||
Type: 1
|
|
||||||
Data: 10
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Sphere1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 1
|
|
||||||
Mass: 1
|
|
||||||
CircleCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Radius: 3
|
|
||||||
- Entity: 1289165777996378215
|
|
||||||
TagComponent:
|
|
||||||
Tag: Cube
|
|
||||||
TransformComponent:
|
|
||||||
Position: [0, 0, 0]
|
|
||||||
Rotation: [1, 0, 0, 0]
|
|
||||||
Scale: [50, 1, 50]
|
|
||||||
ScriptComponent:
|
|
||||||
ModuleName: Example.Sink
|
|
||||||
StoredFields:
|
|
||||||
- Name: SinkSpeed
|
|
||||||
Type: 1
|
|
||||||
Data: 0
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 0
|
|
||||||
Mass: 1
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [25, 0.5]
|
|
||||||
- Entity: 5178862374589434728
|
|
||||||
TagComponent:
|
|
||||||
Tag: Camera
|
|
||||||
TransformComponent:
|
|
||||||
Position: [0, 25, 79.75]
|
|
||||||
Rotation: [0.995602965, -0.0936739072, 0, 0]
|
|
||||||
Scale: [1, 0.999999821, 0.999999821]
|
|
||||||
ScriptComponent:
|
|
||||||
ModuleName: Example.BasicController
|
|
||||||
StoredFields:
|
|
||||||
- Name: Speed
|
|
||||||
Type: 1
|
|
||||||
Data: 12
|
|
||||||
CameraComponent:
|
|
||||||
Camera: some camera data...
|
|
||||||
Primary: true
|
|
||||||
- Entity: 3948844418381294888
|
|
||||||
TagComponent:
|
|
||||||
Tag: Box
|
|
||||||
TransformComponent:
|
|
||||||
Position: [-1.48028564, 49.5945244, -2.38418579e-07]
|
|
||||||
Rotation: [0.977883637, 0, 0, -0.209149733]
|
|
||||||
Scale: [1.99999976, 1.99999976, 2]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 1
|
|
||||||
Mass: 1
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [1, 1]
|
|
||||||
@ -1,119 +0,0 @@
|
|||||||
Scene: Scene Name
|
|
||||||
Environment:
|
|
||||||
AssetPath: assets/env/pink_sunrise_4k.hdr
|
|
||||||
Light:
|
|
||||||
Direction: [-0.787, -0.73299998, 1]
|
|
||||||
Radiance: [1, 1, 1]
|
|
||||||
Multiplier: 0.514999986
|
|
||||||
Entities:
|
|
||||||
- Entity: 10169503531257462571
|
|
||||||
TagComponent:
|
|
||||||
Tag: Box
|
|
||||||
TransformComponent:
|
|
||||||
Position: [0, 1.5, 0]
|
|
||||||
Rotation: [1, 0, 0, 0]
|
|
||||||
Scale: [2, 2, 2]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBodyComponent:
|
|
||||||
BodyType: 1
|
|
||||||
Mass: 0.5
|
|
||||||
IsKinematic: false
|
|
||||||
Constraints:
|
|
||||||
LockPositionX: false
|
|
||||||
LockPositionY: false
|
|
||||||
LockPositionZ: false
|
|
||||||
LockRotationX: true
|
|
||||||
LockRotationY: true
|
|
||||||
LockRotationZ: true
|
|
||||||
PhysicsMaterialComponent:
|
|
||||||
StaticFriction: 1
|
|
||||||
DynamicFriction: 1
|
|
||||||
Bounciness: 0
|
|
||||||
BoxColliderComponent:
|
|
||||||
Offset: [0, 0, 0]
|
|
||||||
Size: [2, 2, 2]
|
|
||||||
- Entity: 14057422478420564497
|
|
||||||
TagComponent:
|
|
||||||
Tag: Player
|
|
||||||
TransformComponent:
|
|
||||||
Position: [-19.43363, 4.50874043, -1.96695328e-06]
|
|
||||||
Rotation: [1, 0, 0, 0]
|
|
||||||
Scale: [1, 1, 1]
|
|
||||||
ScriptComponent:
|
|
||||||
ModuleName: Example.PlayerSphere
|
|
||||||
StoredFields:
|
|
||||||
- Name: HorizontalForce
|
|
||||||
Type: 1
|
|
||||||
Data: 10
|
|
||||||
- Name: MaxSpeed
|
|
||||||
Type: 6
|
|
||||||
Data: [10, 10, 10]
|
|
||||||
- Name: JumpForce
|
|
||||||
Type: 1
|
|
||||||
Data: 200
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Sphere1m.fbx
|
|
||||||
RigidBodyComponent:
|
|
||||||
BodyType: 1
|
|
||||||
Mass: 1
|
|
||||||
IsKinematic: false
|
|
||||||
Constraints:
|
|
||||||
LockPositionX: false
|
|
||||||
LockPositionY: false
|
|
||||||
LockPositionZ: false
|
|
||||||
LockRotationX: true
|
|
||||||
LockRotationY: true
|
|
||||||
LockRotationZ: true
|
|
||||||
PhysicsMaterialComponent:
|
|
||||||
StaticFriction: 1
|
|
||||||
DynamicFriction: 1
|
|
||||||
Bounciness: 0
|
|
||||||
SphereColliderComponent:
|
|
||||||
Radius: 0.5
|
|
||||||
- Entity: 5178862374589434728
|
|
||||||
TagComponent:
|
|
||||||
Tag: Camera
|
|
||||||
TransformComponent:
|
|
||||||
Position: [-21.7406311, 9.70659542, 15]
|
|
||||||
Rotation: [0.999910355, -0.0133911213, 0, 0]
|
|
||||||
Scale: [1, 1, 1]
|
|
||||||
ScriptComponent:
|
|
||||||
ModuleName: Example.BasicController
|
|
||||||
StoredFields:
|
|
||||||
- Name: Speed
|
|
||||||
Type: 1
|
|
||||||
Data: 12
|
|
||||||
- Name: DistanceFromPlayer
|
|
||||||
Type: 1
|
|
||||||
Data: 15
|
|
||||||
CameraComponent:
|
|
||||||
Camera: some camera data...
|
|
||||||
Primary: true
|
|
||||||
- Entity: 18306113171518048249
|
|
||||||
TagComponent:
|
|
||||||
Tag: Box
|
|
||||||
TransformComponent:
|
|
||||||
Position: [0, 0, 0]
|
|
||||||
Rotation: [1, 0, 0, 0]
|
|
||||||
Scale: [50, 1, 50]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBodyComponent:
|
|
||||||
BodyType: 0
|
|
||||||
Mass: 1
|
|
||||||
IsKinematic: false
|
|
||||||
Constraints:
|
|
||||||
LockPositionX: false
|
|
||||||
LockPositionY: false
|
|
||||||
LockPositionZ: false
|
|
||||||
LockRotationX: true
|
|
||||||
LockRotationY: true
|
|
||||||
LockRotationZ: true
|
|
||||||
PhysicsMaterialComponent:
|
|
||||||
StaticFriction: 1
|
|
||||||
DynamicFriction: 1
|
|
||||||
Bounciness: 0
|
|
||||||
BoxColliderComponent:
|
|
||||||
Offset: [0, 0, 0]
|
|
||||||
Size: [50, 1, 50]
|
|
||||||
@ -1,66 +0,0 @@
|
|||||||
Scene: Scene Name
|
|
||||||
Environment:
|
|
||||||
AssetPath: assets/env/birchwood_4k.hdr
|
|
||||||
Light:
|
|
||||||
Direction: [-0.5, -0.5, 1]
|
|
||||||
Radiance: [1, 1, 1]
|
|
||||||
Multiplier: 1
|
|
||||||
Entities:
|
|
||||||
- Entity: 1289165777996378215
|
|
||||||
TagComponent:
|
|
||||||
Tag: Sphere
|
|
||||||
TransformComponent:
|
|
||||||
Position: [0, 21.9805069, -1.64006281]
|
|
||||||
Rotation: [1, 0, 0, 0]
|
|
||||||
Scale: [0.100000024, 0.100000024, 0.100000024]
|
|
||||||
ScriptComponent:
|
|
||||||
ModuleName: Example.Sink
|
|
||||||
StoredFields:
|
|
||||||
- Name: SinkSpeed
|
|
||||||
Type: 1
|
|
||||||
Data: 5
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Sphere1m.fbx
|
|
||||||
- Entity: 5178862374589434728
|
|
||||||
TagComponent:
|
|
||||||
Tag: Camera
|
|
||||||
TransformComponent:
|
|
||||||
Position: [0, 14.75, 79.75]
|
|
||||||
Rotation: [0.995602965, -0.0936739072, 0, 0]
|
|
||||||
Scale: [1, 0.999999821, 0.999999821]
|
|
||||||
ScriptComponent:
|
|
||||||
ModuleName: Example.BasicController
|
|
||||||
StoredFields:
|
|
||||||
- Name: Speed
|
|
||||||
Type: 1
|
|
||||||
Data: 12
|
|
||||||
CameraComponent:
|
|
||||||
Camera: some camera data...
|
|
||||||
Primary: true
|
|
||||||
- Entity: 9095450049242347594
|
|
||||||
TagComponent:
|
|
||||||
Tag: Test Entity
|
|
||||||
TransformComponent:
|
|
||||||
Position: [0.248109579, -1.90734863e-06, -0.268640995]
|
|
||||||
Rotation: [1, 0, 0, 0]
|
|
||||||
Scale: [1, 1, 1]
|
|
||||||
ScriptComponent:
|
|
||||||
ModuleName: Example.Script
|
|
||||||
StoredFields:
|
|
||||||
- Name: VerticalSpeed
|
|
||||||
Type: 1
|
|
||||||
Data: 0
|
|
||||||
- Name: SinkRate
|
|
||||||
Type: 1
|
|
||||||
Data: 0
|
|
||||||
- Name: Speed
|
|
||||||
Type: 1
|
|
||||||
Data: 1
|
|
||||||
- Name: Rotation
|
|
||||||
Type: 1
|
|
||||||
Data: 0
|
|
||||||
- Name: Velocity
|
|
||||||
Type: 6
|
|
||||||
Data: [0, 0, 0]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/TestScene.fbx
|
|
||||||
63
Editor/assets/shaders/BloomBlend.glsl
Normal file
63
Editor/assets/shaders/BloomBlend.glsl
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#type vertex
|
||||||
|
#version 430
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 a_Position;
|
||||||
|
layout(location = 1) in vec2 a_TexCoord;
|
||||||
|
|
||||||
|
out vec2 v_TexCoord;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 position = vec4(a_Position.xy, 0.0, 1.0);
|
||||||
|
v_TexCoord = a_TexCoord;
|
||||||
|
gl_Position = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
#type fragment
|
||||||
|
#version 430
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 o_Color;
|
||||||
|
|
||||||
|
in vec2 v_TexCoord;
|
||||||
|
|
||||||
|
uniform sampler2D u_SceneTexture;
|
||||||
|
uniform sampler2D u_BloomTexture;
|
||||||
|
|
||||||
|
uniform float u_Exposure;
|
||||||
|
uniform bool u_EnableBloom;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
#if 1
|
||||||
|
const float gamma = 2.2;
|
||||||
|
const float pureWhite = 1.0;
|
||||||
|
|
||||||
|
// Tonemapping
|
||||||
|
vec3 color = texture(u_SceneTexture, v_TexCoord).rgb;
|
||||||
|
if (u_EnableBloom)
|
||||||
|
{
|
||||||
|
vec3 bloomColor = texture(u_BloomTexture, v_TexCoord).rgb;
|
||||||
|
color += bloomColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reinhard tonemapping
|
||||||
|
float luminance = dot(color, vec3(0.2126, 0.7152, 0.0722));
|
||||||
|
float mappedLuminance = (luminance * (1.0 + luminance / (pureWhite * pureWhite))) / (1.0 + luminance);
|
||||||
|
|
||||||
|
// Scale color by ratio of average luminances.
|
||||||
|
vec3 mappedColor = (mappedLuminance / luminance) * color* u_Exposure;
|
||||||
|
|
||||||
|
// Gamma correction.
|
||||||
|
o_Color = vec4(color, 1.0);
|
||||||
|
#else
|
||||||
|
const float gamma = 2.2;
|
||||||
|
vec3 hdrColor = texture(u_SceneTexture, v_TexCoord).rgb;
|
||||||
|
vec3 bloomColor = texture(u_BloomTexture, v_TexCoord).rgb;
|
||||||
|
hdrColor += bloomColor; // additive blending
|
||||||
|
// tone mapping
|
||||||
|
vec3 result = vec3(1.0) - exp(-hdrColor * u_Exposure);
|
||||||
|
// also gamma correct while we're at it
|
||||||
|
result = pow(result, vec3(1.0 / gamma));
|
||||||
|
o_Color = vec4(result, 1.0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
79
Editor/assets/shaders/BloomBlur.glsl
Normal file
79
Editor/assets/shaders/BloomBlur.glsl
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#type vertex
|
||||||
|
#version 430
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 a_Position;
|
||||||
|
layout(location = 1) in vec2 a_TexCoord;
|
||||||
|
|
||||||
|
out vec2 v_TexCoord;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 position = vec4(a_Position.xy, 0.0, 1.0);
|
||||||
|
v_TexCoord = a_TexCoord;
|
||||||
|
gl_Position = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
#type fragment
|
||||||
|
#version 430
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 o_Color;
|
||||||
|
|
||||||
|
in vec2 v_TexCoord;
|
||||||
|
|
||||||
|
uniform sampler2D u_Texture;
|
||||||
|
uniform bool u_Horizontal;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
#if 1
|
||||||
|
// From learnopengl.com
|
||||||
|
float weight[5] = float[] (0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216);
|
||||||
|
|
||||||
|
vec2 tex_offset = 1.0 / textureSize(u_Texture, 0); // gets size of single texel
|
||||||
|
vec3 result = texture(u_Texture, v_TexCoord).rgb * weight[0]; // current fragment's contribution
|
||||||
|
if (u_Horizontal)
|
||||||
|
{
|
||||||
|
for(int i = 1; i < 5; ++i)
|
||||||
|
{
|
||||||
|
result += texture(u_Texture, v_TexCoord + vec2(tex_offset.x * i, 0.0)).rgb * weight[i];
|
||||||
|
result += texture(u_Texture, v_TexCoord - vec2(tex_offset.x * i, 0.0)).rgb * weight[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(int i = 1; i < 5; ++i)
|
||||||
|
{
|
||||||
|
result += texture(u_Texture, v_TexCoord + vec2(0.0, tex_offset.y * i)).rgb * weight[i];
|
||||||
|
result += texture(u_Texture, v_TexCoord - vec2(0.0, tex_offset.y * i)).rgb * weight[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
o_Color = vec4(result, 1.0);
|
||||||
|
#else
|
||||||
|
// From https://www.shadertoy.com/view/Xltfzj
|
||||||
|
|
||||||
|
float Pi = 6.28318530718; // Pi*2
|
||||||
|
|
||||||
|
// GAUSSIAN BLUR SETTINGS {{{
|
||||||
|
float Directions =32.0; // BLUR DIRECTIONS (Default 16.0 - More is better but slower)
|
||||||
|
float Quality = 6.0; // BLUR QUALITY (Default 4.0 - More is better but slower)
|
||||||
|
float Size = 16.0; // BLUR SIZE (Radius)
|
||||||
|
// GAUSSIAN BLUR SETTINGS }}}
|
||||||
|
|
||||||
|
vec2 Radius = Size/textureSize(u_Texture, 0);
|
||||||
|
|
||||||
|
vec3 result = texture(u_Texture, v_TexCoord).rgb;
|
||||||
|
vec2 uv = v_TexCoord;
|
||||||
|
// Blur calculations
|
||||||
|
for( float d=0.0; d<Pi; d+=Pi/Directions)
|
||||||
|
{
|
||||||
|
for(float i=1.0/Quality; i<=1.0; i+=1.0/Quality)
|
||||||
|
{
|
||||||
|
result += texture( u_Texture, uv+vec2(cos(d),sin(d))*Radius*i).rgb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output to screen
|
||||||
|
result /= Quality * Directions - 15.0;
|
||||||
|
o_Color = vec4(result, 1.0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
@ -4,13 +4,10 @@
|
|||||||
#version 430
|
#version 430
|
||||||
|
|
||||||
layout(location = 0) in vec3 a_Position;
|
layout(location = 0) in vec3 a_Position;
|
||||||
layout(location = 1) in vec2 a_TexCoord;
|
|
||||||
|
|
||||||
uniform mat4 u_ViewProjection;
|
uniform mat4 u_ViewProjection;
|
||||||
uniform mat4 u_Transform;
|
uniform mat4 u_Transform;
|
||||||
|
|
||||||
out vec2 v_TexCoord;
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
gl_Position = u_ViewProjection * u_Transform * vec4(a_Position, 1.0);
|
gl_Position = u_ViewProjection * u_Transform * vec4(a_Position, 1.0);
|
||||||
|
|||||||
36
Editor/assets/shaders/Outline_Anim.glsl
Normal file
36
Editor/assets/shaders/Outline_Anim.glsl
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// Outline Shader
|
||||||
|
|
||||||
|
#type vertex
|
||||||
|
#version 430
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 a_Position;
|
||||||
|
|
||||||
|
layout(location = 5) in ivec4 a_BoneIndices;
|
||||||
|
layout(location = 6) in vec4 a_BoneWeights;
|
||||||
|
|
||||||
|
uniform mat4 u_ViewProjection;
|
||||||
|
uniform mat4 u_Transform;
|
||||||
|
|
||||||
|
const int MAX_BONES = 100;
|
||||||
|
uniform mat4 u_BoneTransforms[100];
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
mat4 boneTransform = u_BoneTransforms[a_BoneIndices[0]] * a_BoneWeights[0];
|
||||||
|
boneTransform += u_BoneTransforms[a_BoneIndices[1]] * a_BoneWeights[1];
|
||||||
|
boneTransform += u_BoneTransforms[a_BoneIndices[2]] * a_BoneWeights[2];
|
||||||
|
boneTransform += u_BoneTransforms[a_BoneIndices[3]] * a_BoneWeights[3];
|
||||||
|
|
||||||
|
vec4 localPosition = boneTransform * vec4(a_Position, 1.0);
|
||||||
|
gl_Position = u_ViewProjection * u_Transform * localPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
#type fragment
|
||||||
|
#version 430
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 color;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
color = vec4(1.0, 0.5, 0.0, 1.0);
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
// -----------------------------
|
// -----------------------------
|
||||||
// -- From Hazel Engine PBR shader --
|
// -- Hazel Engine PBR shader --
|
||||||
// -----------------------------
|
// -----------------------------
|
||||||
// Note: this shader is still very much in progress. There are likely many bugs and future additions that will go in.
|
// Note: this shader is still very much in progress. There are likely many bugs and future additions that will go in.
|
||||||
// Currently heavily updated.
|
// Currently heavily updated.
|
||||||
@ -22,8 +22,14 @@ layout(location = 5) in ivec4 a_BoneIndices;
|
|||||||
layout(location = 6) in vec4 a_BoneWeights;
|
layout(location = 6) in vec4 a_BoneWeights;
|
||||||
|
|
||||||
uniform mat4 u_ViewProjectionMatrix;
|
uniform mat4 u_ViewProjectionMatrix;
|
||||||
|
uniform mat4 u_ViewMatrix;
|
||||||
uniform mat4 u_Transform;
|
uniform mat4 u_Transform;
|
||||||
|
|
||||||
|
uniform mat4 u_LightMatrixCascade0;
|
||||||
|
uniform mat4 u_LightMatrixCascade1;
|
||||||
|
uniform mat4 u_LightMatrixCascade2;
|
||||||
|
uniform mat4 u_LightMatrixCascade3;
|
||||||
|
|
||||||
const int MAX_BONES = 100;
|
const int MAX_BONES = 100;
|
||||||
uniform mat4 u_BoneTransforms[100];
|
uniform mat4 u_BoneTransforms[100];
|
||||||
|
|
||||||
@ -33,7 +39,10 @@ out VertexOutput
|
|||||||
vec3 Normal;
|
vec3 Normal;
|
||||||
vec2 TexCoord;
|
vec2 TexCoord;
|
||||||
mat3 WorldNormals;
|
mat3 WorldNormals;
|
||||||
|
mat3 WorldTransform;
|
||||||
vec3 Binormal;
|
vec3 Binormal;
|
||||||
|
vec4 ShadowMapCoords[4];
|
||||||
|
vec3 ViewPosition;
|
||||||
} vs_Output;
|
} vs_Output;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
@ -49,7 +58,14 @@ void main()
|
|||||||
vs_Output.Normal = mat3(u_Transform) * 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.WorldTransform = mat3(u_Transform);
|
||||||
|
vs_Output.Binormal = a_Binormal;
|
||||||
|
|
||||||
|
vs_Output.ShadowMapCoords[0] = u_LightMatrixCascade0 * vec4(vs_Output.WorldPosition, 1.0);
|
||||||
|
vs_Output.ShadowMapCoords[1] = u_LightMatrixCascade1 * vec4(vs_Output.WorldPosition, 1.0);
|
||||||
|
vs_Output.ShadowMapCoords[2] = u_LightMatrixCascade2 * vec4(vs_Output.WorldPosition, 1.0);
|
||||||
|
vs_Output.ShadowMapCoords[3] = u_LightMatrixCascade3 * vec4(vs_Output.WorldPosition, 1.0);
|
||||||
|
vs_Output.ViewPosition = vec3(u_ViewMatrix * vec4(vs_Output.WorldPosition, 1.0));
|
||||||
|
|
||||||
gl_Position = u_ViewProjectionMatrix * u_Transform * localPosition;
|
gl_Position = u_ViewProjectionMatrix * u_Transform * localPosition;
|
||||||
}
|
}
|
||||||
@ -65,7 +81,8 @@ const int LightCount = 1;
|
|||||||
// Constant normal incidence Fresnel factor for all dielectrics.
|
// Constant normal incidence Fresnel factor for all dielectrics.
|
||||||
const vec3 Fdielectric = vec3(0.04);
|
const vec3 Fdielectric = vec3(0.04);
|
||||||
|
|
||||||
struct Light {
|
struct DirectionalLight
|
||||||
|
{
|
||||||
vec3 Direction;
|
vec3 Direction;
|
||||||
vec3 Radiance;
|
vec3 Radiance;
|
||||||
float Multiplier;
|
float Multiplier;
|
||||||
@ -77,12 +94,16 @@ in VertexOutput
|
|||||||
vec3 Normal;
|
vec3 Normal;
|
||||||
vec2 TexCoord;
|
vec2 TexCoord;
|
||||||
mat3 WorldNormals;
|
mat3 WorldNormals;
|
||||||
|
mat3 WorldTransform;
|
||||||
vec3 Binormal;
|
vec3 Binormal;
|
||||||
|
vec4 ShadowMapCoords[4];
|
||||||
|
vec3 ViewPosition;
|
||||||
} vs_Input;
|
} vs_Input;
|
||||||
|
|
||||||
layout(location = 0) out vec4 color;
|
layout(location = 0) out vec4 color;
|
||||||
|
layout(location = 1) out vec4 o_BloomColor;
|
||||||
|
|
||||||
uniform Light lights;
|
uniform DirectionalLight u_DirectionalLights;
|
||||||
uniform vec3 u_CameraPosition;
|
uniform vec3 u_CameraPosition;
|
||||||
|
|
||||||
// PBR texture inputs
|
// PBR texture inputs
|
||||||
@ -98,6 +119,25 @@ uniform samplerCube u_EnvIrradianceTex;
|
|||||||
// BRDF LUT
|
// BRDF LUT
|
||||||
uniform sampler2D u_BRDFLUTTexture;
|
uniform sampler2D u_BRDFLUTTexture;
|
||||||
|
|
||||||
|
// PCSS
|
||||||
|
uniform sampler2D u_ShadowMapTexture[4];
|
||||||
|
uniform mat4 u_LightView;
|
||||||
|
uniform bool u_ShowCascades;
|
||||||
|
uniform bool u_SoftShadows;
|
||||||
|
uniform float u_LightSize;
|
||||||
|
uniform float u_MaxShadowDistance;
|
||||||
|
uniform float u_ShadowFade;
|
||||||
|
uniform bool u_CascadeFading;
|
||||||
|
uniform float u_CascadeTransitionFade;
|
||||||
|
|
||||||
|
uniform vec4 u_CascadeSplits;
|
||||||
|
|
||||||
|
uniform float u_IBLContribution;
|
||||||
|
|
||||||
|
uniform float u_BloomThreshold;
|
||||||
|
|
||||||
|
////////////////////////////////////////
|
||||||
|
|
||||||
uniform vec3 u_AlbedoColor;
|
uniform vec3 u_AlbedoColor;
|
||||||
uniform float u_Metalness;
|
uniform float u_Metalness;
|
||||||
uniform float u_Roughness;
|
uniform float u_Roughness;
|
||||||
@ -105,7 +145,6 @@ uniform float u_Roughness;
|
|||||||
uniform float u_EnvMapRotation;
|
uniform float u_EnvMapRotation;
|
||||||
|
|
||||||
// Toggles
|
// Toggles
|
||||||
uniform float u_RadiancePrefilter;
|
|
||||||
uniform float u_AlbedoTexToggle;
|
uniform float u_AlbedoTexToggle;
|
||||||
uniform float u_NormalTexToggle;
|
uniform float u_NormalTexToggle;
|
||||||
uniform float u_MetalnessTexToggle;
|
uniform float u_MetalnessTexToggle;
|
||||||
@ -256,8 +295,8 @@ vec3 Lighting(vec3 F0)
|
|||||||
vec3 result = vec3(0.0);
|
vec3 result = vec3(0.0);
|
||||||
for(int i = 0; i < LightCount; i++)
|
for(int i = 0; i < LightCount; i++)
|
||||||
{
|
{
|
||||||
vec3 Li = -lights.Direction;
|
vec3 Li = u_DirectionalLights.Direction;
|
||||||
vec3 Lradiance = lights.Radiance * lights.Multiplier;
|
vec3 Lradiance = u_DirectionalLights.Radiance * u_DirectionalLights.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.
|
||||||
@ -298,6 +337,181 @@ vec3 IBL(vec3 F0, vec3 Lr)
|
|||||||
return kd * diffuseIBL + specularIBL;
|
return kd * diffuseIBL + specularIBL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////
|
||||||
|
// PCSS
|
||||||
|
/////////////////////////////////////////////
|
||||||
|
|
||||||
|
uint CascadeIndex = 0;
|
||||||
|
float ShadowFade = 1.0;
|
||||||
|
|
||||||
|
float GetShadowBias()
|
||||||
|
{
|
||||||
|
const float MINIMUM_SHADOW_BIAS = 0.002;
|
||||||
|
float bias = max(MINIMUM_SHADOW_BIAS * (1.0 - dot(m_Params.Normal, u_DirectionalLights.Direction)), MINIMUM_SHADOW_BIAS);
|
||||||
|
return bias;
|
||||||
|
}
|
||||||
|
|
||||||
|
float HardShadows_DirectionalLight(sampler2D shadowMap, vec3 shadowCoords)
|
||||||
|
{
|
||||||
|
float bias = GetShadowBias();
|
||||||
|
float z = texture(shadowMap, shadowCoords.xy).x;
|
||||||
|
return 1.0 - step(z + bias, shadowCoords.z) * ShadowFade;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Penumbra
|
||||||
|
|
||||||
|
// this search area estimation comes from the following article:
|
||||||
|
// http://developer.download.nvidia.com/whitepapers/2008/PCSS_DirectionalLight_Integration.pdf
|
||||||
|
float SearchWidth(float uvLightSize, float receiverDistance)
|
||||||
|
{
|
||||||
|
const float NEAR = 0.1;
|
||||||
|
return uvLightSize * (receiverDistance - NEAR) / u_CameraPosition.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
float u_light_zNear = 0.0; // 0.01 gives artifacts? maybe because of ortho proj?
|
||||||
|
float u_light_zFar = 10000.0;
|
||||||
|
vec2 u_lightRadiusUV = vec2(0.05);
|
||||||
|
|
||||||
|
vec2 searchRegionRadiusUV(float zWorld)
|
||||||
|
{
|
||||||
|
return u_lightRadiusUV * (zWorld - u_light_zNear) / zWorld;
|
||||||
|
}
|
||||||
|
|
||||||
|
const vec2 PoissonDistribution[64] = vec2[](
|
||||||
|
vec2(-0.884081, 0.124488),
|
||||||
|
vec2(-0.714377, 0.027940),
|
||||||
|
vec2(-0.747945, 0.227922),
|
||||||
|
vec2(-0.939609, 0.243634),
|
||||||
|
vec2(-0.985465, 0.045534),
|
||||||
|
vec2(-0.861367, -0.136222),
|
||||||
|
vec2(-0.881934, 0.396908),
|
||||||
|
vec2(-0.466938, 0.014526),
|
||||||
|
vec2(-0.558207, 0.212662),
|
||||||
|
vec2(-0.578447, -0.095822),
|
||||||
|
vec2(-0.740266, -0.095631),
|
||||||
|
vec2(-0.751681, 0.472604),
|
||||||
|
vec2(-0.553147, -0.243177),
|
||||||
|
vec2(-0.674762, -0.330730),
|
||||||
|
vec2(-0.402765, -0.122087),
|
||||||
|
vec2(-0.319776, -0.312166),
|
||||||
|
vec2(-0.413923, -0.439757),
|
||||||
|
vec2(-0.979153, -0.201245),
|
||||||
|
vec2(-0.865579, -0.288695),
|
||||||
|
vec2(-0.243704, -0.186378),
|
||||||
|
vec2(-0.294920, -0.055748),
|
||||||
|
vec2(-0.604452, -0.544251),
|
||||||
|
vec2(-0.418056, -0.587679),
|
||||||
|
vec2(-0.549156, -0.415877),
|
||||||
|
vec2(-0.238080, -0.611761),
|
||||||
|
vec2(-0.267004, -0.459702),
|
||||||
|
vec2(-0.100006, -0.229116),
|
||||||
|
vec2(-0.101928, -0.380382),
|
||||||
|
vec2(-0.681467, -0.700773),
|
||||||
|
vec2(-0.763488, -0.543386),
|
||||||
|
vec2(-0.549030, -0.750749),
|
||||||
|
vec2(-0.809045, -0.408738),
|
||||||
|
vec2(-0.388134, -0.773448),
|
||||||
|
vec2(-0.429392, -0.894892),
|
||||||
|
vec2(-0.131597, 0.065058),
|
||||||
|
vec2(-0.275002, 0.102922),
|
||||||
|
vec2(-0.106117, -0.068327),
|
||||||
|
vec2(-0.294586, -0.891515),
|
||||||
|
vec2(-0.629418, 0.379387),
|
||||||
|
vec2(-0.407257, 0.339748),
|
||||||
|
vec2(0.071650, -0.384284),
|
||||||
|
vec2(0.022018, -0.263793),
|
||||||
|
vec2(0.003879, -0.136073),
|
||||||
|
vec2(-0.137533, -0.767844),
|
||||||
|
vec2(-0.050874, -0.906068),
|
||||||
|
vec2(0.114133, -0.070053),
|
||||||
|
vec2(0.163314, -0.217231),
|
||||||
|
vec2(-0.100262, -0.587992),
|
||||||
|
vec2(-0.004942, 0.125368),
|
||||||
|
vec2(0.035302, -0.619310),
|
||||||
|
vec2(0.195646, -0.459022),
|
||||||
|
vec2(0.303969, -0.346362),
|
||||||
|
vec2(-0.678118, 0.685099),
|
||||||
|
vec2(-0.628418, 0.507978),
|
||||||
|
vec2(-0.508473, 0.458753),
|
||||||
|
vec2(0.032134, -0.782030),
|
||||||
|
vec2(0.122595, 0.280353),
|
||||||
|
vec2(-0.043643, 0.312119),
|
||||||
|
vec2(0.132993, 0.085170),
|
||||||
|
vec2(-0.192106, 0.285848),
|
||||||
|
vec2(0.183621, -0.713242),
|
||||||
|
vec2(0.265220, -0.596716),
|
||||||
|
vec2(-0.009628, -0.483058),
|
||||||
|
vec2(-0.018516, 0.435703)
|
||||||
|
);
|
||||||
|
|
||||||
|
vec2 SamplePoisson(int index)
|
||||||
|
{
|
||||||
|
return PoissonDistribution[index % 64];
|
||||||
|
}
|
||||||
|
|
||||||
|
float FindBlockerDistance_DirectionalLight(sampler2D shadowMap, vec3 shadowCoords, float uvLightSize)
|
||||||
|
{
|
||||||
|
float bias = GetShadowBias();
|
||||||
|
|
||||||
|
int numBlockerSearchSamples = 64;
|
||||||
|
int blockers = 0;
|
||||||
|
float avgBlockerDistance = 0;
|
||||||
|
|
||||||
|
float zEye = -(u_LightView * vec4(vs_Input.WorldPosition, 1.0)).z;
|
||||||
|
vec2 searchWidth = searchRegionRadiusUV(zEye);
|
||||||
|
for (int i = 0; i < numBlockerSearchSamples; i++)
|
||||||
|
{
|
||||||
|
float z = texture(shadowMap, shadowCoords.xy + SamplePoisson(i) * searchWidth).r;
|
||||||
|
if (z < (shadowCoords.z - bias))
|
||||||
|
{
|
||||||
|
blockers++;
|
||||||
|
avgBlockerDistance += z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (blockers > 0)
|
||||||
|
return avgBlockerDistance / float(blockers);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
float PenumbraWidth(sampler2D shadowMap, vec3 shadowCoords, float uvLightSize)
|
||||||
|
{
|
||||||
|
float blockerDistance = FindBlockerDistance_DirectionalLight(shadowMap, shadowCoords, uvLightSize);
|
||||||
|
if (blockerDistance == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return (shadowCoords.z - blockerDistance) / blockerDistance;
|
||||||
|
}
|
||||||
|
|
||||||
|
float PCF_DirectionalLight(sampler2D shadowMap, vec3 shadowCoords, float uvRadius)
|
||||||
|
{
|
||||||
|
float bias = GetShadowBias();
|
||||||
|
int numPCFSamples = 64;
|
||||||
|
float sum = 0;
|
||||||
|
for (int i = 0; i < numPCFSamples; i++)
|
||||||
|
{
|
||||||
|
float z = texture(shadowMap, shadowCoords.xy + SamplePoisson(i) * uvRadius).r;
|
||||||
|
sum += (z < (shadowCoords.z - bias)) ? 1 : 0;
|
||||||
|
}
|
||||||
|
return sum / numPCFSamples;
|
||||||
|
}
|
||||||
|
|
||||||
|
float PCSS_DirectionalLight(sampler2D shadowMap, vec3 shadowCoords, float uvLightSize)
|
||||||
|
{
|
||||||
|
float blockerDistance = FindBlockerDistance_DirectionalLight(shadowMap, shadowCoords, uvLightSize);
|
||||||
|
if (blockerDistance == -1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
float penumbraWidth = (shadowCoords.z - blockerDistance) / blockerDistance;
|
||||||
|
|
||||||
|
float NEAR = 0.01; // Should this value be tweakable?
|
||||||
|
float uvRadius = penumbraWidth * uvLightSize * NEAR / shadowCoords.z;
|
||||||
|
return 1.0 - PCF_DirectionalLight(shadowMap, shadowCoords, uvRadius) * ShadowFade;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
// Standard PBR inputs
|
// Standard PBR inputs
|
||||||
@ -323,8 +537,102 @@ 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 = Lighting(F0);
|
const uint SHADOW_MAP_CASCADE_COUNT = 4;
|
||||||
vec3 iblContribution = IBL(F0, Lr);
|
for(uint i = 0; i < SHADOW_MAP_CASCADE_COUNT - 1; i++)
|
||||||
|
{
|
||||||
|
if(vs_Input.ViewPosition.z < u_CascadeSplits[i])
|
||||||
|
CascadeIndex = i + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
float shadowDistance = u_MaxShadowDistance;//u_CascadeSplits[3];
|
||||||
|
float transitionDistance = u_ShadowFade;
|
||||||
|
float distance = length(vs_Input.ViewPosition);
|
||||||
|
ShadowFade = distance - (shadowDistance - transitionDistance);
|
||||||
|
ShadowFade /= transitionDistance;
|
||||||
|
ShadowFade = clamp(1.0 - ShadowFade, 0.0, 1.0);
|
||||||
|
|
||||||
|
bool fadeCascades = u_CascadeFading;
|
||||||
|
float shadowAmount = 1.0;
|
||||||
|
if (fadeCascades)
|
||||||
|
{
|
||||||
|
float cascadeTransitionFade = u_CascadeTransitionFade;
|
||||||
|
|
||||||
|
float c0 = smoothstep(u_CascadeSplits[0] + cascadeTransitionFade * 0.5f, u_CascadeSplits[0] - cascadeTransitionFade * 0.5f, vs_Input.ViewPosition.z);
|
||||||
|
float c1 = smoothstep(u_CascadeSplits[1] + cascadeTransitionFade * 0.5f, u_CascadeSplits[1] - cascadeTransitionFade * 0.5f, vs_Input.ViewPosition.z);
|
||||||
|
float c2 = smoothstep(u_CascadeSplits[2] + cascadeTransitionFade * 0.5f, u_CascadeSplits[2] - cascadeTransitionFade * 0.5f, vs_Input.ViewPosition.z);
|
||||||
|
if (c0 > 0.0 && c0 < 1.0)
|
||||||
|
{
|
||||||
|
// Sample 0 & 1
|
||||||
|
vec3 shadowMapCoords = (vs_Input.ShadowMapCoords[0].xyz / vs_Input.ShadowMapCoords[0].w);
|
||||||
|
float shadowAmount0 = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[0], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[0], shadowMapCoords);
|
||||||
|
shadowMapCoords = (vs_Input.ShadowMapCoords[1].xyz / vs_Input.ShadowMapCoords[1].w);
|
||||||
|
float shadowAmount1 = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[1], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[1], shadowMapCoords);
|
||||||
|
|
||||||
|
shadowAmount = mix(shadowAmount0, shadowAmount1, c0);
|
||||||
|
}
|
||||||
|
else if (c1 > 0.0 && c1 < 1.0)
|
||||||
|
{
|
||||||
|
// Sample 1 & 2
|
||||||
|
vec3 shadowMapCoords = (vs_Input.ShadowMapCoords[1].xyz / vs_Input.ShadowMapCoords[1].w);
|
||||||
|
float shadowAmount1 = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[1], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[1], shadowMapCoords);
|
||||||
|
shadowMapCoords = (vs_Input.ShadowMapCoords[2].xyz / vs_Input.ShadowMapCoords[2].w);
|
||||||
|
float shadowAmount2 = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[2], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[2], shadowMapCoords);
|
||||||
|
|
||||||
|
shadowAmount = mix(shadowAmount1, shadowAmount2, c1);
|
||||||
|
}
|
||||||
|
else if (c2 > 0.0 && c2 < 1.0)
|
||||||
|
{
|
||||||
|
// Sample 2 & 3
|
||||||
|
vec3 shadowMapCoords = (vs_Input.ShadowMapCoords[2].xyz / vs_Input.ShadowMapCoords[2].w);
|
||||||
|
float shadowAmount2 = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[2], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[2], shadowMapCoords);
|
||||||
|
shadowMapCoords = (vs_Input.ShadowMapCoords[3].xyz / vs_Input.ShadowMapCoords[3].w);
|
||||||
|
float shadowAmount3 = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[3], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[3], shadowMapCoords);
|
||||||
|
|
||||||
|
shadowAmount = mix(shadowAmount2, shadowAmount3, c2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vec3 shadowMapCoords = (vs_Input.ShadowMapCoords[CascadeIndex].xyz / vs_Input.ShadowMapCoords[CascadeIndex].w);
|
||||||
|
shadowAmount = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[CascadeIndex], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[CascadeIndex], shadowMapCoords);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vec3 shadowMapCoords = (vs_Input.ShadowMapCoords[CascadeIndex].xyz / vs_Input.ShadowMapCoords[CascadeIndex].w);
|
||||||
|
shadowAmount = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[CascadeIndex], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[CascadeIndex], shadowMapCoords);
|
||||||
|
}
|
||||||
|
|
||||||
|
float NdotL = dot(m_Params.Normal, u_DirectionalLights.Direction);
|
||||||
|
NdotL = smoothstep(0.0, 0.4, NdotL + 0.2);
|
||||||
|
shadowAmount *= (NdotL * 1.0);
|
||||||
|
|
||||||
|
vec3 iblContribution = IBL(F0, Lr) * u_IBLContribution;
|
||||||
|
vec3 lightContribution = u_DirectionalLights.Multiplier > 0.0f ? (Lighting(F0) * shadowAmount) : vec3(0.0f);
|
||||||
|
|
||||||
color = vec4(lightContribution + iblContribution, 1.0);
|
color = vec4(lightContribution + iblContribution, 1.0);
|
||||||
|
|
||||||
|
// Bloom
|
||||||
|
float brightness = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722));
|
||||||
|
o_BloomColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
if (brightness > u_BloomThreshold)
|
||||||
|
o_BloomColor = color;
|
||||||
|
|
||||||
|
if (u_ShowCascades)
|
||||||
|
{
|
||||||
|
switch(CascadeIndex)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
color.rgb *= vec3(1.0f, 0.25f, 0.25f);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
color.rgb *= vec3(0.25f, 1.0f, 0.25f);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
color.rgb *= vec3(0.25f, 0.25f, 1.0f);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
color.rgb *= vec3(1.0f, 1.0f, 0.25f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
// -----------------------------
|
// -----------------------------
|
||||||
// -- From Hazel Engine PBR shader --
|
// -- Hazel Engine PBR shader --
|
||||||
// -----------------------------
|
// -----------------------------
|
||||||
// Note: this shader is still very much in progress. There are likely many bugs and future additions that will go in.
|
// Note: this shader is still very much in progress. There are likely many bugs and future additions that will go in.
|
||||||
// Currently heavily updated.
|
// Currently heavily updated.
|
||||||
@ -19,8 +19,14 @@ layout(location = 3) in vec3 a_Binormal;
|
|||||||
layout(location = 4) in vec2 a_TexCoord;
|
layout(location = 4) in vec2 a_TexCoord;
|
||||||
|
|
||||||
uniform mat4 u_ViewProjectionMatrix;
|
uniform mat4 u_ViewProjectionMatrix;
|
||||||
|
uniform mat4 u_ViewMatrix;
|
||||||
uniform mat4 u_Transform;
|
uniform mat4 u_Transform;
|
||||||
|
|
||||||
|
uniform mat4 u_LightMatrixCascade0;
|
||||||
|
uniform mat4 u_LightMatrixCascade1;
|
||||||
|
uniform mat4 u_LightMatrixCascade2;
|
||||||
|
uniform mat4 u_LightMatrixCascade3;
|
||||||
|
|
||||||
out VertexOutput
|
out VertexOutput
|
||||||
{
|
{
|
||||||
vec3 WorldPosition;
|
vec3 WorldPosition;
|
||||||
@ -29,6 +35,8 @@ out VertexOutput
|
|||||||
mat3 WorldNormals;
|
mat3 WorldNormals;
|
||||||
mat3 WorldTransform;
|
mat3 WorldTransform;
|
||||||
vec3 Binormal;
|
vec3 Binormal;
|
||||||
|
vec4 ShadowMapCoords[4];
|
||||||
|
vec3 ViewPosition;
|
||||||
} vs_Output;
|
} vs_Output;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
@ -40,6 +48,12 @@ void main()
|
|||||||
vs_Output.WorldTransform = mat3(u_Transform);
|
vs_Output.WorldTransform = mat3(u_Transform);
|
||||||
vs_Output.Binormal = a_Binormal;
|
vs_Output.Binormal = a_Binormal;
|
||||||
|
|
||||||
|
vs_Output.ShadowMapCoords[0] = u_LightMatrixCascade0 * vec4(vs_Output.WorldPosition, 1.0);
|
||||||
|
vs_Output.ShadowMapCoords[1] = u_LightMatrixCascade1 * vec4(vs_Output.WorldPosition, 1.0);
|
||||||
|
vs_Output.ShadowMapCoords[2] = u_LightMatrixCascade2 * vec4(vs_Output.WorldPosition, 1.0);
|
||||||
|
vs_Output.ShadowMapCoords[3] = u_LightMatrixCascade3 * vec4(vs_Output.WorldPosition, 1.0);
|
||||||
|
vs_Output.ViewPosition = vec3(u_ViewMatrix * vec4(vs_Output.WorldPosition, 1.0));
|
||||||
|
|
||||||
gl_Position = u_ViewProjectionMatrix * u_Transform * vec4(a_Position, 1.0);
|
gl_Position = u_ViewProjectionMatrix * u_Transform * vec4(a_Position, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +68,8 @@ const int LightCount = 1;
|
|||||||
// Constant normal incidence Fresnel factor for all dielectrics.
|
// Constant normal incidence Fresnel factor for all dielectrics.
|
||||||
const vec3 Fdielectric = vec3(0.04);
|
const vec3 Fdielectric = vec3(0.04);
|
||||||
|
|
||||||
struct Light {
|
struct DirectionalLight
|
||||||
|
{
|
||||||
vec3 Direction;
|
vec3 Direction;
|
||||||
vec3 Radiance;
|
vec3 Radiance;
|
||||||
float Multiplier;
|
float Multiplier;
|
||||||
@ -68,11 +83,14 @@ in VertexOutput
|
|||||||
mat3 WorldNormals;
|
mat3 WorldNormals;
|
||||||
mat3 WorldTransform;
|
mat3 WorldTransform;
|
||||||
vec3 Binormal;
|
vec3 Binormal;
|
||||||
|
vec4 ShadowMapCoords[4];
|
||||||
|
vec3 ViewPosition;
|
||||||
} vs_Input;
|
} vs_Input;
|
||||||
|
|
||||||
layout(location = 0) out vec4 color;
|
layout(location = 0) out vec4 color;
|
||||||
|
layout(location = 1) out vec4 o_BloomColor;
|
||||||
|
|
||||||
uniform Light lights;
|
uniform DirectionalLight u_DirectionalLights;
|
||||||
uniform vec3 u_CameraPosition;
|
uniform vec3 u_CameraPosition;
|
||||||
|
|
||||||
// PBR texture inputs
|
// PBR texture inputs
|
||||||
@ -88,6 +106,25 @@ uniform samplerCube u_EnvIrradianceTex;
|
|||||||
// BRDF LUT
|
// BRDF LUT
|
||||||
uniform sampler2D u_BRDFLUTTexture;
|
uniform sampler2D u_BRDFLUTTexture;
|
||||||
|
|
||||||
|
// PCSS
|
||||||
|
uniform sampler2D u_ShadowMapTexture[4];
|
||||||
|
uniform mat4 u_LightView;
|
||||||
|
uniform bool u_ShowCascades;
|
||||||
|
uniform bool u_SoftShadows;
|
||||||
|
uniform float u_LightSize;
|
||||||
|
uniform float u_MaxShadowDistance;
|
||||||
|
uniform float u_ShadowFade;
|
||||||
|
uniform bool u_CascadeFading;
|
||||||
|
uniform float u_CascadeTransitionFade;
|
||||||
|
|
||||||
|
uniform vec4 u_CascadeSplits;
|
||||||
|
|
||||||
|
uniform float u_IBLContribution;
|
||||||
|
|
||||||
|
uniform float u_BloomThreshold;
|
||||||
|
|
||||||
|
////////////////////////////////////////
|
||||||
|
|
||||||
uniform vec3 u_AlbedoColor;
|
uniform vec3 u_AlbedoColor;
|
||||||
uniform float u_Metalness;
|
uniform float u_Metalness;
|
||||||
uniform float u_Roughness;
|
uniform float u_Roughness;
|
||||||
@ -95,7 +132,6 @@ uniform float u_Roughness;
|
|||||||
uniform float u_EnvMapRotation;
|
uniform float u_EnvMapRotation;
|
||||||
|
|
||||||
// Toggles
|
// Toggles
|
||||||
uniform float u_RadiancePrefilter;
|
|
||||||
uniform float u_AlbedoTexToggle;
|
uniform float u_AlbedoTexToggle;
|
||||||
uniform float u_NormalTexToggle;
|
uniform float u_NormalTexToggle;
|
||||||
uniform float u_MetalnessTexToggle;
|
uniform float u_MetalnessTexToggle;
|
||||||
@ -246,8 +282,8 @@ vec3 Lighting(vec3 F0)
|
|||||||
vec3 result = vec3(0.0);
|
vec3 result = vec3(0.0);
|
||||||
for(int i = 0; i < LightCount; i++)
|
for(int i = 0; i < LightCount; i++)
|
||||||
{
|
{
|
||||||
vec3 Li = -lights.Direction;
|
vec3 Li = u_DirectionalLights.Direction;
|
||||||
vec3 Lradiance = lights.Radiance * lights.Multiplier;
|
vec3 Lradiance = u_DirectionalLights.Radiance * u_DirectionalLights.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.
|
||||||
@ -273,7 +309,6 @@ 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 = 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;
|
||||||
|
|
||||||
@ -289,6 +324,181 @@ vec3 IBL(vec3 F0, vec3 Lr)
|
|||||||
return kd * diffuseIBL + specularIBL;
|
return kd * diffuseIBL + specularIBL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////
|
||||||
|
// PCSS
|
||||||
|
/////////////////////////////////////////////
|
||||||
|
|
||||||
|
uint CascadeIndex = 0;
|
||||||
|
float ShadowFade = 1.0;
|
||||||
|
|
||||||
|
float GetShadowBias()
|
||||||
|
{
|
||||||
|
const float MINIMUM_SHADOW_BIAS = 0.002;
|
||||||
|
float bias = max(MINIMUM_SHADOW_BIAS * (1.0 - dot(m_Params.Normal, u_DirectionalLights.Direction)), MINIMUM_SHADOW_BIAS);
|
||||||
|
return bias;
|
||||||
|
}
|
||||||
|
|
||||||
|
float HardShadows_DirectionalLight(sampler2D shadowMap, vec3 shadowCoords)
|
||||||
|
{
|
||||||
|
float bias = GetShadowBias();
|
||||||
|
float z = texture(shadowMap, shadowCoords.xy).x;
|
||||||
|
return 1.0 - step(z + bias, shadowCoords.z) * ShadowFade;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Penumbra
|
||||||
|
|
||||||
|
// this search area estimation comes from the following article:
|
||||||
|
// http://developer.download.nvidia.com/whitepapers/2008/PCSS_DirectionalLight_Integration.pdf
|
||||||
|
float SearchWidth(float uvLightSize, float receiverDistance)
|
||||||
|
{
|
||||||
|
const float NEAR = 0.1;
|
||||||
|
return uvLightSize * (receiverDistance - NEAR) / u_CameraPosition.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
float u_light_zNear = 0.0; // 0.01 gives artifacts? maybe because of ortho proj?
|
||||||
|
float u_light_zFar = 10000.0;
|
||||||
|
vec2 u_lightRadiusUV = vec2(0.05);
|
||||||
|
|
||||||
|
vec2 searchRegionRadiusUV(float zWorld)
|
||||||
|
{
|
||||||
|
return u_lightRadiusUV * (zWorld - u_light_zNear) / zWorld;
|
||||||
|
}
|
||||||
|
|
||||||
|
const vec2 PoissonDistribution[64] = vec2[](
|
||||||
|
vec2(-0.884081, 0.124488),
|
||||||
|
vec2(-0.714377, 0.027940),
|
||||||
|
vec2(-0.747945, 0.227922),
|
||||||
|
vec2(-0.939609, 0.243634),
|
||||||
|
vec2(-0.985465, 0.045534),
|
||||||
|
vec2(-0.861367, -0.136222),
|
||||||
|
vec2(-0.881934, 0.396908),
|
||||||
|
vec2(-0.466938, 0.014526),
|
||||||
|
vec2(-0.558207, 0.212662),
|
||||||
|
vec2(-0.578447, -0.095822),
|
||||||
|
vec2(-0.740266, -0.095631),
|
||||||
|
vec2(-0.751681, 0.472604),
|
||||||
|
vec2(-0.553147, -0.243177),
|
||||||
|
vec2(-0.674762, -0.330730),
|
||||||
|
vec2(-0.402765, -0.122087),
|
||||||
|
vec2(-0.319776, -0.312166),
|
||||||
|
vec2(-0.413923, -0.439757),
|
||||||
|
vec2(-0.979153, -0.201245),
|
||||||
|
vec2(-0.865579, -0.288695),
|
||||||
|
vec2(-0.243704, -0.186378),
|
||||||
|
vec2(-0.294920, -0.055748),
|
||||||
|
vec2(-0.604452, -0.544251),
|
||||||
|
vec2(-0.418056, -0.587679),
|
||||||
|
vec2(-0.549156, -0.415877),
|
||||||
|
vec2(-0.238080, -0.611761),
|
||||||
|
vec2(-0.267004, -0.459702),
|
||||||
|
vec2(-0.100006, -0.229116),
|
||||||
|
vec2(-0.101928, -0.380382),
|
||||||
|
vec2(-0.681467, -0.700773),
|
||||||
|
vec2(-0.763488, -0.543386),
|
||||||
|
vec2(-0.549030, -0.750749),
|
||||||
|
vec2(-0.809045, -0.408738),
|
||||||
|
vec2(-0.388134, -0.773448),
|
||||||
|
vec2(-0.429392, -0.894892),
|
||||||
|
vec2(-0.131597, 0.065058),
|
||||||
|
vec2(-0.275002, 0.102922),
|
||||||
|
vec2(-0.106117, -0.068327),
|
||||||
|
vec2(-0.294586, -0.891515),
|
||||||
|
vec2(-0.629418, 0.379387),
|
||||||
|
vec2(-0.407257, 0.339748),
|
||||||
|
vec2(0.071650, -0.384284),
|
||||||
|
vec2(0.022018, -0.263793),
|
||||||
|
vec2(0.003879, -0.136073),
|
||||||
|
vec2(-0.137533, -0.767844),
|
||||||
|
vec2(-0.050874, -0.906068),
|
||||||
|
vec2(0.114133, -0.070053),
|
||||||
|
vec2(0.163314, -0.217231),
|
||||||
|
vec2(-0.100262, -0.587992),
|
||||||
|
vec2(-0.004942, 0.125368),
|
||||||
|
vec2(0.035302, -0.619310),
|
||||||
|
vec2(0.195646, -0.459022),
|
||||||
|
vec2(0.303969, -0.346362),
|
||||||
|
vec2(-0.678118, 0.685099),
|
||||||
|
vec2(-0.628418, 0.507978),
|
||||||
|
vec2(-0.508473, 0.458753),
|
||||||
|
vec2(0.032134, -0.782030),
|
||||||
|
vec2(0.122595, 0.280353),
|
||||||
|
vec2(-0.043643, 0.312119),
|
||||||
|
vec2(0.132993, 0.085170),
|
||||||
|
vec2(-0.192106, 0.285848),
|
||||||
|
vec2(0.183621, -0.713242),
|
||||||
|
vec2(0.265220, -0.596716),
|
||||||
|
vec2(-0.009628, -0.483058),
|
||||||
|
vec2(-0.018516, 0.435703)
|
||||||
|
);
|
||||||
|
|
||||||
|
vec2 SamplePoisson(int index)
|
||||||
|
{
|
||||||
|
return PoissonDistribution[index % 64];
|
||||||
|
}
|
||||||
|
|
||||||
|
float FindBlockerDistance_DirectionalLight(sampler2D shadowMap, vec3 shadowCoords, float uvLightSize)
|
||||||
|
{
|
||||||
|
float bias = GetShadowBias();
|
||||||
|
|
||||||
|
int numBlockerSearchSamples = 64;
|
||||||
|
int blockers = 0;
|
||||||
|
float avgBlockerDistance = 0;
|
||||||
|
|
||||||
|
float zEye = -(u_LightView * vec4(vs_Input.WorldPosition, 1.0)).z;
|
||||||
|
vec2 searchWidth = searchRegionRadiusUV(zEye);
|
||||||
|
for (int i = 0; i < numBlockerSearchSamples; i++)
|
||||||
|
{
|
||||||
|
float z = texture(shadowMap, shadowCoords.xy + SamplePoisson(i) * searchWidth).r;
|
||||||
|
if (z < (shadowCoords.z - bias))
|
||||||
|
{
|
||||||
|
blockers++;
|
||||||
|
avgBlockerDistance += z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (blockers > 0)
|
||||||
|
return avgBlockerDistance / float(blockers);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
float PenumbraWidth(sampler2D shadowMap, vec3 shadowCoords, float uvLightSize)
|
||||||
|
{
|
||||||
|
float blockerDistance = FindBlockerDistance_DirectionalLight(shadowMap, shadowCoords, uvLightSize);
|
||||||
|
if (blockerDistance == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return (shadowCoords.z - blockerDistance) / blockerDistance;
|
||||||
|
}
|
||||||
|
|
||||||
|
float PCF_DirectionalLight(sampler2D shadowMap, vec3 shadowCoords, float uvRadius)
|
||||||
|
{
|
||||||
|
float bias = GetShadowBias();
|
||||||
|
int numPCFSamples = 64;
|
||||||
|
float sum = 0;
|
||||||
|
for (int i = 0; i < numPCFSamples; i++)
|
||||||
|
{
|
||||||
|
float z = texture(shadowMap, shadowCoords.xy + SamplePoisson(i) * uvRadius).r;
|
||||||
|
sum += (z < (shadowCoords.z - bias)) ? 1 : 0;
|
||||||
|
}
|
||||||
|
return sum / numPCFSamples;
|
||||||
|
}
|
||||||
|
|
||||||
|
float PCSS_DirectionalLight(sampler2D shadowMap, vec3 shadowCoords, float uvLightSize)
|
||||||
|
{
|
||||||
|
float blockerDistance = FindBlockerDistance_DirectionalLight(shadowMap, shadowCoords, uvLightSize);
|
||||||
|
if (blockerDistance == -1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
float penumbraWidth = (shadowCoords.z - blockerDistance) / blockerDistance;
|
||||||
|
|
||||||
|
float NEAR = 0.01; // Should this value be tweakable?
|
||||||
|
float uvRadius = penumbraWidth * uvLightSize * NEAR / shadowCoords.z;
|
||||||
|
return 1.0 - PCF_DirectionalLight(shadowMap, shadowCoords, uvRadius) * ShadowFade;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
// Standard PBR inputs
|
// Standard PBR inputs
|
||||||
@ -314,9 +524,102 @@ 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 = Lighting(F0);
|
const uint SHADOW_MAP_CASCADE_COUNT = 4;
|
||||||
vec3 iblContribution = IBL(F0, Lr);
|
for(uint i = 0; i < SHADOW_MAP_CASCADE_COUNT - 1; i++)
|
||||||
|
{
|
||||||
|
if(vs_Input.ViewPosition.z < u_CascadeSplits[i])
|
||||||
|
CascadeIndex = i + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
float shadowDistance = u_MaxShadowDistance;//u_CascadeSplits[3];
|
||||||
|
float transitionDistance = u_ShadowFade;
|
||||||
|
float distance = length(vs_Input.ViewPosition);
|
||||||
|
ShadowFade = distance - (shadowDistance - transitionDistance);
|
||||||
|
ShadowFade /= transitionDistance;
|
||||||
|
ShadowFade = clamp(1.0 - ShadowFade, 0.0, 1.0);
|
||||||
|
|
||||||
|
bool fadeCascades = u_CascadeFading;
|
||||||
|
float shadowAmount = 1.0;
|
||||||
|
if (fadeCascades)
|
||||||
|
{
|
||||||
|
float cascadeTransitionFade = u_CascadeTransitionFade;
|
||||||
|
|
||||||
|
float c0 = smoothstep(u_CascadeSplits[0] + cascadeTransitionFade * 0.5f, u_CascadeSplits[0] - cascadeTransitionFade * 0.5f, vs_Input.ViewPosition.z);
|
||||||
|
float c1 = smoothstep(u_CascadeSplits[1] + cascadeTransitionFade * 0.5f, u_CascadeSplits[1] - cascadeTransitionFade * 0.5f, vs_Input.ViewPosition.z);
|
||||||
|
float c2 = smoothstep(u_CascadeSplits[2] + cascadeTransitionFade * 0.5f, u_CascadeSplits[2] - cascadeTransitionFade * 0.5f, vs_Input.ViewPosition.z);
|
||||||
|
if (c0 > 0.0 && c0 < 1.0)
|
||||||
|
{
|
||||||
|
// Sample 0 & 1
|
||||||
|
vec3 shadowMapCoords = (vs_Input.ShadowMapCoords[0].xyz / vs_Input.ShadowMapCoords[0].w);
|
||||||
|
float shadowAmount0 = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[0], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[0], shadowMapCoords);
|
||||||
|
shadowMapCoords = (vs_Input.ShadowMapCoords[1].xyz / vs_Input.ShadowMapCoords[1].w);
|
||||||
|
float shadowAmount1 = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[1], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[1], shadowMapCoords);
|
||||||
|
|
||||||
|
shadowAmount = mix(shadowAmount0, shadowAmount1, c0);
|
||||||
|
}
|
||||||
|
else if (c1 > 0.0 && c1 < 1.0)
|
||||||
|
{
|
||||||
|
// Sample 1 & 2
|
||||||
|
vec3 shadowMapCoords = (vs_Input.ShadowMapCoords[1].xyz / vs_Input.ShadowMapCoords[1].w);
|
||||||
|
float shadowAmount1 = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[1], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[1], shadowMapCoords);
|
||||||
|
shadowMapCoords = (vs_Input.ShadowMapCoords[2].xyz / vs_Input.ShadowMapCoords[2].w);
|
||||||
|
float shadowAmount2 = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[2], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[2], shadowMapCoords);
|
||||||
|
|
||||||
|
shadowAmount = mix(shadowAmount1, shadowAmount2, c1);
|
||||||
|
}
|
||||||
|
else if (c2 > 0.0 && c2 < 1.0)
|
||||||
|
{
|
||||||
|
// Sample 2 & 3
|
||||||
|
vec3 shadowMapCoords = (vs_Input.ShadowMapCoords[2].xyz / vs_Input.ShadowMapCoords[2].w);
|
||||||
|
float shadowAmount2 = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[2], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[2], shadowMapCoords);
|
||||||
|
shadowMapCoords = (vs_Input.ShadowMapCoords[3].xyz / vs_Input.ShadowMapCoords[3].w);
|
||||||
|
float shadowAmount3 = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[3], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[3], shadowMapCoords);
|
||||||
|
|
||||||
|
shadowAmount = mix(shadowAmount2, shadowAmount3, c2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vec3 shadowMapCoords = (vs_Input.ShadowMapCoords[CascadeIndex].xyz / vs_Input.ShadowMapCoords[CascadeIndex].w);
|
||||||
|
shadowAmount = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[CascadeIndex], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[CascadeIndex], shadowMapCoords);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vec3 shadowMapCoords = (vs_Input.ShadowMapCoords[CascadeIndex].xyz / vs_Input.ShadowMapCoords[CascadeIndex].w);
|
||||||
|
shadowAmount = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[CascadeIndex], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[CascadeIndex], shadowMapCoords);
|
||||||
|
}
|
||||||
|
|
||||||
|
float NdotL = dot(m_Params.Normal, u_DirectionalLights.Direction);
|
||||||
|
NdotL = smoothstep(0.0, 0.4, NdotL + 0.2);
|
||||||
|
shadowAmount *= (NdotL * 1.0);
|
||||||
|
|
||||||
|
vec3 iblContribution = IBL(F0, Lr) * u_IBLContribution;
|
||||||
|
vec3 lightContribution = u_DirectionalLights.Multiplier > 0.0f ? (Lighting(F0) * shadowAmount) : vec3(0.0f);
|
||||||
|
|
||||||
color = vec4(lightContribution + iblContribution, 1.0);
|
color = vec4(lightContribution + iblContribution, 1.0);
|
||||||
// color = vec4(iblContribution, 1.0);
|
|
||||||
|
// Bloom
|
||||||
|
float brightness = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722));
|
||||||
|
o_BloomColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
if (brightness > u_BloomThreshold)
|
||||||
|
o_BloomColor = color;
|
||||||
|
|
||||||
|
if (u_ShowCascades)
|
||||||
|
{
|
||||||
|
switch(CascadeIndex)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
color.rgb *= vec3(1.0f, 0.25f, 0.25f);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
color.rgb *= vec3(0.25f, 1.0f, 0.25f);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
color.rgb *= vec3(0.25f, 0.25f, 1.0f);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
color.rgb *= vec3(1.0f, 1.0f, 0.25f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,20 +17,34 @@ void main()
|
|||||||
#version 430
|
#version 430
|
||||||
|
|
||||||
layout(location = 0) out vec4 o_Color;
|
layout(location = 0) out vec4 o_Color;
|
||||||
|
layout(location = 1) out vec4 o_BloomTexture;
|
||||||
|
|
||||||
in vec2 v_TexCoord;
|
in vec2 v_TexCoord;
|
||||||
|
|
||||||
uniform sampler2DMS u_Texture;
|
uniform sampler2DMS u_Texture;
|
||||||
|
|
||||||
uniform float u_Exposure;
|
uniform float u_Exposure;
|
||||||
uniform int u_TextureSamples;
|
uniform int u_TextureSamples;
|
||||||
|
|
||||||
vec4 MultiSampleTexture(sampler2DMS tex, ivec2 texCoord, int samples)
|
uniform bool u_EnableBloom;
|
||||||
|
uniform float u_BloomThreshold;
|
||||||
|
|
||||||
|
const float uFar = 1.0;
|
||||||
|
|
||||||
|
vec4 SampleTexture(sampler2D tex, vec2 texCoord)
|
||||||
{
|
{
|
||||||
|
return texture(tex, texCoord);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 MultiSampleTexture(sampler2DMS tex, vec2 tc)
|
||||||
|
{
|
||||||
|
ivec2 texSize = textureSize(tex);
|
||||||
|
ivec2 texCoord = ivec2(tc * texSize);
|
||||||
vec4 result = vec4(0.0);
|
vec4 result = vec4(0.0);
|
||||||
for (int i = 0; i < samples; i++)
|
for (int i = 0; i < u_TextureSamples; i++)
|
||||||
result += texelFetch(tex, texCoord, i);
|
result += texelFetch(tex, texCoord, i);
|
||||||
|
|
||||||
result /= float(samples);
|
result /= float(u_TextureSamples);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,10 +53,18 @@ void main()
|
|||||||
const float gamma = 2.2;
|
const float gamma = 2.2;
|
||||||
const float pureWhite = 1.0;
|
const float pureWhite = 1.0;
|
||||||
|
|
||||||
ivec2 texSize = textureSize(u_Texture);
|
// Tonemapping
|
||||||
ivec2 texCoord = ivec2(v_TexCoord * texSize);
|
vec4 msColor = MultiSampleTexture(u_Texture, v_TexCoord);
|
||||||
vec4 msColor = MultiSampleTexture(u_Texture, texCoord, u_TextureSamples);
|
|
||||||
vec3 color = msColor.rgb * u_Exposure;//texture(u_Texture, v_TexCoord).rgb * u_Exposure;
|
vec3 color = msColor.rgb;
|
||||||
|
|
||||||
|
if (u_EnableBloom)
|
||||||
|
{
|
||||||
|
vec3 bloomColor = MultiSampleTexture(u_Texture, v_TexCoord).rgb;
|
||||||
|
color += bloomColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
color *= u_Exposure;
|
||||||
|
|
||||||
// Reinhard tonemapping operator.
|
// Reinhard tonemapping operator.
|
||||||
// see: "Photographic Tone Reproduction for Digital Images", eq. 4
|
// see: "Photographic Tone Reproduction for Digital Images", eq. 4
|
||||||
@ -54,4 +76,8 @@ void main()
|
|||||||
|
|
||||||
// Gamma correction.
|
// Gamma correction.
|
||||||
o_Color = vec4(pow(mappedColor, vec3(1.0 / gamma)), 1.0);
|
o_Color = vec4(pow(mappedColor, vec3(1.0 / gamma)), 1.0);
|
||||||
|
|
||||||
|
// Show over-exposed areas
|
||||||
|
// if (o_Color.r > 1.0 || o_Color.g > 1.0 || o_Color.b > 1.0)
|
||||||
|
// o_Color.rgb *= vec3(1.0, 0.25, 0.25);
|
||||||
}
|
}
|
||||||
23
Editor/assets/shaders/ShadowMap.glsl
Normal file
23
Editor/assets/shaders/ShadowMap.glsl
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Shadow Map shader
|
||||||
|
|
||||||
|
#type vertex
|
||||||
|
#version 430
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 a_Position;
|
||||||
|
|
||||||
|
uniform mat4 u_ViewProjection;
|
||||||
|
uniform mat4 u_Transform;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = u_ViewProjection * u_Transform * vec4(a_Position, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#type fragment
|
||||||
|
#version 430
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 o_Color;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
}
|
||||||
35
Editor/assets/shaders/ShadowMap_Anim.glsl
Normal file
35
Editor/assets/shaders/ShadowMap_Anim.glsl
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// Shadow Map shader
|
||||||
|
|
||||||
|
#type vertex
|
||||||
|
#version 430
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 a_Position;
|
||||||
|
|
||||||
|
layout(location = 5) in ivec4 a_BoneIndices;
|
||||||
|
layout(location = 6) in vec4 a_BoneWeights;
|
||||||
|
|
||||||
|
uniform mat4 u_ViewProjection;
|
||||||
|
uniform mat4 u_Transform;
|
||||||
|
|
||||||
|
const int MAX_BONES = 100;
|
||||||
|
uniform mat4 u_BoneTransforms[100];
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
mat4 boneTransform = u_BoneTransforms[a_BoneIndices[0]] * a_BoneWeights[0];
|
||||||
|
boneTransform += u_BoneTransforms[a_BoneIndices[1]] * a_BoneWeights[1];
|
||||||
|
boneTransform += u_BoneTransforms[a_BoneIndices[2]] * a_BoneWeights[2];
|
||||||
|
boneTransform += u_BoneTransforms[a_BoneIndices[3]] * a_BoneWeights[3];
|
||||||
|
|
||||||
|
vec4 localPosition = boneTransform * vec4(a_Position, 1.0);
|
||||||
|
gl_Position = u_ViewProjection * u_Transform * localPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
#type fragment
|
||||||
|
#version 430
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 o_Color;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
}
|
||||||
@ -24,10 +24,13 @@ layout(location = 0) out vec4 finalColor;
|
|||||||
|
|
||||||
uniform samplerCube u_Texture;
|
uniform samplerCube u_Texture;
|
||||||
uniform float u_TextureLod;
|
uniform float u_TextureLod;
|
||||||
|
uniform float u_SkyIntensity;
|
||||||
|
|
||||||
in vec3 v_Position;
|
in vec3 v_Position;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
finalColor = textureLod(u_Texture, v_Position, u_TextureLod);
|
vec3 color = textureLod(u_Texture, v_Position, u_TextureLod).rgb * u_SkyIntensity;
|
||||||
|
finalColor = vec4(color, 1.0);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -121,7 +121,7 @@ namespace FPSExample
|
|||||||
|
|
||||||
private void UpdateCameraTransform(){
|
private void UpdateCameraTransform(){
|
||||||
Vec3 position = m_Transform.Position;
|
Vec3 position = m_Transform.Position;
|
||||||
position.Y += 1.5f;
|
position.Y += m_Transform.Position.Y + 1.5f;
|
||||||
m_CameraTransform.Position = position;
|
m_CameraTransform.Position = position;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,6 +31,8 @@ namespace Prism
|
|||||||
|
|
||||||
m_Window = std::unique_ptr<Window>(Window::Create(WindowProps{props.Name, props.Width, props.Height}));
|
m_Window = std::unique_ptr<Window>(Window::Create(WindowProps{props.Name, props.Width, props.Height}));
|
||||||
m_Window->SetEventCallback(BIND_EVENT_FN(OnEvent));
|
m_Window->SetEventCallback(BIND_EVENT_FN(OnEvent));
|
||||||
|
m_Window->SetVSync(true);
|
||||||
|
m_Window->Maximize();
|
||||||
|
|
||||||
m_ImGuiLayer = new ImGuiLayer("ImGui Layer");
|
m_ImGuiLayer = new ImGuiLayer("ImGui Layer");
|
||||||
PushOverlay(m_ImGuiLayer);
|
PushOverlay(m_ImGuiLayer);
|
||||||
|
|||||||
273
Prism/src/Prism/Core/ImGui/ImGui.h
Normal file
273
Prism/src/Prism/Core/ImGui/ImGui.h
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
//
|
||||||
|
// Created by sfd on 26-1-1.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef IMGUI_H
|
||||||
|
#define IMGUI_H
|
||||||
|
#include <cstdint>
|
||||||
|
#include <imgui.h>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
|
namespace Prism::UI {
|
||||||
|
|
||||||
|
static int s_UIContextID = 0;
|
||||||
|
static uint32_t s_Counter = 0;
|
||||||
|
static char s_IDBuffer[16];
|
||||||
|
|
||||||
|
static void PushID()
|
||||||
|
{
|
||||||
|
ImGui::PushID(s_UIContextID++);
|
||||||
|
s_Counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PopID()
|
||||||
|
{
|
||||||
|
ImGui::PopID();
|
||||||
|
s_UIContextID--;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void BeginPropertyGrid()
|
||||||
|
{
|
||||||
|
PushID();
|
||||||
|
ImGui::Columns(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Property(const char* label, std::string& value, const bool error = false)
|
||||||
|
{
|
||||||
|
bool modified = false;
|
||||||
|
|
||||||
|
ImGui::Text(label);
|
||||||
|
ImGui::NextColumn();
|
||||||
|
ImGui::PushItemWidth(-1);
|
||||||
|
|
||||||
|
char buffer[256];
|
||||||
|
snprintf(buffer, sizeof(buffer), "%s", value.c_str());
|
||||||
|
|
||||||
|
s_IDBuffer[0] = '#';
|
||||||
|
s_IDBuffer[1] = '#';
|
||||||
|
memset(s_IDBuffer + 2, 0, 14);
|
||||||
|
snprintf(s_IDBuffer + 2, 14, "%x", s_Counter++);
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.9f, 0.2f, 0.2f, 1.0f));
|
||||||
|
if (ImGui::InputText(s_IDBuffer, buffer, 256))
|
||||||
|
{
|
||||||
|
value = buffer;
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
if (error)
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::NextColumn();
|
||||||
|
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Property(const char* label, const char* value)
|
||||||
|
{
|
||||||
|
ImGui::Text(label);
|
||||||
|
ImGui::NextColumn();
|
||||||
|
ImGui::PushItemWidth(-1);
|
||||||
|
|
||||||
|
s_IDBuffer[0] = '#';
|
||||||
|
s_IDBuffer[1] = '#';
|
||||||
|
memset(s_IDBuffer + 2, 0, 14);
|
||||||
|
snprintf(s_IDBuffer + 2, 14, "%x", s_Counter++);
|
||||||
|
ImGui::InputText(s_IDBuffer, const_cast<char*>(value), 256, ImGuiInputTextFlags_ReadOnly);
|
||||||
|
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::NextColumn();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Property(const char* label, bool& value)
|
||||||
|
{
|
||||||
|
bool modified = false;
|
||||||
|
|
||||||
|
ImGui::Text(label);
|
||||||
|
ImGui::NextColumn();
|
||||||
|
ImGui::PushItemWidth(-1);
|
||||||
|
|
||||||
|
s_IDBuffer[0] = '#';
|
||||||
|
s_IDBuffer[1] = '#';
|
||||||
|
memset(s_IDBuffer + 2, 0, 14);
|
||||||
|
snprintf(s_IDBuffer + 2, 14, "%x", s_Counter++);
|
||||||
|
if (ImGui::Checkbox(s_IDBuffer, &value))
|
||||||
|
modified = true;
|
||||||
|
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::NextColumn();
|
||||||
|
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Property(const char* label, int& value)
|
||||||
|
{
|
||||||
|
bool modified = false;
|
||||||
|
|
||||||
|
ImGui::Text(label);
|
||||||
|
ImGui::NextColumn();
|
||||||
|
ImGui::PushItemWidth(-1);
|
||||||
|
|
||||||
|
s_IDBuffer[0] = '#';
|
||||||
|
s_IDBuffer[1] = '#';
|
||||||
|
memset(s_IDBuffer + 2, 0, 14);
|
||||||
|
snprintf(s_IDBuffer + 2, 14, "%x", s_Counter++);
|
||||||
|
if (ImGui::DragInt(s_IDBuffer, &value))
|
||||||
|
modified = true;
|
||||||
|
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::NextColumn();
|
||||||
|
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool PropertySlider(const char* label, int& value, const int min, const int max)
|
||||||
|
{
|
||||||
|
bool modified = false;
|
||||||
|
|
||||||
|
ImGui::Text(label);
|
||||||
|
ImGui::NextColumn();
|
||||||
|
ImGui::PushItemWidth(-1);
|
||||||
|
|
||||||
|
s_IDBuffer[0] = '#';
|
||||||
|
s_IDBuffer[1] = '#';
|
||||||
|
memset(s_IDBuffer + 2, 0, 14);
|
||||||
|
snprintf(s_IDBuffer + 2, 14, "%x", s_Counter++);
|
||||||
|
if (ImGui::SliderInt(s_IDBuffer, &value, min, max))
|
||||||
|
modified = true;
|
||||||
|
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::NextColumn();
|
||||||
|
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Property(const char* label, float& value, const float delta = 0.1f, const float min = 0.0f, const float max = 0.0f)
|
||||||
|
{
|
||||||
|
bool modified = false;
|
||||||
|
|
||||||
|
ImGui::Text(label);
|
||||||
|
ImGui::NextColumn();
|
||||||
|
ImGui::PushItemWidth(-1);
|
||||||
|
|
||||||
|
s_IDBuffer[0] = '#';
|
||||||
|
s_IDBuffer[1] = '#';
|
||||||
|
memset(s_IDBuffer + 2, 0, 14);
|
||||||
|
snprintf(s_IDBuffer + 2, 14, "%x", s_Counter++);
|
||||||
|
if (ImGui::DragFloat(s_IDBuffer, &value, delta, min, max))
|
||||||
|
modified = true;
|
||||||
|
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::NextColumn();
|
||||||
|
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Property(const char* label, glm::vec2& value, const float delta = 0.1f)
|
||||||
|
{
|
||||||
|
bool modified = false;
|
||||||
|
|
||||||
|
ImGui::Text(label);
|
||||||
|
ImGui::NextColumn();
|
||||||
|
ImGui::PushItemWidth(-1);
|
||||||
|
|
||||||
|
s_IDBuffer[0] = '#';
|
||||||
|
s_IDBuffer[1] = '#';
|
||||||
|
memset(s_IDBuffer + 2, 0, 14);
|
||||||
|
snprintf(s_IDBuffer + 2, 14, "%x", s_Counter++);
|
||||||
|
if (ImGui::DragFloat3(s_IDBuffer, glm::value_ptr(value), delta))
|
||||||
|
modified = true;
|
||||||
|
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::NextColumn();
|
||||||
|
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool PropertyColor(const char* label, glm::vec3& value)
|
||||||
|
{
|
||||||
|
bool modified = false;
|
||||||
|
|
||||||
|
ImGui::Text(label);
|
||||||
|
ImGui::NextColumn();
|
||||||
|
ImGui::PushItemWidth(-1);
|
||||||
|
|
||||||
|
s_IDBuffer[0] = '#';
|
||||||
|
s_IDBuffer[1] = '#';
|
||||||
|
memset(s_IDBuffer + 2, 0, 14);
|
||||||
|
snprintf(s_IDBuffer + 2, 14, "%x", s_Counter++);
|
||||||
|
if (ImGui::ColorEdit3(s_IDBuffer, glm::value_ptr(value)))
|
||||||
|
modified = true;
|
||||||
|
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::NextColumn();
|
||||||
|
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Property(const char* label, glm::vec3& value, const float delta = 0.1f)
|
||||||
|
{
|
||||||
|
bool modified = false;
|
||||||
|
|
||||||
|
ImGui::Text(label);
|
||||||
|
ImGui::NextColumn();
|
||||||
|
ImGui::PushItemWidth(-1);
|
||||||
|
|
||||||
|
s_IDBuffer[0] = '#';
|
||||||
|
s_IDBuffer[1] = '#';
|
||||||
|
memset(s_IDBuffer + 2, 0, 14);
|
||||||
|
snprintf(s_IDBuffer + 2, 14, "%x", s_Counter++);
|
||||||
|
if (ImGui::DragFloat3(s_IDBuffer, glm::value_ptr(value), delta))
|
||||||
|
modified = true;
|
||||||
|
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::NextColumn();
|
||||||
|
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Property(const char* label, glm::vec4& value, const float delta = 0.1f)
|
||||||
|
{
|
||||||
|
bool modified = false;
|
||||||
|
|
||||||
|
ImGui::Text(label);
|
||||||
|
ImGui::NextColumn();
|
||||||
|
ImGui::PushItemWidth(-1);
|
||||||
|
|
||||||
|
s_IDBuffer[0] = '#';
|
||||||
|
s_IDBuffer[1] = '#';
|
||||||
|
memset(s_IDBuffer + 2, 0, 14);
|
||||||
|
snprintf(s_IDBuffer + 2, 14, "%x", s_Counter++);
|
||||||
|
if (ImGui::DragFloat4(s_IDBuffer, glm::value_ptr(value), delta))
|
||||||
|
modified = true;
|
||||||
|
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::NextColumn();
|
||||||
|
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void EndPropertyGrid()
|
||||||
|
{
|
||||||
|
ImGui::Columns(1);
|
||||||
|
PopID();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool BeginTreeNode(const char* name, const bool defaultOpen = true)
|
||||||
|
{
|
||||||
|
ImGuiTreeNodeFlags treeNodeFlags = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_FramePadding;
|
||||||
|
if (defaultOpen)
|
||||||
|
treeNodeFlags |= ImGuiTreeNodeFlags_DefaultOpen;
|
||||||
|
|
||||||
|
return ImGui::TreeNodeEx(name, treeNodeFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void EndTreeNode()
|
||||||
|
{
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //IMGUI_H
|
||||||
@ -45,6 +45,8 @@ namespace Prism
|
|||||||
virtual void SetVSync(bool enable) = 0;
|
virtual void SetVSync(bool enable) = 0;
|
||||||
virtual bool const IsVSync() const = 0;
|
virtual bool const IsVSync() const = 0;
|
||||||
|
|
||||||
|
virtual void Maximize() = 0;
|
||||||
|
|
||||||
static Window* Create(const WindowProps& props);
|
static Window* Create(const WindowProps& props);
|
||||||
|
|
||||||
virtual const std::string& GetTitle() const = 0;
|
virtual const std::string& GetTitle() const = 0;
|
||||||
|
|||||||
@ -44,7 +44,8 @@ namespace Prism
|
|||||||
const glm::vec2& mouse{ Input::GetMouseX(), Input::GetMouseY() };
|
const glm::vec2& mouse{ Input::GetMouseX(), Input::GetMouseY() };
|
||||||
const glm::vec2 delta = (mouse - m_InitialMousePosition) * 0.003f;
|
const glm::vec2 delta = (mouse - m_InitialMousePosition) * 0.003f;
|
||||||
m_InitialMousePosition = mouse;
|
m_InitialMousePosition = mouse;
|
||||||
|
if (delta.x != 0.0f || delta.y != 0.0f)
|
||||||
|
{
|
||||||
if (Input::IsMouseButtonPressed(MouseButton::Middle))
|
if (Input::IsMouseButtonPressed(MouseButton::Middle))
|
||||||
MousePan(delta);
|
MousePan(delta);
|
||||||
else if (Input::IsMouseButtonPressed(MouseButton::Left))
|
else if (Input::IsMouseButtonPressed(MouseButton::Left))
|
||||||
@ -52,6 +53,7 @@ namespace Prism
|
|||||||
else if (Input::IsMouseButtonPressed(MouseButton::Right))
|
else if (Input::IsMouseButtonPressed(MouseButton::Right))
|
||||||
MouseZoom(delta.y);
|
MouseZoom(delta.y);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
UpdateCameraView();
|
UpdateCameraView();
|
||||||
}
|
}
|
||||||
@ -77,6 +79,19 @@ 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 EditorCamera::OnImGuiRender()
|
||||||
|
{
|
||||||
|
ImGui::Begin("Camera Info");
|
||||||
|
UI::Property("yaw", m_Yaw);
|
||||||
|
UI::Property("pitch", m_Pitch);
|
||||||
|
UI::Property("focus", m_FocalPoint);
|
||||||
|
UI::Property("distance", m_Distance);
|
||||||
|
UI::Property("rotation", m_Rotation);
|
||||||
|
UI::Property("focus", m_FocalPoint);
|
||||||
|
UI::Property("position", m_Position);
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
void EditorCamera::UpdateCameraView()
|
void EditorCamera::UpdateCameraView()
|
||||||
{
|
{
|
||||||
m_Position = CalculatePosition();
|
m_Position = CalculatePosition();
|
||||||
|
|||||||
@ -40,12 +40,11 @@ namespace Prism
|
|||||||
const glm::vec3& GetPosition() const { return m_Position; }
|
const glm::vec3& GetPosition() const { return m_Position; }
|
||||||
glm::quat GetOrientation() const;
|
glm::quat GetOrientation() const;
|
||||||
|
|
||||||
float GetExposure() const { return m_Exposure; }
|
|
||||||
float& GetExposure() { return m_Exposure; }
|
|
||||||
|
|
||||||
float GetPitch() const { return m_Pitch; }
|
float GetPitch() const { return m_Pitch; }
|
||||||
float GetYaw() const { return m_Yaw; }
|
float GetYaw() const { return m_Yaw; }
|
||||||
|
|
||||||
|
void OnImGuiRender();
|
||||||
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:
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include "imgui_internal.h"
|
#include "imgui_internal.h"
|
||||||
|
#include "Prism/Core/ImGui/imgui.h"
|
||||||
#include "Prism/Physics/Physics3D.h"
|
#include "Prism/Physics/Physics3D.h"
|
||||||
#include "Prism/Physics/PhysicsLayer.h"
|
#include "Prism/Physics/PhysicsLayer.h"
|
||||||
|
|
||||||
|
|||||||
@ -167,9 +167,34 @@ namespace Prism
|
|||||||
|
|
||||||
if (ImGui::BeginPopupContextWindow())
|
if (ImGui::BeginPopupContextWindow())
|
||||||
{
|
{
|
||||||
if (ImGui::MenuItem("Create Empty Entity"))
|
|
||||||
|
if (ImGui::BeginMenu("Create"))
|
||||||
{
|
{
|
||||||
m_Context->CreateEntity("Empty Entity");
|
if (ImGui::MenuItem("Empty Entity"))
|
||||||
|
{
|
||||||
|
auto newEntity = m_Context->CreateEntity("Empty Entity");
|
||||||
|
SetSelected(newEntity);
|
||||||
|
}
|
||||||
|
if (ImGui::MenuItem("Mesh"))
|
||||||
|
{
|
||||||
|
auto newEntity = m_Context->CreateEntity("Mesh");
|
||||||
|
newEntity.AddComponent<MeshComponent>();
|
||||||
|
SetSelected(newEntity);
|
||||||
|
}
|
||||||
|
ImGui::Separator();
|
||||||
|
if (ImGui::MenuItem("Directional Light"))
|
||||||
|
{
|
||||||
|
auto newEntity = m_Context->CreateEntity("Directional Light");
|
||||||
|
newEntity.AddComponent<DirectionalLightComponent>();
|
||||||
|
SetSelected(newEntity);
|
||||||
|
}
|
||||||
|
if (ImGui::MenuItem("Sky Light"))
|
||||||
|
{
|
||||||
|
auto newEntity = m_Context->CreateEntity("Sky Light");
|
||||||
|
newEntity.AddComponent<SkyLightComponent>();
|
||||||
|
SetSelected(newEntity);
|
||||||
|
}
|
||||||
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
@ -322,224 +347,6 @@ namespace Prism
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int s_UIContextID = 0;
|
|
||||||
static uint32_t s_Counter = 0;
|
|
||||||
static char s_IDBuffer[16];
|
|
||||||
|
|
||||||
static void PushID()
|
|
||||||
{
|
|
||||||
ImGui::PushID(s_UIContextID++);
|
|
||||||
s_Counter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void PopID()
|
|
||||||
{
|
|
||||||
ImGui::PopID();
|
|
||||||
s_UIContextID--;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void BeginPropertyGrid()
|
|
||||||
{
|
|
||||||
PushID();
|
|
||||||
ImGui::Columns(2);
|
|
||||||
ImGui::SetColumnWidth(0, 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool Property(const char* label, std::string& value, bool error = false)
|
|
||||||
{
|
|
||||||
bool modified = false;
|
|
||||||
|
|
||||||
ImGui::Text(label);
|
|
||||||
ImGui::NextColumn();
|
|
||||||
ImGui::PushItemWidth(-1);
|
|
||||||
|
|
||||||
char buffer[256];
|
|
||||||
snprintf(buffer, sizeof(buffer), "%s", value.c_str());
|
|
||||||
|
|
||||||
s_IDBuffer[0] = '#';
|
|
||||||
s_IDBuffer[1] = '#';
|
|
||||||
memset(s_IDBuffer + 2, 0, 14);
|
|
||||||
// itoa(s_Counter++, s_IDBuffer + 2, 16);
|
|
||||||
snprintf(s_IDBuffer + 2, 14, "%x", s_Counter++);
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.9f, 0.2f, 0.2f, 1.0f));
|
|
||||||
|
|
||||||
if (ImGui::InputText(s_IDBuffer, buffer, 256))
|
|
||||||
{
|
|
||||||
value = buffer;
|
|
||||||
modified = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
ImGui::PopStyleColor();
|
|
||||||
|
|
||||||
ImGui::PopItemWidth();
|
|
||||||
ImGui::NextColumn();
|
|
||||||
|
|
||||||
return modified;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Property(const char* label, const char* value)
|
|
||||||
{
|
|
||||||
ImGui::Text(label);
|
|
||||||
ImGui::NextColumn();
|
|
||||||
ImGui::PushItemWidth(-1);
|
|
||||||
|
|
||||||
s_IDBuffer[0] = '#';
|
|
||||||
s_IDBuffer[1] = '#';
|
|
||||||
memset(s_IDBuffer + 2, 0, 14);
|
|
||||||
// itoa(s_Counter++, s_IDBuffer + 2, 16);
|
|
||||||
snprintf(s_IDBuffer + 2, 14, "%x", s_Counter++);
|
|
||||||
|
|
||||||
ImGui::InputText(s_IDBuffer, (char*)value, 256, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
ImGui::PopItemWidth();
|
|
||||||
ImGui::NextColumn();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool Property(const char* label, bool& value)
|
|
||||||
{
|
|
||||||
bool modified = false;
|
|
||||||
|
|
||||||
ImGui::Text(label);
|
|
||||||
ImGui::NextColumn();
|
|
||||||
ImGui::PushItemWidth(-1);
|
|
||||||
|
|
||||||
s_IDBuffer[0] = '#';
|
|
||||||
s_IDBuffer[1] = '#';
|
|
||||||
memset(s_IDBuffer + 2, 0, 14);
|
|
||||||
// itoa(s_Counter++, s_IDBuffer + 2, 16);
|
|
||||||
snprintf(s_IDBuffer + 2, 14, "%x", s_Counter++);
|
|
||||||
if (ImGui::Checkbox(s_IDBuffer, &value))
|
|
||||||
modified = true;
|
|
||||||
|
|
||||||
ImGui::PopItemWidth();
|
|
||||||
ImGui::NextColumn();
|
|
||||||
|
|
||||||
return modified;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool Property(const char* label, int& value)
|
|
||||||
{
|
|
||||||
bool modified = false;
|
|
||||||
|
|
||||||
ImGui::Text(label);
|
|
||||||
ImGui::NextColumn();
|
|
||||||
ImGui::PushItemWidth(-1);
|
|
||||||
|
|
||||||
s_IDBuffer[0] = '#';
|
|
||||||
s_IDBuffer[1] = '#';
|
|
||||||
memset(s_IDBuffer + 2, 0, 14);
|
|
||||||
// itoa(s_Counter++, s_IDBuffer + 2, 16);
|
|
||||||
snprintf(s_IDBuffer + 2, 14, "%x", s_Counter++);
|
|
||||||
|
|
||||||
if (ImGui::DragInt(s_IDBuffer, &value))
|
|
||||||
modified = true;
|
|
||||||
|
|
||||||
ImGui::PopItemWidth();
|
|
||||||
ImGui::NextColumn();
|
|
||||||
|
|
||||||
return modified;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool Property(const char* label, float& value, float delta = 0.1f, float min = 0.0f, float max = 0.0f)
|
|
||||||
{
|
|
||||||
bool modified = false;
|
|
||||||
|
|
||||||
ImGui::Text(label);
|
|
||||||
ImGui::NextColumn();
|
|
||||||
ImGui::PushItemWidth(-1);
|
|
||||||
|
|
||||||
s_IDBuffer[0] = '#';
|
|
||||||
s_IDBuffer[1] = '#';
|
|
||||||
memset(s_IDBuffer + 2, 0, 14);
|
|
||||||
// itoa(s_Counter++, s_IDBuffer + 2, 16);
|
|
||||||
snprintf(s_IDBuffer + 2, 14, "%x", s_Counter++);
|
|
||||||
|
|
||||||
if (ImGui::DragFloat(s_IDBuffer, &value, delta, min, max))
|
|
||||||
modified = true;
|
|
||||||
|
|
||||||
ImGui::PopItemWidth();
|
|
||||||
ImGui::NextColumn();
|
|
||||||
|
|
||||||
return modified;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool Property(const char* label, glm::vec2& value, float delta = 0.1f)
|
|
||||||
{
|
|
||||||
bool modified = false;
|
|
||||||
|
|
||||||
ImGui::Text(label);
|
|
||||||
ImGui::NextColumn();
|
|
||||||
ImGui::PushItemWidth(-1);
|
|
||||||
|
|
||||||
s_IDBuffer[0] = '#';
|
|
||||||
s_IDBuffer[1] = '#';
|
|
||||||
memset(s_IDBuffer + 2, 0, 14);
|
|
||||||
// itoa(s_Counter++, s_IDBuffer + 2, 16);
|
|
||||||
snprintf(s_IDBuffer + 2, 14, "%x", s_Counter++);
|
|
||||||
|
|
||||||
if (ImGui::DragFloat2(s_IDBuffer, glm::value_ptr(value), delta))
|
|
||||||
modified = true;
|
|
||||||
|
|
||||||
ImGui::PopItemWidth();
|
|
||||||
ImGui::NextColumn();
|
|
||||||
|
|
||||||
return modified;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool Property(const char* label, glm::vec3& value, float delta = 0.1f)
|
|
||||||
{
|
|
||||||
bool modified = false;
|
|
||||||
|
|
||||||
ImGui::Text(label);
|
|
||||||
ImGui::NextColumn();
|
|
||||||
ImGui::PushItemWidth(-1);
|
|
||||||
|
|
||||||
s_IDBuffer[0] = '#';
|
|
||||||
s_IDBuffer[1] = '#';
|
|
||||||
memset(s_IDBuffer + 2, 0, 14);
|
|
||||||
// itoa(s_Counter++, s_IDBuffer + 2, 16);
|
|
||||||
snprintf(s_IDBuffer + 2, 14, "%x", s_Counter++);
|
|
||||||
|
|
||||||
if (ImGui::DragFloat3(s_IDBuffer, glm::value_ptr(value), delta))
|
|
||||||
modified = true;
|
|
||||||
|
|
||||||
ImGui::PopItemWidth();
|
|
||||||
ImGui::NextColumn();
|
|
||||||
|
|
||||||
return modified;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool Property(const char* label, glm::vec4& value, float delta = 0.1f)
|
|
||||||
{
|
|
||||||
bool modified = false;
|
|
||||||
|
|
||||||
ImGui::Text(label);
|
|
||||||
ImGui::NextColumn();
|
|
||||||
ImGui::PushItemWidth(-1);
|
|
||||||
|
|
||||||
s_IDBuffer[0] = '#';
|
|
||||||
s_IDBuffer[1] = '#';
|
|
||||||
memset(s_IDBuffer + 2, 0, 14);
|
|
||||||
// itoa(s_Counter++, s_IDBuffer + 2, 16);
|
|
||||||
snprintf(s_IDBuffer + 2, 14, "%x", s_Counter++);
|
|
||||||
|
|
||||||
if (ImGui::DragFloat4(s_IDBuffer, glm::value_ptr(value), delta))
|
|
||||||
modified = true;
|
|
||||||
|
|
||||||
ImGui::PopItemWidth();
|
|
||||||
ImGui::NextColumn();
|
|
||||||
|
|
||||||
return modified;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void EndPropertyGrid()
|
|
||||||
{
|
|
||||||
ImGui::Columns(1);
|
|
||||||
PopID();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename UIFunction>
|
template<typename T, typename UIFunction>
|
||||||
static void DrawComponent(const std::string& name, Entity entity, UIFunction uiFunction)
|
static void DrawComponent(const std::string& name, Entity entity, UIFunction uiFunction)
|
||||||
@ -622,6 +429,8 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
AddComponentPopup<CameraComponent>("Camera");
|
AddComponentPopup<CameraComponent>("Camera");
|
||||||
AddComponentPopup<MeshComponent>("Mesh");
|
AddComponentPopup<MeshComponent>("Mesh");
|
||||||
|
AddComponentPopup<DirectionalLightComponent>("Directional Light");
|
||||||
|
AddComponentPopup<SkyLightComponent>("sky Light");
|
||||||
AddComponentPopup<ScriptComponent>("Script");
|
AddComponentPopup<ScriptComponent>("Script");
|
||||||
AddComponentPopup<SpriteRendererComponent>("SpriteRenderer");
|
AddComponentPopup<SpriteRendererComponent>("SpriteRenderer");
|
||||||
AddComponentPopup<RigidBody2DComponent>("RigidBody2D");
|
AddComponentPopup<RigidBody2DComponent>("RigidBody2D");
|
||||||
@ -682,6 +491,7 @@ namespace Prism
|
|||||||
if (!file.empty())
|
if (!file.empty())
|
||||||
meshComponent.Mesh = Ref<Mesh>::Create(file);
|
meshComponent.Mesh = Ref<Mesh>::Create(file);
|
||||||
}
|
}
|
||||||
|
ImGui::Columns(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
DrawComponent<CameraComponent>("Camera", entity, [](CameraComponent& cameraComponent) {
|
DrawComponent<CameraComponent>("Camera", entity, [](CameraComponent& cameraComponent) {
|
||||||
@ -704,20 +514,20 @@ namespace Prism
|
|||||||
ImGui::EndCombo();
|
ImGui::EndCombo();
|
||||||
}
|
}
|
||||||
|
|
||||||
BeginPropertyGrid();
|
UI::BeginPropertyGrid();
|
||||||
// Perspective parameters
|
// Perspective parameters
|
||||||
if (cameraComponent.Camera.GetProjectionType() == SceneCamera::ProjectionType::Perspective)
|
if (cameraComponent.Camera.GetProjectionType() == SceneCamera::ProjectionType::Perspective)
|
||||||
{
|
{
|
||||||
float verticalFOV = cameraComponent.Camera.GetPerspectiveVerticalFOV();
|
float verticalFOV = cameraComponent.Camera.GetPerspectiveVerticalFOV();
|
||||||
if (Property("Vertical FOV", verticalFOV))
|
if (UI::Property("Vertical FOV", verticalFOV))
|
||||||
cameraComponent.Camera.SetPerspectiveVerticalFOV(verticalFOV);
|
cameraComponent.Camera.SetPerspectiveVerticalFOV(verticalFOV);
|
||||||
|
|
||||||
float nearClip = cameraComponent.Camera.GetPerspectiveNearClip();
|
float nearClip = cameraComponent.Camera.GetPerspectiveNearClip();
|
||||||
if (Property("Near Clip", nearClip))
|
if (UI::Property("Near Clip", nearClip))
|
||||||
cameraComponent.Camera.SetPerspectiveNearClip(nearClip);
|
cameraComponent.Camera.SetPerspectiveNearClip(nearClip);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
float farClip = cameraComponent.Camera.GetPerspectiveFarClip();
|
float farClip = cameraComponent.Camera.GetPerspectiveFarClip();
|
||||||
if (Property("Far Clip", farClip))
|
if (UI::Property("Far Clip", farClip))
|
||||||
cameraComponent.Camera.SetPerspectiveFarClip(farClip);
|
cameraComponent.Camera.SetPerspectiveFarClip(farClip);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -725,18 +535,57 @@ namespace Prism
|
|||||||
else if (cameraComponent.Camera.GetProjectionType() == SceneCamera::ProjectionType::Orthographic)
|
else if (cameraComponent.Camera.GetProjectionType() == SceneCamera::ProjectionType::Orthographic)
|
||||||
{
|
{
|
||||||
float orthoSize = cameraComponent.Camera.GetOrthographicSize();
|
float orthoSize = cameraComponent.Camera.GetOrthographicSize();
|
||||||
if (Property("Size", orthoSize))
|
if (UI::Property("Size", orthoSize))
|
||||||
cameraComponent.Camera.SetOrthographicSize(orthoSize);
|
cameraComponent.Camera.SetOrthographicSize(orthoSize);
|
||||||
|
|
||||||
float nearClip = cameraComponent.Camera.GetOrthographicNearClip();
|
float nearClip = cameraComponent.Camera.GetOrthographicNearClip();
|
||||||
if (Property("Near Clip", nearClip))
|
if (UI::Property("Near Clip", nearClip))
|
||||||
cameraComponent.Camera.SetOrthographicNearClip(nearClip);
|
cameraComponent.Camera.SetOrthographicNearClip(nearClip);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
float farClip = cameraComponent.Camera.GetOrthographicFarClip();
|
float farClip = cameraComponent.Camera.GetOrthographicFarClip();
|
||||||
if (Property("Far Clip", farClip))
|
if (UI::Property("Far Clip", farClip))
|
||||||
cameraComponent.Camera.SetOrthographicFarClip(farClip);
|
cameraComponent.Camera.SetOrthographicFarClip(farClip);
|
||||||
}
|
}
|
||||||
EndPropertyGrid();
|
UI::EndPropertyGrid();
|
||||||
|
});
|
||||||
|
|
||||||
|
DrawComponent<DirectionalLightComponent>("Directional Light", entity, [](DirectionalLightComponent& dlc)
|
||||||
|
{
|
||||||
|
UI::BeginPropertyGrid();
|
||||||
|
UI::PropertyColor("Radiance", dlc.Radiance);
|
||||||
|
UI::Property("Intensity", dlc.Intensity);
|
||||||
|
UI::Property("Cast Shadows", dlc.CastShadows);
|
||||||
|
UI::Property("Soft Shadows", dlc.SoftShadows);
|
||||||
|
UI::Property("Source Size", dlc.LightSize);
|
||||||
|
UI::EndPropertyGrid();
|
||||||
|
});
|
||||||
|
|
||||||
|
DrawComponent<SkyLightComponent>("Sky Light", entity, [](SkyLightComponent& slc)
|
||||||
|
{
|
||||||
|
ImGui::Columns(3);
|
||||||
|
ImGui::SetColumnWidth(0, 100);
|
||||||
|
ImGui::SetColumnWidth(1, 300);
|
||||||
|
ImGui::SetColumnWidth(2, 40);
|
||||||
|
ImGui::Text("File Path");
|
||||||
|
ImGui::NextColumn();
|
||||||
|
ImGui::PushItemWidth(-1);
|
||||||
|
if (!slc.SceneEnvironment.FilePath.empty())
|
||||||
|
ImGui::InputText("##envfilepath", (char*)slc.SceneEnvironment.FilePath.c_str(), 256, ImGuiInputTextFlags_ReadOnly);
|
||||||
|
else
|
||||||
|
ImGui::InputText("##envfilepath", (char*)"Empty", 256, ImGuiInputTextFlags_ReadOnly);
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::NextColumn();
|
||||||
|
if (ImGui::Button("...##openenv"))
|
||||||
|
{
|
||||||
|
std::string file = Application::Get().OpenFile("*.hdr");
|
||||||
|
if (!file.empty())
|
||||||
|
slc.SceneEnvironment = Environment::Load(file);
|
||||||
|
}
|
||||||
|
ImGui::Columns(1);
|
||||||
|
|
||||||
|
UI::BeginPropertyGrid();
|
||||||
|
UI::Property("Intensity", slc.Intensity, 0.01f, 0.0f, 5.0f);
|
||||||
|
UI::EndPropertyGrid();
|
||||||
});
|
});
|
||||||
|
|
||||||
DrawComponent<SpriteRendererComponent>("Sprite Renderer", entity, [](SpriteRendererComponent& mc)
|
DrawComponent<SpriteRendererComponent>("Sprite Renderer", entity, [](SpriteRendererComponent& mc)
|
||||||
@ -744,9 +593,9 @@ namespace Prism
|
|||||||
});
|
});
|
||||||
|
|
||||||
DrawComponent<ScriptComponent>("Script", entity, [=](ScriptComponent& scriptComponent) mutable {
|
DrawComponent<ScriptComponent>("Script", entity, [=](ScriptComponent& scriptComponent) mutable {
|
||||||
BeginPropertyGrid();
|
UI::BeginPropertyGrid();
|
||||||
const std::string oldName = scriptComponent.ModuleName;
|
const std::string oldName = scriptComponent.ModuleName;
|
||||||
if (Property("Module Name", scriptComponent.ModuleName, !ScriptEngine::ModuleExists(scriptComponent.ModuleName))) // TODO: no live edit
|
if (UI::Property("Module Name", scriptComponent.ModuleName, !ScriptEngine::ModuleExists(scriptComponent.ModuleName))) // TODO: no live edit
|
||||||
{
|
{
|
||||||
// Shutdown old script
|
// Shutdown old script
|
||||||
if (ScriptEngine::ModuleExists(oldName))
|
if (ScriptEngine::ModuleExists(oldName))
|
||||||
@ -772,7 +621,7 @@ namespace Prism
|
|||||||
case FieldType::Int:
|
case FieldType::Int:
|
||||||
{
|
{
|
||||||
int value = isRuntime ? field.GetRuntimeValue<int>() : field.GetStoredValue<int>();
|
int value = isRuntime ? field.GetRuntimeValue<int>() : field.GetStoredValue<int>();
|
||||||
if (Property(field.Name.c_str(), value))
|
if (UI::Property(field.Name.c_str(), value))
|
||||||
{
|
{
|
||||||
if (isRuntime)
|
if (isRuntime)
|
||||||
field.SetRuntimeValue(value);
|
field.SetRuntimeValue(value);
|
||||||
@ -784,7 +633,7 @@ namespace Prism
|
|||||||
case FieldType::Float:
|
case FieldType::Float:
|
||||||
{
|
{
|
||||||
float value = isRuntime ? field.GetRuntimeValue<float>() : field.GetStoredValue<float>();
|
float value = isRuntime ? field.GetRuntimeValue<float>() : field.GetStoredValue<float>();
|
||||||
if (Property(field.Name.c_str(), value, 0.2f))
|
if (UI::Property(field.Name.c_str(), value, 0.2f))
|
||||||
{
|
{
|
||||||
if (isRuntime)
|
if (isRuntime)
|
||||||
field.SetRuntimeValue(value);
|
field.SetRuntimeValue(value);
|
||||||
@ -796,7 +645,7 @@ namespace Prism
|
|||||||
case FieldType::Vec2:
|
case FieldType::Vec2:
|
||||||
{
|
{
|
||||||
glm::vec2 value = isRuntime ? field.GetRuntimeValue<glm::vec2>() : field.GetStoredValue<glm::vec2>();
|
glm::vec2 value = isRuntime ? field.GetRuntimeValue<glm::vec2>() : field.GetStoredValue<glm::vec2>();
|
||||||
if (Property(field.Name.c_str(), value, 0.2f))
|
if (UI::Property(field.Name.c_str(), value, 0.2f))
|
||||||
{
|
{
|
||||||
if (isRuntime)
|
if (isRuntime)
|
||||||
field.SetRuntimeValue(value);
|
field.SetRuntimeValue(value);
|
||||||
@ -808,7 +657,7 @@ namespace Prism
|
|||||||
case FieldType::Vec3:
|
case FieldType::Vec3:
|
||||||
{
|
{
|
||||||
glm::vec3 value = isRuntime ? field.GetRuntimeValue<glm::vec3>() : field.GetStoredValue<glm::vec3>();
|
glm::vec3 value = isRuntime ? field.GetRuntimeValue<glm::vec3>() : field.GetStoredValue<glm::vec3>();
|
||||||
if (Property(field.Name.c_str(), value, 0.2f))
|
if (UI::Property(field.Name.c_str(), value, 0.2f))
|
||||||
{
|
{
|
||||||
if (isRuntime)
|
if (isRuntime)
|
||||||
field.SetRuntimeValue(value);
|
field.SetRuntimeValue(value);
|
||||||
@ -820,7 +669,7 @@ namespace Prism
|
|||||||
case FieldType::Vec4:
|
case FieldType::Vec4:
|
||||||
{
|
{
|
||||||
glm::vec4 value = isRuntime ? field.GetRuntimeValue<glm::vec4>() : field.GetStoredValue<glm::vec4>();
|
glm::vec4 value = isRuntime ? field.GetRuntimeValue<glm::vec4>() : field.GetStoredValue<glm::vec4>();
|
||||||
if (Property(field.Name.c_str(), value, 0.2f))
|
if (UI::Property(field.Name.c_str(), value, 0.2f))
|
||||||
{
|
{
|
||||||
if (isRuntime)
|
if (isRuntime)
|
||||||
field.SetRuntimeValue(value);
|
field.SetRuntimeValue(value);
|
||||||
@ -834,7 +683,7 @@ namespace Prism
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EndPropertyGrid();
|
UI::EndPropertyGrid();
|
||||||
#if TODO
|
#if TODO
|
||||||
if (ImGui::Button("Run Script"))
|
if (ImGui::Button("Run Script"))
|
||||||
{
|
{
|
||||||
@ -866,34 +715,34 @@ namespace Prism
|
|||||||
|
|
||||||
if (rb2dComponent.BodyType == RigidBody2DComponent::Type::Dynamic)
|
if (rb2dComponent.BodyType == RigidBody2DComponent::Type::Dynamic)
|
||||||
{
|
{
|
||||||
BeginPropertyGrid();
|
UI::BeginPropertyGrid();
|
||||||
Property("Fixed Rotation", rb2dComponent.FixedRotation);
|
UI::Property("Fixed Rotation", rb2dComponent.FixedRotation);
|
||||||
EndPropertyGrid();
|
UI::EndPropertyGrid();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
DrawComponent<BoxCollider2DComponent>("Box Collider 2D", entity, [](BoxCollider2DComponent& bc2dComponent)
|
DrawComponent<BoxCollider2DComponent>("Box Collider 2D", entity, [](BoxCollider2DComponent& bc2dComponent)
|
||||||
{
|
{
|
||||||
BeginPropertyGrid();
|
UI::BeginPropertyGrid();
|
||||||
|
|
||||||
Property("Offset", bc2dComponent.Offset);
|
UI::Property("Offset", bc2dComponent.Offset);
|
||||||
Property("Size", bc2dComponent.Size);
|
UI::Property("Size", bc2dComponent.Size);
|
||||||
Property("Density", bc2dComponent.Density);
|
UI::Property("Density", bc2dComponent.Density);
|
||||||
Property("Friction", bc2dComponent.Friction);
|
UI::Property("Friction", bc2dComponent.Friction);
|
||||||
|
|
||||||
EndPropertyGrid();
|
UI::EndPropertyGrid();
|
||||||
});
|
});
|
||||||
|
|
||||||
DrawComponent<CircleCollider2DComponent>("Circle Collider 2D", entity, [](CircleCollider2DComponent& cc2dComponent)
|
DrawComponent<CircleCollider2DComponent>("Circle Collider 2D", entity, [](CircleCollider2DComponent& cc2dComponent)
|
||||||
{
|
{
|
||||||
BeginPropertyGrid();
|
UI::BeginPropertyGrid();
|
||||||
|
|
||||||
Property("Offset", cc2dComponent.Offset);
|
UI::Property("Offset", cc2dComponent.Offset);
|
||||||
Property("Radius", cc2dComponent.Radius);
|
UI::Property("Radius", cc2dComponent.Radius);
|
||||||
Property("Density", cc2dComponent.Density);
|
UI::Property("Density", cc2dComponent.Density);
|
||||||
Property("Friction", cc2dComponent.Friction);
|
UI::Property("Friction", cc2dComponent.Friction);
|
||||||
|
|
||||||
EndPropertyGrid();
|
UI::EndPropertyGrid();
|
||||||
});
|
});
|
||||||
|
|
||||||
DrawComponent<RigidBodyComponent>("Rigidbody", entity, [](RigidBodyComponent& rbc)
|
DrawComponent<RigidBodyComponent>("Rigidbody", entity, [](RigidBodyComponent& rbc)
|
||||||
@ -948,21 +797,21 @@ namespace Prism
|
|||||||
|
|
||||||
if (rbc.BodyType == RigidBodyComponent::Type::Dynamic)
|
if (rbc.BodyType == RigidBodyComponent::Type::Dynamic)
|
||||||
{
|
{
|
||||||
BeginPropertyGrid();
|
UI::BeginPropertyGrid();
|
||||||
Property("Mass", rbc.Mass);
|
UI::Property("Mass", rbc.Mass);
|
||||||
Property("Is Kinematic", rbc.IsKinematic);
|
UI::Property("Is Kinematic", rbc.IsKinematic);
|
||||||
EndPropertyGrid();
|
UI::EndPropertyGrid();
|
||||||
|
|
||||||
if (ImGui::TreeNode("RigidBodyConstraints", "Constraints"))
|
if (ImGui::TreeNode("RigidBodyConstraints", "Constraints"))
|
||||||
{
|
{
|
||||||
BeginPropertyGrid();
|
UI::BeginPropertyGrid();
|
||||||
Property("Position: X", rbc.LockPositionX);
|
UI::Property("Position: X", rbc.LockPositionX);
|
||||||
Property("Position: Y", rbc.LockPositionY);
|
UI::Property("Position: Y", rbc.LockPositionY);
|
||||||
Property("Position: Z", rbc.LockPositionZ);
|
UI::Property("Position: Z", rbc.LockPositionZ);
|
||||||
Property("Rotation: X", rbc.LockRotationX);
|
UI::Property("Rotation: X", rbc.LockRotationX);
|
||||||
Property("Rotation: Y", rbc.LockRotationY);
|
UI::Property("Rotation: Y", rbc.LockRotationY);
|
||||||
Property("Rotation: Z", rbc.LockRotationZ);
|
UI::Property("Rotation: Z", rbc.LockRotationZ);
|
||||||
EndPropertyGrid();
|
UI::EndPropertyGrid();
|
||||||
|
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
@ -972,60 +821,60 @@ namespace Prism
|
|||||||
|
|
||||||
DrawComponent<PhysicsMaterialComponent>("Physics Material", entity, [](PhysicsMaterialComponent& pmc)
|
DrawComponent<PhysicsMaterialComponent>("Physics Material", entity, [](PhysicsMaterialComponent& pmc)
|
||||||
{
|
{
|
||||||
BeginPropertyGrid();
|
UI::BeginPropertyGrid();
|
||||||
|
|
||||||
Property("Static Friction", pmc.StaticFriction, 0.01f, 0.0f, 1.0f);
|
UI::Property("Static Friction", pmc.StaticFriction, 0.01f, 0.0f, 1.0f);
|
||||||
Property("Dynamic Friction", pmc.DynamicFriction, 0.01f, 0.0f, 1.0f);
|
UI::Property("Dynamic Friction", pmc.DynamicFriction, 0.01f, 0.0f, 1.0f);
|
||||||
Property("Bounciness", pmc.Bounciness, 0.01f, 0.0f, 1.0f);
|
UI::Property("Bounciness", pmc.Bounciness, 0.01f, 0.0f, 1.0f);
|
||||||
|
|
||||||
EndPropertyGrid();
|
UI::EndPropertyGrid();
|
||||||
});
|
});
|
||||||
|
|
||||||
DrawComponent<BoxColliderComponent>("Box Collider", entity, [](BoxColliderComponent& bcc)
|
DrawComponent<BoxColliderComponent>("Box Collider", entity, [](BoxColliderComponent& bcc)
|
||||||
{
|
{
|
||||||
BeginPropertyGrid();
|
UI::BeginPropertyGrid();
|
||||||
|
|
||||||
if (Property("Size", bcc.Size))
|
if (UI::Property("Size", bcc.Size))
|
||||||
{
|
{
|
||||||
bcc.DebugMesh = MeshFactory::CreateBox(bcc.Size);
|
bcc.DebugMesh = MeshFactory::CreateBox(bcc.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
Property("IsTrigger", bcc.IsTrigger);
|
UI::Property("IsTrigger", bcc.IsTrigger);
|
||||||
|
|
||||||
EndPropertyGrid();
|
UI::EndPropertyGrid();
|
||||||
});
|
});
|
||||||
|
|
||||||
DrawComponent<SphereColliderComponent>("Sphere Collider", entity, [](SphereColliderComponent& scc)
|
DrawComponent<SphereColliderComponent>("Sphere Collider", entity, [](SphereColliderComponent& scc)
|
||||||
{
|
{
|
||||||
BeginPropertyGrid();
|
UI::BeginPropertyGrid();
|
||||||
|
|
||||||
if (Property("Radius", scc.Radius))
|
if (UI::Property("Radius", scc.Radius))
|
||||||
{
|
{
|
||||||
scc.DebugMesh = MeshFactory::CreateSphere(scc.Radius);
|
scc.DebugMesh = MeshFactory::CreateSphere(scc.Radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
Property("IsTrigger", scc.IsTrigger);
|
UI::Property("IsTrigger", scc.IsTrigger);
|
||||||
|
|
||||||
EndPropertyGrid();
|
UI::EndPropertyGrid();
|
||||||
});
|
});
|
||||||
|
|
||||||
DrawComponent<CapsuleColliderComponent>("Capsule Collider", entity, [](CapsuleColliderComponent& ccc)
|
DrawComponent<CapsuleColliderComponent>("Capsule Collider", entity, [](CapsuleColliderComponent& ccc)
|
||||||
{
|
{
|
||||||
BeginPropertyGrid();
|
UI::BeginPropertyGrid();
|
||||||
|
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
|
||||||
if (Property("Radius", ccc.Radius)) changed = true;
|
if (UI::Property("Radius", ccc.Radius)) changed = true;
|
||||||
if (Property("Height", ccc.Height)) changed = true;
|
if (UI::Property("Height", ccc.Height)) changed = true;
|
||||||
|
|
||||||
Property("Is Trigger", ccc.IsTrigger);
|
UI::Property("Is Trigger", ccc.IsTrigger);
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
ccc.DebugMesh = MeshFactory::CreateCapsule(ccc.Radius, ccc.Height);
|
ccc.DebugMesh = MeshFactory::CreateCapsule(ccc.Radius, ccc.Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
EndPropertyGrid();
|
UI::EndPropertyGrid();
|
||||||
});
|
});
|
||||||
|
|
||||||
DrawComponent<MeshColliderComponent>("Mesh Collider", entity, [](MeshColliderComponent& mcc)
|
DrawComponent<MeshColliderComponent>("Mesh Collider", entity, [](MeshColliderComponent& mcc)
|
||||||
@ -1049,14 +898,28 @@ namespace Prism
|
|||||||
if (!file.empty())
|
if (!file.empty())
|
||||||
{
|
{
|
||||||
mcc.CollisionMesh = Ref<Mesh>::Create(file);
|
mcc.CollisionMesh = Ref<Mesh>::Create(file);
|
||||||
PhysicsWrappers::CreateConvexMesh(mcc);
|
if (mcc.IsConvex)
|
||||||
|
PhysicsWrappers::CreateConvexMesh(mcc, true);
|
||||||
|
else
|
||||||
|
PhysicsWrappers::CreateTriangleMesh(mcc, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndColumns();
|
ImGui::EndColumns();
|
||||||
|
|
||||||
BeginPropertyGrid();
|
UI::BeginPropertyGrid();
|
||||||
Property("Is Trigger", mcc.IsTrigger);
|
if (UI::Property("Is Convex", mcc.IsConvex))
|
||||||
EndPropertyGrid();
|
{
|
||||||
|
if (mcc.CollisionMesh)
|
||||||
|
{
|
||||||
|
if (mcc.IsConvex)
|
||||||
|
PhysicsWrappers::CreateConvexMesh(mcc, true);
|
||||||
|
else
|
||||||
|
PhysicsWrappers::CreateTriangleMesh(mcc, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UI::Property("Is Trigger", mcc.IsTrigger);
|
||||||
|
UI::EndPropertyGrid();
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -146,7 +146,7 @@ namespace Prism
|
|||||||
|
|
||||||
s_SimulationTime -= s_Settings.FixedTimestep;
|
s_SimulationTime -= s_Settings.FixedTimestep;
|
||||||
|
|
||||||
for (Entity& e : s_SimulatedEntities)
|
for (const Entity& e : s_SimulatedEntities)
|
||||||
{
|
{
|
||||||
if (ScriptEngine::IsEntityModuleValid(e))
|
if (ScriptEngine::IsEntityModuleValid(e))
|
||||||
ScriptEngine::OnPhysicsUpdateEntity(e, s_Settings.FixedTimestep);
|
ScriptEngine::OnPhysicsUpdateEntity(e, s_Settings.FixedTimestep);
|
||||||
|
|||||||
@ -10,6 +10,12 @@
|
|||||||
|
|
||||||
namespace Prism
|
namespace Prism
|
||||||
{
|
{
|
||||||
|
physx::PxTransform ToPhysXTransform(const TransformComponent& transform)
|
||||||
|
{
|
||||||
|
const physx::PxQuat r = ToPhysXQuat(glm::normalize(glm::quat(transform.Rotation)));
|
||||||
|
const physx::PxVec3 p = ToPhysXVector(transform.Translation);
|
||||||
|
return physx::PxTransform(p, r);
|
||||||
|
}
|
||||||
|
|
||||||
physx::PxTransform ToPhysXTransform(const glm::mat4& matrix)
|
physx::PxTransform ToPhysXTransform(const glm::mat4& matrix)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -9,10 +9,12 @@
|
|||||||
#include <PxPhysicsAPI.h>
|
#include <PxPhysicsAPI.h>
|
||||||
|
|
||||||
#include "glm/glm.hpp"
|
#include "glm/glm.hpp"
|
||||||
|
#include "Prism/Scene/Components.h"
|
||||||
|
|
||||||
namespace Prism
|
namespace Prism
|
||||||
{
|
{
|
||||||
|
|
||||||
|
physx::PxTransform ToPhysXTransform(const TransformComponent& transform);
|
||||||
physx::PxTransform ToPhysXTransform(const glm::mat4& matrix);
|
physx::PxTransform ToPhysXTransform(const glm::mat4& matrix);
|
||||||
physx::PxMat44 ToPhysXMatrix(const glm::mat4& matrix);
|
physx::PxMat44 ToPhysXMatrix(const glm::mat4& matrix);
|
||||||
physx::PxVec3 ToPhysXVector(const glm::vec3& vector);
|
physx::PxVec3 ToPhysXVector(const glm::vec3& vector);
|
||||||
|
|||||||
@ -284,21 +284,278 @@ namespace Prism
|
|||||||
shape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, !collider.IsTrigger);
|
shape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, !collider.IsTrigger);
|
||||||
shape->setFlag(physx::PxShapeFlag::eTRIGGER_SHAPE, collider.IsTrigger);
|
shape->setFlag(physx::PxShapeFlag::eTRIGGER_SHAPE, collider.IsTrigger);
|
||||||
|
|
||||||
shape->setLocalPose(physx::PxTransform(physx::PxQuat(physx::PxHalfPi, physx::PxVec3(0, 0, 1))));
|
// shape->setLocalPose(physx::PxTransform(physx::PxQuat(physx::PxHalfPi, physx::PxVec3(0, 0, 1))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PhysicsWrappers::AddMeshCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material,MeshColliderComponent& collider, const glm::vec3& scale)
|
void PhysicsWrappers::AddMeshCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material,MeshColliderComponent& collider, const glm::vec3& scale)
|
||||||
{
|
{
|
||||||
physx::PxConvexMeshGeometry convexGeometry = physx::PxConvexMeshGeometry(CreateConvexMesh(collider));
|
if (collider.IsConvex)
|
||||||
|
{
|
||||||
|
std::vector<physx::PxConvexMesh*> meshes = CreateConvexMesh(collider, true);
|
||||||
|
|
||||||
|
for (const auto mesh : meshes)
|
||||||
|
{
|
||||||
|
physx::PxConvexMeshGeometry convexGeometry = physx::PxConvexMeshGeometry(mesh, physx::PxMeshScale(ToPhysXVector(scale)));
|
||||||
convexGeometry.meshFlags = physx::PxConvexMeshGeometryFlag::eTIGHT_BOUNDS;
|
convexGeometry.meshFlags = physx::PxConvexMeshGeometryFlag::eTIGHT_BOUNDS;
|
||||||
physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(actor, convexGeometry, material);
|
physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(actor, convexGeometry, material);
|
||||||
shape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, !collider.IsTrigger);
|
shape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, !collider.IsTrigger);
|
||||||
shape->setFlag(physx::PxShapeFlag::eTRIGGER_SHAPE, collider.IsTrigger);
|
shape->setFlag(physx::PxShapeFlag::eTRIGGER_SHAPE, collider.IsTrigger);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
physx::PxConvexMesh* PhysicsWrappers::CreateConvexMesh(MeshColliderComponent& collider)
|
else
|
||||||
{
|
{
|
||||||
|
std::vector<physx::PxTriangleMesh*> meshes = CreateTriangleMesh(collider, true);
|
||||||
|
|
||||||
|
for (const auto mesh : meshes)
|
||||||
|
{
|
||||||
|
physx::PxTriangleMeshGeometry convexGeometry = physx::PxTriangleMeshGeometry(mesh, physx::PxMeshScale(ToPhysXVector(scale)));
|
||||||
|
physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(actor, convexGeometry, material);
|
||||||
|
shape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, !collider.IsTrigger);
|
||||||
|
shape->setFlag(physx::PxShapeFlag::eTRIGGER_SHAPE, collider.IsTrigger);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<physx::PxTriangleMesh*> PhysicsWrappers::CreateTriangleMesh(MeshColliderComponent& collider, bool invalidateOld)
|
||||||
|
{
|
||||||
|
std::vector<physx::PxTriangleMesh*> meshes;
|
||||||
|
|
||||||
|
// 设置烹饪参数,可以根据需要调整
|
||||||
|
physx::PxCookingParams cookingParams(s_Physics->getTolerancesScale());
|
||||||
|
// 可以添加额外的烹饪参数设置,如:
|
||||||
|
// cookingParams.meshPreprocessParams = physx::PxMeshPreprocessingFlag::eWELD_VERTICES;
|
||||||
|
// cookingParams.meshWeldTolerance = 0.01f;
|
||||||
|
|
||||||
|
// 获取顶点和索引数据
|
||||||
|
const std::vector<Vertex>& vertices = collider.CollisionMesh->GetStaticVertices();
|
||||||
|
const std::vector<Index>& indices = collider.CollisionMesh->GetIndices();
|
||||||
|
|
||||||
|
// 提取顶点位置(如果需要)
|
||||||
|
std::vector<glm::vec3> vertexPositions;
|
||||||
|
if (vertices[0].Position != glm::vec3()) {
|
||||||
|
vertexPositions.reserve(vertices.size());
|
||||||
|
for (const auto& vertex : vertices) {
|
||||||
|
vertexPositions.push_back(vertex.Position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清空旧的处理网格(如果需要)
|
||||||
|
if (invalidateOld) {
|
||||||
|
collider.ProcessedMeshes.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理每个子网格
|
||||||
|
for (const auto& submesh : collider.CollisionMesh->GetSubmeshes())
|
||||||
|
{
|
||||||
|
// 准备三角形网格描述
|
||||||
|
physx::PxTriangleMeshDesc triangleDesc;
|
||||||
|
triangleDesc.points.count = submesh.VertexCount;
|
||||||
|
triangleDesc.points.stride = sizeof(glm::vec3);
|
||||||
|
|
||||||
|
// 使用顶点位置数组或原始顶点数据
|
||||||
|
if (!vertexPositions.empty()) {
|
||||||
|
triangleDesc.points.data = &vertexPositions[submesh.BaseVertex];
|
||||||
|
} else {
|
||||||
|
triangleDesc.points.stride = sizeof(Vertex);
|
||||||
|
triangleDesc.points.data = &vertices[submesh.BaseVertex];
|
||||||
|
}
|
||||||
|
|
||||||
|
triangleDesc.triangles.count = submesh.IndexCount / 3;
|
||||||
|
triangleDesc.triangles.data = &indices[submesh.BaseIndex / 3];
|
||||||
|
triangleDesc.triangles.stride = sizeof(Index); // 假设Index包含三个值
|
||||||
|
|
||||||
|
// 如果需要,设置三角形标志
|
||||||
|
// triangleDesc.flags = physx::PxMeshFlag::e16_BIT_INDICES; // 如果使用16位索引
|
||||||
|
|
||||||
|
// 创建三角形网格
|
||||||
|
physx::PxTriangleMeshCookingResult::Enum result;
|
||||||
|
physx::PxTriangleMesh* triangleMesh = PxCreateTriangleMesh(
|
||||||
|
cookingParams,
|
||||||
|
triangleDesc,
|
||||||
|
*PxGetStandaloneInsertionCallback(),
|
||||||
|
&result
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!triangleMesh) {
|
||||||
|
PM_CORE_ERROR("Failed to create triangle mesh for submesh: {0}", submesh.MeshName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
meshes.push_back(triangleMesh);
|
||||||
|
|
||||||
|
// 为可视化生成渲染网格(如果需要)
|
||||||
|
if (collider.ProcessedMeshes.empty() || invalidateOld)
|
||||||
|
{
|
||||||
|
const uint32_t nbVerts = triangleMesh->getNbVertices();
|
||||||
|
const physx::PxVec3* meshVertices = triangleMesh->getVertices();
|
||||||
|
const uint32_t nbTriangles = triangleMesh->getNbTriangles();
|
||||||
|
|
||||||
|
std::vector<Vertex> processedVertices;
|
||||||
|
std::vector<Index> processedIndices;
|
||||||
|
|
||||||
|
// 获取顶点数据
|
||||||
|
processedVertices.reserve(nbVerts);
|
||||||
|
for (uint32_t v = 0; v < nbVerts; v++)
|
||||||
|
{
|
||||||
|
Vertex vertex;
|
||||||
|
vertex.Position = FromPhysXVector(meshVertices[v]);
|
||||||
|
processedVertices.push_back(vertex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取三角形索引
|
||||||
|
processedIndices.reserve(nbTriangles);
|
||||||
|
|
||||||
|
// 检查索引格式(16位或32位)
|
||||||
|
if (triangleMesh->getTriangleMeshFlags() & physx::PxTriangleMeshFlag::e16_BIT_INDICES)
|
||||||
|
{
|
||||||
|
const physx::PxU16* tris = static_cast<const physx::PxU16*>(triangleMesh->getTriangles());
|
||||||
|
for (uint32_t tri = 0; tri < nbTriangles; tri++)
|
||||||
|
{
|
||||||
|
Index index;
|
||||||
|
index.V1 = tris[3 * tri + 0];
|
||||||
|
index.V2 = tris[3 * tri + 1];
|
||||||
|
index.V3 = tris[3 * tri + 2];
|
||||||
|
processedIndices.push_back(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const physx::PxU32* tris = static_cast<const physx::PxU32*>(triangleMesh->getTriangles());
|
||||||
|
for (uint32_t tri = 0; tri < nbTriangles; tri++)
|
||||||
|
{
|
||||||
|
Index index;
|
||||||
|
index.V1 = static_cast<uint32_t>(tris[3 * tri + 0]);
|
||||||
|
index.V2 = static_cast<uint32_t>(tris[3 * tri + 1]);
|
||||||
|
index.V3 = static_cast<uint32_t>(tris[3 * tri + 2]);
|
||||||
|
processedIndices.push_back(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 为当前子网格创建渲染网格
|
||||||
|
collider.ProcessedMeshes.push_back(Ref<Mesh>::Create(processedVertices, processedIndices));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return meshes;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<physx::PxConvexMesh*> PhysicsWrappers::CreateConvexMesh(MeshColliderComponent& collider, bool invalidateOld)
|
||||||
|
{
|
||||||
|
std::vector<physx::PxConvexMesh*> meshes;
|
||||||
|
|
||||||
|
// 设置烹饪参数,保持与原始版本相同的配置
|
||||||
|
physx::PxCookingParams cookingParams(s_Physics->getTolerancesScale());
|
||||||
|
cookingParams.planeTolerance = 0.0F;
|
||||||
|
cookingParams.meshPreprocessParams = physx::PxMeshPreprocessingFlags(physx::PxMeshPreprocessingFlag::eWELD_VERTICES);
|
||||||
|
cookingParams.meshWeldTolerance = 0.01f;
|
||||||
|
|
||||||
|
// 获取顶点数据
|
||||||
|
const std::vector<Vertex>& vertices = collider.CollisionMesh->GetStaticVertices();
|
||||||
|
const std::vector<Index>& indices = collider.CollisionMesh->GetIndices();
|
||||||
|
|
||||||
|
// 准备顶点位置数组(如果需要的话)
|
||||||
|
std::vector<glm::vec3> vertexPositions;
|
||||||
|
if (vertices[0].Position != glm::vec3()) {
|
||||||
|
vertexPositions.reserve(vertices.size());
|
||||||
|
for (const auto& vertex : vertices) {
|
||||||
|
vertexPositions.push_back(vertex.Position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (invalidateOld) {
|
||||||
|
collider.ProcessedMeshes.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 处理每个子网格
|
||||||
|
for (const auto& submesh : collider.CollisionMesh->GetSubmeshes())
|
||||||
|
{
|
||||||
|
// 准备凸包描述
|
||||||
|
physx::PxConvexMeshDesc convexDesc;
|
||||||
|
convexDesc.points.count = submesh.VertexCount;
|
||||||
|
convexDesc.points.stride = sizeof(glm::vec3);
|
||||||
|
|
||||||
|
// 使用顶点位置数组或原始顶点数据
|
||||||
|
if (!vertexPositions.empty()) {
|
||||||
|
convexDesc.points.data = &vertexPositions[submesh.BaseVertex];
|
||||||
|
} else {
|
||||||
|
convexDesc.points.stride = sizeof(Vertex);
|
||||||
|
convexDesc.points.data = &vertices[submesh.BaseVertex];
|
||||||
|
}
|
||||||
|
|
||||||
|
convexDesc.flags = physx::PxConvexFlag::eCOMPUTE_CONVEX |
|
||||||
|
physx::PxConvexFlag::eCHECK_ZERO_AREA_TRIANGLES |
|
||||||
|
physx::PxConvexFlag::eSHIFT_VERTICES;
|
||||||
|
|
||||||
|
// 创建凸包网格
|
||||||
|
physx::PxConvexMeshCookingResult::Enum result;
|
||||||
|
physx::PxConvexMesh* convexMesh = PxCreateConvexMesh(
|
||||||
|
cookingParams,
|
||||||
|
convexDesc,
|
||||||
|
*PxGetStandaloneInsertionCallback(),
|
||||||
|
&result
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!convexMesh) {
|
||||||
|
PM_CORE_ERROR("Failed to create convex mesh for submesh: {0}", submesh.MeshName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
meshes.push_back(convexMesh);
|
||||||
|
|
||||||
|
// 为可视化生成渲染网格(如果需要)
|
||||||
|
if (collider.ProcessedMeshes.empty() || invalidateOld)
|
||||||
|
{
|
||||||
|
const uint32_t nbPolygons = convexMesh->getNbPolygons();
|
||||||
|
const physx::PxVec3* convexVertices = convexMesh->getVertices();
|
||||||
|
const physx::PxU8* convexIndices = convexMesh->getIndexBuffer();
|
||||||
|
|
||||||
|
std::vector<Vertex> collisionVertices;
|
||||||
|
std::vector<Index> collisionIndices;
|
||||||
|
uint32_t vertCounter = 0;
|
||||||
|
uint32_t indexCounter = 0;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < nbPolygons; i++)
|
||||||
|
{
|
||||||
|
physx::PxHullPolygon polygon;
|
||||||
|
convexMesh->getPolygonData(i, polygon);
|
||||||
|
|
||||||
|
const uint32_t vI0 = vertCounter;
|
||||||
|
|
||||||
|
// 收集当前多边形的所有顶点
|
||||||
|
for (uint32_t vI = 0; vI < polygon.mNbVerts; vI++)
|
||||||
|
{
|
||||||
|
Vertex vertex;
|
||||||
|
vertex.Position = FromPhysXVector(
|
||||||
|
convexVertices[convexIndices[polygon.mIndexBase + vI]]
|
||||||
|
);
|
||||||
|
// 如果需要坐标系转换,可以在这里添加
|
||||||
|
// vertex.Position = glm::rotate(vertex.Position, glm::radians(90.0f), {1.0f, 0.0f, 0.0f});
|
||||||
|
|
||||||
|
collisionVertices.push_back(vertex);
|
||||||
|
vertCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 为当前多边形生成三角形索引(扇形三角剖分)
|
||||||
|
for (auto vI = 1; vI < polygon.mNbVerts - 1; vI++)
|
||||||
|
{
|
||||||
|
Index index;
|
||||||
|
index.V1 = vI0;
|
||||||
|
index.V2 = vI0 + vI + 1;
|
||||||
|
index.V3 = vI0 + vI;
|
||||||
|
collisionIndices.push_back(index);
|
||||||
|
indexCounter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 为当前子网格创建渲染网格
|
||||||
|
collider.ProcessedMeshes.push_back(Ref<Mesh>::Create(collisionVertices, collisionIndices));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return meshes;
|
||||||
|
#if 0
|
||||||
const auto& vertices = collider.CollisionMesh->GetStaticVertices();
|
const auto& vertices = collider.CollisionMesh->GetStaticVertices();
|
||||||
|
|
||||||
|
|
||||||
@ -373,6 +630,7 @@ namespace Prism
|
|||||||
}
|
}
|
||||||
|
|
||||||
return mesh;
|
return mesh;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
physx::PxMaterial* PhysicsWrappers::CreateMaterial(const PhysicsMaterialComponent& material)
|
physx::PxMaterial* PhysicsWrappers::CreateMaterial(const PhysicsMaterialComponent& material)
|
||||||
@ -498,7 +756,8 @@ namespace Prism
|
|||||||
PM_CORE_WARN("PVD is already connected, reconnecting");
|
PM_CORE_WARN("PVD is already connected, reconnecting");
|
||||||
s_VisualDebugger->disconnect();
|
s_VisualDebugger->disconnect();
|
||||||
}
|
}
|
||||||
isConnect = s_VisualDebugger->connect(*transport, physx::PxPvdInstrumentationFlag::eALL);
|
s_VisualDebugger->connect(*transport, physx::PxPvdInstrumentationFlag::eALL);
|
||||||
|
isConnect = s_VisualDebugger->isConnected();
|
||||||
#endif
|
#endif
|
||||||
return isConnect;
|
return isConnect;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -45,7 +45,8 @@ namespace Prism
|
|||||||
static void AddMeshCollider(::physx::PxRigidActor& actor, const ::physx::PxMaterial& material, ::Prism::MeshColliderComponent& collider, const glm::vec3& scale = glm::vec3(0.0f));
|
static void AddMeshCollider(::physx::PxRigidActor& actor, const ::physx::PxMaterial& material, ::Prism::MeshColliderComponent& collider, const glm::vec3& scale = glm::vec3(0.0f));
|
||||||
|
|
||||||
|
|
||||||
static physx::PxConvexMesh* CreateConvexMesh(MeshColliderComponent& collider);
|
static std::vector<physx::PxTriangleMesh*> CreateTriangleMesh(MeshColliderComponent& collider, bool invalidateOld = false);
|
||||||
|
static std::vector<physx::PxConvexMesh*> CreateConvexMesh(MeshColliderComponent& collider, bool invalidateOld = false);
|
||||||
|
|
||||||
|
|
||||||
static physx::PxMaterial* CreateMaterial(const PhysicsMaterialComponent& material);
|
static physx::PxMaterial* CreateMaterial(const PhysicsMaterialComponent& material);
|
||||||
|
|||||||
@ -10,74 +10,231 @@
|
|||||||
|
|
||||||
namespace Prism
|
namespace Prism
|
||||||
{
|
{
|
||||||
OpenGLFrameBuffer::OpenGLFrameBuffer(const FramebufferSpecification& spec)
|
namespace Utils
|
||||||
: m_Specification(spec)
|
|
||||||
{
|
{
|
||||||
OpenGLFrameBuffer::Resize(spec.Width, spec.Height, true);
|
static GLenum TextureTarget(bool multisampled)
|
||||||
|
{
|
||||||
|
return multisampled ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void CreateTextures(bool multisampled, RendererID* outID, uint32_t count)
|
||||||
|
{
|
||||||
|
glCreateTextures(TextureTarget(multisampled), count, outID);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void BindTexture(bool multisampled, RendererID id)
|
||||||
|
{
|
||||||
|
glBindTexture(TextureTarget(multisampled), id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLenum DataType(GLenum format)
|
||||||
|
{
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case GL_RGBA8: return GL_UNSIGNED_BYTE;
|
||||||
|
case GL_RG16F:
|
||||||
|
case GL_RG32F:
|
||||||
|
case GL_RGBA16F:
|
||||||
|
case GL_RGBA32F: return GL_FLOAT;
|
||||||
|
case GL_DEPTH24_STENCIL8: return GL_UNSIGNED_INT_24_8;
|
||||||
|
}
|
||||||
|
|
||||||
|
PM_CORE_ASSERT(false, "Unknown format!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AttachColorTexture(RendererID id, int samples, GLenum format, uint32_t width, uint32_t height, int index)
|
||||||
|
{
|
||||||
|
const bool multisampled = samples > 1;
|
||||||
|
if (multisampled)
|
||||||
|
{
|
||||||
|
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, format, width, height, GL_FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Only RGBA access for now
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, GL_RGBA, DataType(format), nullptr);
|
||||||
|
|
||||||
|
glTexParameteri(TextureTarget(multisampled), GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(TextureTarget(multisampled), GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(TextureTarget(multisampled), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(TextureTarget(multisampled), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + index, TextureTarget(multisampled), id, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AttachDepthTexture(RendererID id, int samples, GLenum format, GLenum attachmentType, uint32_t width, uint32_t height)
|
||||||
|
{
|
||||||
|
bool multisampled = samples > 1;
|
||||||
|
if (multisampled)
|
||||||
|
{
|
||||||
|
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, format, width, height, GL_FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glTexStorage2D(GL_TEXTURE_2D, 1, format, width, height);
|
||||||
|
|
||||||
|
glTexParameteri(TextureTarget(multisampled), GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(TextureTarget(multisampled), GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(TextureTarget(multisampled), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(TextureTarget(multisampled), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, attachmentType, TextureTarget(multisampled), id, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsDepthFormat(FramebufferTextureFormat format)
|
||||||
|
{
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case FramebufferTextureFormat::DEPTH24STENCIL8:
|
||||||
|
case FramebufferTextureFormat::DEPTH32F:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenGLFrameBuffer::OpenGLFrameBuffer(const FramebufferSpecification& spec)
|
||||||
|
: m_Specification(spec), m_Width(spec.Width), m_Height(spec.Height)
|
||||||
|
{
|
||||||
|
for (auto format : m_Specification.Attachments.Attachments)
|
||||||
|
{
|
||||||
|
if (!Utils::IsDepthFormat(format.TextureFormat))
|
||||||
|
m_ColorAttachmentFormats.emplace_back(format.TextureFormat);
|
||||||
|
else
|
||||||
|
m_DepthAttachmentFormat = format.TextureFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
Resize(spec.Width, spec.Height, true);
|
||||||
|
}
|
||||||
|
|
||||||
OpenGLFrameBuffer::~OpenGLFrameBuffer()
|
OpenGLFrameBuffer::~OpenGLFrameBuffer()
|
||||||
{
|
{
|
||||||
GLuint rendererID = m_RendererID;
|
Ref<OpenGLFrameBuffer> instance = this;
|
||||||
Renderer::Submit([rendererID](){
|
Renderer::Submit([instance]() {
|
||||||
glDeleteFramebuffers(1, &rendererID);
|
glDeleteFramebuffers(1, &instance->m_RendererID);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLFrameBuffer::Bind() const
|
void OpenGLFrameBuffer::Bind() const
|
||||||
{
|
{
|
||||||
Renderer::Submit([=](){
|
Ref<const OpenGLFrameBuffer> instance = this;
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, m_RendererID);
|
Renderer::Submit([instance]() {
|
||||||
glViewport(0, 0, m_Specification.Width, m_Specification.Height);
|
glBindFramebuffer(GL_FRAMEBUFFER, instance->m_RendererID);
|
||||||
|
glViewport(0, 0, instance->m_Width, instance->m_Height);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLFrameBuffer::Unbind() const
|
void OpenGLFrameBuffer::Unbind() const
|
||||||
{
|
{
|
||||||
Renderer::Submit([=](){
|
Renderer::Submit([](){
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLFrameBuffer::Resize(const uint32_t width, const uint32_t height, const bool forceReCreate)
|
void OpenGLFrameBuffer::Resize(const uint32_t width, const uint32_t height, const bool forceReCreate)
|
||||||
{
|
{
|
||||||
if (!forceReCreate && (m_Specification.Width == width && m_Specification.Height == height))
|
if (!forceReCreate && (m_Width == width && m_Height == height))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_Specification.Width = width;
|
m_Width = width;
|
||||||
m_Specification.Height = height;
|
m_Height = height;
|
||||||
Renderer::Submit([this]()
|
|
||||||
|
Ref<OpenGLFrameBuffer> instance = this;
|
||||||
|
Renderer::Submit([instance]() mutable
|
||||||
{
|
{
|
||||||
if (m_RendererID)
|
if (instance->m_RendererID)
|
||||||
{
|
{
|
||||||
glDeleteFramebuffers(1, &m_RendererID);
|
glDeleteFramebuffers(1, &instance->m_RendererID);
|
||||||
glDeleteTextures(1, &m_ColorAttachment);
|
glDeleteTextures(static_cast<GLsizei>(instance->m_ColorAttachments.size()), instance->m_ColorAttachments.data());
|
||||||
glDeleteTextures(1, &m_DepthAttachment);
|
glDeleteTextures(1, &instance->m_DepthAttachment);
|
||||||
|
|
||||||
|
instance->m_ColorAttachments.clear();
|
||||||
|
instance->m_DepthAttachment = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
glGenFramebuffers(1, &m_RendererID);
|
glGenFramebuffers(1, &instance->m_RendererID);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, m_RendererID);
|
glBindFramebuffer(GL_FRAMEBUFFER, instance->m_RendererID);
|
||||||
|
|
||||||
|
bool multisample = instance->m_Specification.Samples > 1;
|
||||||
|
|
||||||
|
if (instance->m_ColorAttachmentFormats.size())
|
||||||
|
{
|
||||||
|
instance->m_ColorAttachments.resize(instance->m_ColorAttachmentFormats.size());
|
||||||
|
Utils::CreateTextures(multisample, instance->m_ColorAttachments.data(), static_cast<uint32_t>(instance->m_ColorAttachments.size()));
|
||||||
|
|
||||||
|
// Create color attachments
|
||||||
|
for (int i = 0; i < instance->m_ColorAttachments.size(); i++)
|
||||||
|
{
|
||||||
|
Utils::BindTexture(multisample, instance->m_ColorAttachments[i]);
|
||||||
|
switch (instance->m_ColorAttachmentFormats[i])
|
||||||
|
{
|
||||||
|
case FramebufferTextureFormat::RGBA8:
|
||||||
|
Utils::AttachColorTexture(instance->m_ColorAttachments[i], instance->m_Specification.Samples, GL_RGBA8, instance->m_Width, instance->m_Height, i);
|
||||||
|
break;
|
||||||
|
case FramebufferTextureFormat::RGBA16F:
|
||||||
|
Utils::AttachColorTexture(instance->m_ColorAttachments[i], instance->m_Specification.Samples, GL_RGBA16F, instance->m_Width, instance->m_Height, i);
|
||||||
|
break;
|
||||||
|
case FramebufferTextureFormat::RGBA32F:
|
||||||
|
Utils::AttachColorTexture(instance->m_ColorAttachments[i], instance->m_Specification.Samples, GL_RGBA32F, instance->m_Width, instance->m_Height, i);
|
||||||
|
break;
|
||||||
|
case FramebufferTextureFormat::RG32F:
|
||||||
|
Utils::AttachColorTexture(instance->m_ColorAttachments[i], instance->m_Specification.Samples, GL_RG32F, instance->m_Width, instance->m_Height, i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instance->m_DepthAttachmentFormat != FramebufferTextureFormat::None)
|
||||||
|
{
|
||||||
|
Utils::CreateTextures(multisample, &instance->m_DepthAttachment, 1);
|
||||||
|
Utils::BindTexture(multisample, instance->m_DepthAttachment);
|
||||||
|
switch (instance->m_DepthAttachmentFormat)
|
||||||
|
{
|
||||||
|
case FramebufferTextureFormat::DEPTH24STENCIL8:
|
||||||
|
Utils::AttachDepthTexture(instance->m_DepthAttachment, instance->m_Specification.Samples, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL_ATTACHMENT, instance->m_Width, instance->m_Height);
|
||||||
|
break;
|
||||||
|
case FramebufferTextureFormat::DEPTH32F:
|
||||||
|
Utils::AttachDepthTexture(instance->m_DepthAttachment, instance->m_Specification.Samples, GL_DEPTH_COMPONENT32F, GL_DEPTH_ATTACHMENT, instance->m_Width, instance->m_Height);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instance->m_ColorAttachments.size() > 1)
|
||||||
|
{
|
||||||
|
PM_CORE_ASSERT(instance->m_ColorAttachments.size() <= 4);
|
||||||
|
GLenum buffers[4] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 };
|
||||||
|
glDrawBuffers(static_cast<GLsizei>(instance->m_ColorAttachments.size()), buffers);
|
||||||
|
}
|
||||||
|
else if (instance->m_ColorAttachments.size() == 0)
|
||||||
|
{
|
||||||
|
// Only depth-pass
|
||||||
|
glDrawBuffer(GL_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
bool multisample = m_Specification.Samples > 1;
|
|
||||||
if (multisample)
|
if (multisample)
|
||||||
{
|
{
|
||||||
glCreateTextures(GL_TEXTURE_2D_MULTISAMPLE, 1, &m_ColorAttachment);
|
glCreateTextures(GL_TEXTURE_2D_MULTISAMPLE, 1, &m_ColorAttachment);
|
||||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_ColorAttachment);
|
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_ColorAttachment);
|
||||||
|
|
||||||
// TODO: Create Prism texture object based on format here
|
// TODO: Create Hazel texture object based on format here
|
||||||
if (m_Specification.Format == FramebufferFormat::RGBA16F)
|
if (m_Specification.Format == FramebufferFormat::RGBA16F)
|
||||||
{
|
{
|
||||||
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_Specification.Samples, GL_RGBA16F, m_Specification.Width, m_Specification.Height, GL_TRUE);
|
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_Specification.Samples, GL_RGBA16F, m_Specification.Width, m_Specification.Height, GL_FALSE);
|
||||||
}
|
}
|
||||||
else if (m_Specification.Format == FramebufferFormat::RGBA8)
|
else if (m_Specification.Format == FramebufferFormat::RGBA8)
|
||||||
{
|
{
|
||||||
// glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 8, GL_RGBA8, m_Specification.Width, m_Specification.Height, GL_TRUE);
|
glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_Specification.Samples, GL_RGBA8, m_Specification.Width, m_Specification.Height, GL_FALSE);
|
||||||
glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_Specification.Samples, GL_RGBA8, m_Specification.Width, m_Specification.Height, GL_TRUE);
|
|
||||||
}
|
}
|
||||||
// glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
// glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
// glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
// glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
// glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, m_ColorAttachment, 0);
|
|
||||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
|
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -85,30 +242,51 @@ namespace Prism
|
|||||||
glCreateTextures(GL_TEXTURE_2D, 1, &m_ColorAttachment);
|
glCreateTextures(GL_TEXTURE_2D, 1, &m_ColorAttachment);
|
||||||
glBindTexture(GL_TEXTURE_2D, m_ColorAttachment);
|
glBindTexture(GL_TEXTURE_2D, m_ColorAttachment);
|
||||||
|
|
||||||
// TODO: Create texture object based on format here
|
// TODO: Create Hazel texture object based on format here
|
||||||
if (m_Specification.Format == FramebufferFormat::RGBA16F)
|
if (m_Specification.Format == FramebufferFormat::RGBA16F)
|
||||||
{
|
{
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, m_Specification.Width, m_Specification.Height, 0, GL_RGBA, GL_FLOAT, nullptr);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, m_Specification.Width, m_Specification.Height, 0, GL_RGBA, GL_FLOAT, nullptr);
|
||||||
}
|
}
|
||||||
|
else if (m_Specification.Format == FramebufferFormat::RG32F) // "Shadow" for now
|
||||||
|
{
|
||||||
|
glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT32F, m_Specification.Width, m_Specification.Height);
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_ColorAttachment, 0);
|
||||||
|
glDrawBuffer(GL_NONE);
|
||||||
|
}
|
||||||
else if (m_Specification.Format == FramebufferFormat::RGBA8)
|
else if (m_Specification.Format == FramebufferFormat::RGBA8)
|
||||||
{
|
{
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_Specification.Width, m_Specification.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_Specification.Width, m_Specification.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||||
}
|
}
|
||||||
|
else if (m_Specification.Format == FramebufferFormat::COMP)
|
||||||
|
{
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, m_Specification.Width, m_Specification.Height, 0, GL_RGBA, GL_FLOAT, nullptr);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
glCreateTextures(GL_TEXTURE_2D, 1, &m_ColorAttachment2);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, m_ColorAttachment2);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, m_Specification.Width, m_Specification.Height, 0, GL_RGBA, GL_FLOAT, nullptr);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_Specification.Format != FramebufferFormat::RG32F)
|
||||||
|
{
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_ColorAttachment, 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_ColorAttachment, 0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (multisample)
|
if (multisample)
|
||||||
{
|
{
|
||||||
glCreateTextures(GL_TEXTURE_2D_MULTISAMPLE, 1, &m_DepthAttachment);
|
glCreateTextures(GL_TEXTURE_2D_MULTISAMPLE, 1, &m_DepthAttachment);
|
||||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_DepthAttachment);
|
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_DepthAttachment);
|
||||||
// glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 8, GL_DEPTH24_STENCIL8, m_Specification.Width, m_Specification.Height, GL_TRUE);
|
glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_Specification.Samples, GL_DEPTH24_STENCIL8, m_Specification.Width, m_Specification.Height, GL_FALSE);
|
||||||
glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_Specification.Samples, GL_DEPTH24_STENCIL8, m_Specification.Width, m_Specification.Height, GL_TRUE);
|
|
||||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
|
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
|
||||||
// glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, m_DepthAttachment, 0);
|
|
||||||
}
|
}
|
||||||
else
|
else if (m_Specification.Format != FramebufferFormat::RG32F)
|
||||||
{
|
{
|
||||||
glCreateTextures(GL_TEXTURE_2D, 1, &m_DepthAttachment);
|
glCreateTextures(GL_TEXTURE_2D, 1, &m_DepthAttachment);
|
||||||
glBindTexture(GL_TEXTURE_2D, m_DepthAttachment);
|
glBindTexture(GL_TEXTURE_2D, m_DepthAttachment);
|
||||||
@ -116,15 +294,31 @@ namespace Prism
|
|||||||
GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, m_Specification.Width, m_Specification.Height, 0,
|
GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, m_Specification.Width, m_Specification.Height, 0,
|
||||||
GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL
|
GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL
|
||||||
);
|
);
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_DepthAttachment, 0);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
//glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_DepthAttachment, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_ColorAttachment, 0);
|
if (m_Specification.Format != FramebufferFormat::RG32F)
|
||||||
|
{
|
||||||
if (multisample)
|
if (multisample)
|
||||||
|
{
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, m_ColorAttachment, 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, m_ColorAttachment, 0);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_ColorAttachment, 0);
|
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_ColorAttachment, 0);
|
||||||
|
if (m_Specification.Format == FramebufferFormat::COMP)
|
||||||
|
{
|
||||||
|
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, m_ColorAttachment2, 0);
|
||||||
|
const GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
|
||||||
|
glDrawBuffers(2, buffers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, m_DepthAttachment, 0);
|
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, m_DepthAttachment, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
PM_CORE_ASSERT(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Framebuffer is incomplete!");
|
PM_CORE_ASSERT(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Framebuffer is incomplete!");
|
||||||
|
|
||||||
@ -132,18 +326,11 @@ namespace Prism
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLFrameBuffer::BindTexture(const uint32_t slot) const
|
void OpenGLFrameBuffer::BindTexture(uint32_t attachmentIndex, uint32_t slot) const
|
||||||
{
|
{
|
||||||
Renderer::Submit([=](){
|
Ref<const OpenGLFrameBuffer> instance = this;
|
||||||
glActiveTexture(GL_TEXTURE0 + slot);
|
Renderer::Submit([instance, attachmentIndex, slot]() {
|
||||||
|
glBindTextureUnit(slot, instance->m_ColorAttachments[attachmentIndex]);
|
||||||
if (m_Specification.Samples > 1) {
|
|
||||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_ColorAttachment);
|
|
||||||
} else {
|
|
||||||
glBindTexture(GL_TEXTURE_2D, m_ColorAttachment);
|
|
||||||
}
|
|
||||||
|
|
||||||
// glBindTexture(GL_TEXTURE_2D, m_ColorAttachment);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,19 +20,28 @@ namespace Prism
|
|||||||
|
|
||||||
void Resize(uint32_t width, uint32_t height, bool forceReCreate) override;
|
void Resize(uint32_t width, uint32_t height, bool forceReCreate) override;
|
||||||
|
|
||||||
void BindTexture(uint32_t slot) const override;
|
void BindTexture(uint32_t attachmentIndex, uint32_t slot) const override;
|
||||||
|
|
||||||
|
uint32_t GetWidth() const override { return m_Specification.Width; }
|
||||||
|
uint32_t GetHeight() const override { return m_Specification.Height; }
|
||||||
|
|
||||||
RendererID GetRendererID() const override { return m_RendererID; }
|
RendererID GetRendererID() const override { return m_RendererID; }
|
||||||
RendererID GetColorAttachmentRendererID() const override { return m_ColorAttachment; }
|
RendererID GetColorAttachmentRendererID(const int index = 0) const override { return m_ColorAttachments[index]; }
|
||||||
RendererID GetDepthAttachmentRendererID() const override { return m_DepthAttachment; }
|
RendererID GetDepthAttachmentRendererID() const override { return m_DepthAttachment; }
|
||||||
|
|
||||||
virtual const FramebufferSpecification& GetSpecification() const override { return m_Specification; }
|
virtual const FramebufferSpecification& GetSpecification() const override { return m_Specification; }
|
||||||
private:
|
private:
|
||||||
FramebufferSpecification m_Specification;
|
|
||||||
|
|
||||||
|
FramebufferSpecification m_Specification;
|
||||||
RendererID m_RendererID = 0;
|
RendererID m_RendererID = 0;
|
||||||
|
|
||||||
RendererID m_ColorAttachment = 0, m_DepthAttachment = 0;
|
std::vector<RendererID> m_ColorAttachments;
|
||||||
|
RendererID m_DepthAttachment;
|
||||||
|
|
||||||
|
std::vector<FramebufferTextureFormat> m_ColorAttachmentFormats;
|
||||||
|
FramebufferTextureFormat m_DepthAttachmentFormat = FramebufferTextureFormat::None;
|
||||||
|
|
||||||
|
uint32_t m_Width = 0, m_Height = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -118,6 +118,13 @@ namespace Prism
|
|||||||
m_ShaderReloadedCallbacks.push_back(callback);
|
m_ShaderReloadedCallbacks.push_back(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpenGLShader::SetBool(const std::string& name, bool value)
|
||||||
|
{
|
||||||
|
Renderer::Submit([=]() {
|
||||||
|
UploadUniformInt(name, value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void OpenGLShader::SetFloat(const std::string& name, float value)
|
void OpenGLShader::SetFloat(const std::string& name, float value)
|
||||||
{
|
{
|
||||||
Renderer::Submit([=]() {
|
Renderer::Submit([=]() {
|
||||||
@ -125,6 +132,13 @@ namespace Prism
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpenGLShader::SetFloat2(const std::string& name, const glm::vec2& value)
|
||||||
|
{
|
||||||
|
Renderer::Submit([=]() {
|
||||||
|
UploadUniformFloat2(name, value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void OpenGLShader::SetFloat3(const std::string& name, const glm::vec3& value)
|
void OpenGLShader::SetFloat3(const std::string& name, const glm::vec3& value)
|
||||||
{
|
{
|
||||||
Renderer::Submit([=]()
|
Renderer::Submit([=]()
|
||||||
@ -299,7 +313,7 @@ namespace Prism
|
|||||||
|
|
||||||
std::vector<std::string> Tokenize(const std::string& string)
|
std::vector<std::string> Tokenize(const std::string& string)
|
||||||
{
|
{
|
||||||
return SplitString(string, " \t\n");
|
return SplitString(string, " \t\n\r");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> GetLines(const std::string& string)
|
std::vector<std::string> GetLines(const std::string& string)
|
||||||
@ -372,6 +386,7 @@ namespace Prism
|
|||||||
|
|
||||||
static bool IsTypeStringResource(const std::string& type)
|
static bool IsTypeStringResource(const std::string& type)
|
||||||
{
|
{
|
||||||
|
if (type == "sampler1D") return true;
|
||||||
if (type == "sampler2D") return true;
|
if (type == "sampler2D") return true;
|
||||||
if (type == "sampler2DMS") return true;
|
if (type == "sampler2DMS") return true;
|
||||||
if (type == "samplerCube") return true;
|
if (type == "samplerCube") return true;
|
||||||
@ -630,11 +645,11 @@ namespace Prism
|
|||||||
}
|
}
|
||||||
else if (resource->GetCount() > 1)
|
else if (resource->GetCount() > 1)
|
||||||
{
|
{
|
||||||
resource->m_Register = 0;
|
resource->m_Register = sampler;
|
||||||
uint32_t count = resource->GetCount();
|
uint32_t count = resource->GetCount();
|
||||||
int* samplers = new int[count];
|
int* samplers = new int[count];
|
||||||
for (uint32_t s = 0; s < count; s++)
|
for (uint32_t s = 0; s < count; s++)
|
||||||
samplers[s] = s;
|
samplers[s] = sampler++;
|
||||||
UploadUniformIntArray(resource->GetName(), samplers, count);
|
UploadUniformIntArray(resource->GetName(), samplers, count);
|
||||||
delete[] samplers;
|
delete[] samplers;
|
||||||
}
|
}
|
||||||
@ -671,7 +686,7 @@ namespace Prism
|
|||||||
|
|
||||||
std::vector<GLchar> infoLog(maxLength);
|
std::vector<GLchar> infoLog(maxLength);
|
||||||
glGetShaderInfoLog(shaderRendererID, maxLength, &maxLength, &infoLog[0]);
|
glGetShaderInfoLog(shaderRendererID, maxLength, &maxLength, &infoLog[0]);
|
||||||
PM_CORE_ERROR("Shader compile failed: \n{0}", &infoLog[0]);
|
PM_CORE_ERROR("Shader compilation failed ({0}):\n{1}", m_AssetPath, &infoLog[0]);
|
||||||
|
|
||||||
glDeleteShader(shaderRendererID);
|
glDeleteShader(shaderRendererID);
|
||||||
|
|
||||||
@ -692,7 +707,7 @@ namespace Prism
|
|||||||
|
|
||||||
std::vector<GLchar> infoLog(maxLength);
|
std::vector<GLchar> infoLog(maxLength);
|
||||||
glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
|
glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
|
||||||
PM_CORE_ERROR("Shader compilation failed:\n{0}", &infoLog[0]);
|
PM_CORE_ERROR("Shader link failed ({0}):\n{1}", m_AssetPath, &infoLog[0]);
|
||||||
|
|
||||||
glDeleteProgram(program);
|
glDeleteProgram(program);
|
||||||
|
|
||||||
@ -727,7 +742,7 @@ namespace Prism
|
|||||||
if (location != -1)
|
if (location != -1)
|
||||||
glUniform1i(location, value);
|
glUniform1i(location, value);
|
||||||
else
|
else
|
||||||
PM_CORE_WARN("Uniform '{0}' not found!", name);
|
PM_CORE_WARN("{0}: Uniform '{1}' not found!", m_Name,name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLShader::UploadUniformFloat(const std::string& name, const float value) const
|
void OpenGLShader::UploadUniformFloat(const std::string& name, const float value) const
|
||||||
@ -737,7 +752,7 @@ namespace Prism
|
|||||||
if (location != -1)
|
if (location != -1)
|
||||||
glUniform1f(location, value);
|
glUniform1f(location, value);
|
||||||
else
|
else
|
||||||
PM_CORE_WARN("Uniform '{0}' not found!", name);
|
PM_CORE_WARN("{0}: Uniform '{1}' not found!", m_Name,name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLShader::UploadUniformFloat2(const std::string& name, const glm::vec2& values) const
|
void OpenGLShader::UploadUniformFloat2(const std::string& name, const glm::vec2& values) const
|
||||||
@ -747,7 +762,7 @@ namespace Prism
|
|||||||
if (location != -1)
|
if (location != -1)
|
||||||
glUniform2fv(location,1, glm::value_ptr(values));
|
glUniform2fv(location,1, glm::value_ptr(values));
|
||||||
else
|
else
|
||||||
PM_CORE_WARN("Uniform '{0}' not found!", name);
|
PM_CORE_WARN("{0}: Uniform '{1}' not found!", m_Name,name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLShader::UploadUniformFloat3(const std::string& name, const glm::vec3& values) const
|
void OpenGLShader::UploadUniformFloat3(const std::string& name, const glm::vec3& values) const
|
||||||
@ -757,7 +772,7 @@ namespace Prism
|
|||||||
if (location != -1)
|
if (location != -1)
|
||||||
glUniform3fv(location,1, glm::value_ptr(values));
|
glUniform3fv(location,1, glm::value_ptr(values));
|
||||||
else
|
else
|
||||||
PM_CORE_WARN("Uniform '{0}' not found!", name);
|
PM_CORE_WARN("{0}: Uniform '{1}' not found!", m_Name,name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLShader::UploadUniformFloat4(const std::string& name, const glm::vec4& values) const
|
void OpenGLShader::UploadUniformFloat4(const std::string& name, const glm::vec4& values) const
|
||||||
@ -767,7 +782,7 @@ namespace Prism
|
|||||||
if (location != -1)
|
if (location != -1)
|
||||||
glUniform4fv(location,1, glm::value_ptr(values));
|
glUniform4fv(location,1, glm::value_ptr(values));
|
||||||
else
|
else
|
||||||
PM_CORE_WARN("Uniform '{0}' not found!", name);
|
PM_CORE_WARN("{0}: Uniform '{1}' not found!", m_Name,name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLShader::UploadUniformMat4(const std::string& name, const glm::mat4& values) const
|
void OpenGLShader::UploadUniformMat4(const std::string& name, const glm::mat4& values) const
|
||||||
@ -777,7 +792,7 @@ namespace Prism
|
|||||||
if (location != -1)
|
if (location != -1)
|
||||||
glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(values));
|
glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(values));
|
||||||
else
|
else
|
||||||
PM_CORE_WARN("Uniform '{0}' not found!", name);
|
PM_CORE_WARN("{0}: Uniform '{1}' not found!", m_Name,name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLShader::ResolveAndSetUniforms(const Ref<OpenGLShaderUniformBufferDeclaration>& decl, Buffer buffer)
|
void OpenGLShader::ResolveAndSetUniforms(const Ref<OpenGLShaderUniformBufferDeclaration>& decl, Buffer buffer)
|
||||||
@ -803,6 +818,9 @@ namespace Prism
|
|||||||
uint32_t offset = uniform->GetOffset();
|
uint32_t offset = uniform->GetOffset();
|
||||||
switch (uniform->GetType())
|
switch (uniform->GetType())
|
||||||
{
|
{
|
||||||
|
case OpenGLShaderUniformDeclaration::Type::BOOL:
|
||||||
|
UploadUniformFloat(uniform->GetLocation(), *(bool*)&buffer.Data[offset]);
|
||||||
|
break;
|
||||||
case OpenGLShaderUniformDeclaration::Type::FLOAT32:
|
case OpenGLShaderUniformDeclaration::Type::FLOAT32:
|
||||||
UploadUniformFloat(uniform->GetLocation(), *(float*)&buffer.Data[offset]);
|
UploadUniformFloat(uniform->GetLocation(), *(float*)&buffer.Data[offset]);
|
||||||
break;
|
break;
|
||||||
@ -839,6 +857,9 @@ namespace Prism
|
|||||||
uint32_t offset = uniform->GetOffset();
|
uint32_t offset = uniform->GetOffset();
|
||||||
switch (uniform->GetType())
|
switch (uniform->GetType())
|
||||||
{
|
{
|
||||||
|
case OpenGLShaderUniformDeclaration::Type::BOOL:
|
||||||
|
UploadUniformFloat(uniform->GetLocation(), *(bool*)&buffer.Data[offset]);
|
||||||
|
break;
|
||||||
case OpenGLShaderUniformDeclaration::Type::FLOAT32:
|
case OpenGLShaderUniformDeclaration::Type::FLOAT32:
|
||||||
UploadUniformFloat(uniform->GetLocation(), *(float*)&buffer.Data[offset]);
|
UploadUniformFloat(uniform->GetLocation(), *(float*)&buffer.Data[offset]);
|
||||||
break;
|
break;
|
||||||
@ -872,6 +893,9 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
switch (field.GetType())
|
switch (field.GetType())
|
||||||
{
|
{
|
||||||
|
case OpenGLShaderUniformDeclaration::Type::BOOL:
|
||||||
|
UploadUniformFloat(field.GetLocation(), *(bool*)&data[offset]);
|
||||||
|
break;
|
||||||
case OpenGLShaderUniformDeclaration::Type::FLOAT32:
|
case OpenGLShaderUniformDeclaration::Type::FLOAT32:
|
||||||
UploadUniformFloat(field.GetLocation(), *(float*)&data[offset]);
|
UploadUniformFloat(field.GetLocation(), *(float*)&data[offset]);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -27,7 +27,9 @@ namespace Prism
|
|||||||
virtual void UploadUniformBuffer(const UniformBufferBase& uniformBuffer) override;
|
virtual void UploadUniformBuffer(const UniformBufferBase& uniformBuffer) override;
|
||||||
virtual void AddShaderReloadedCallback(const ShaderReloadedCallback& callback) override;
|
virtual void AddShaderReloadedCallback(const ShaderReloadedCallback& callback) override;
|
||||||
|
|
||||||
|
virtual void SetBool(const std::string& name, bool value) override;
|
||||||
virtual void SetFloat(const std::string& name, float value) override;
|
virtual void SetFloat(const std::string& name, float value) override;
|
||||||
|
virtual void SetFloat2(const std::string& name, const glm::vec2& value) override;
|
||||||
virtual void SetFloat3(const std::string& name, const glm::vec3& value) override;
|
virtual void SetFloat3(const std::string& name, const glm::vec3& value) override;
|
||||||
virtual void SetInt(const std::string& name, int value) override;
|
virtual void SetInt(const std::string& name, int value) override;
|
||||||
virtual void SetMat4(const std::string& name, const glm::mat4& value) override;
|
virtual void SetMat4(const std::string& name, const glm::mat4& value) override;
|
||||||
|
|||||||
@ -35,6 +35,7 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
case OpenGLShaderUniformDeclaration::Type::BOOL: return 1;
|
||||||
case OpenGLShaderUniformDeclaration::Type::INT32: return 4;
|
case OpenGLShaderUniformDeclaration::Type::INT32: return 4;
|
||||||
case OpenGLShaderUniformDeclaration::Type::FLOAT32: return 4;
|
case OpenGLShaderUniformDeclaration::Type::FLOAT32: return 4;
|
||||||
case OpenGLShaderUniformDeclaration::Type::VEC2: return 4 * 2;
|
case OpenGLShaderUniformDeclaration::Type::VEC2: return 4 * 2;
|
||||||
@ -48,14 +49,15 @@ namespace Prism
|
|||||||
|
|
||||||
OpenGLShaderUniformDeclaration::Type OpenGLShaderUniformDeclaration::StringToType(const std::string& type)
|
OpenGLShaderUniformDeclaration::Type OpenGLShaderUniformDeclaration::StringToType(const std::string& type)
|
||||||
{
|
{
|
||||||
if (type == "int") return Type::INT32;
|
if (type == "bool") return OpenGLShaderUniformDeclaration::Type::BOOL;
|
||||||
if (type == "int32") return Type::INT32;
|
if (type == "int") return OpenGLShaderUniformDeclaration::Type::INT32;
|
||||||
if (type == "float") return Type::FLOAT32;
|
if (type == "int32") return OpenGLShaderUniformDeclaration::Type::INT32;
|
||||||
if (type == "vec2") return Type::VEC2;
|
if (type == "float") return OpenGLShaderUniformDeclaration::Type::FLOAT32;
|
||||||
if (type == "vec3") return Type::VEC3;
|
if (type == "vec2") return OpenGLShaderUniformDeclaration::Type::VEC2;
|
||||||
if (type == "vec4") return Type::VEC4;
|
if (type == "vec3") return OpenGLShaderUniformDeclaration::Type::VEC3;
|
||||||
if (type == "mat3") return Type::MAT3;
|
if (type == "vec4") return OpenGLShaderUniformDeclaration::Type::VEC4;
|
||||||
if (type == "mat4") return Type::MAT4;
|
if (type == "mat3") return OpenGLShaderUniformDeclaration::Type::MAT3;
|
||||||
|
if (type == "mat4") return OpenGLShaderUniformDeclaration::Type::MAT4;
|
||||||
|
|
||||||
return Type::NONE;
|
return Type::NONE;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,7 +44,7 @@ namespace Prism
|
|||||||
public:
|
public:
|
||||||
enum class Type
|
enum class Type
|
||||||
{
|
{
|
||||||
NONE, FLOAT32, VEC2, VEC3, VEC4, MAT3, MAT4, INT32, STRUCT
|
NONE, FLOAT32, VEC2, VEC3, VEC4, MAT3, MAT4, INT32, STRUCT, BOOL
|
||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
std::string m_Name;
|
std::string m_Name;
|
||||||
|
|||||||
@ -67,7 +67,7 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
PM_CORE_INFO("Loading texture {0}, srgb={1}", path, srgb);
|
PM_CORE_INFO("Loading texture {0}, srgb={1}", path, srgb);
|
||||||
m_ImageData.Data = stbi_load(path.c_str(), &width, &height, &channels, srgb ? STBI_rgb : STBI_rgb_alpha);
|
m_ImageData.Data = stbi_load(path.c_str(), &width, &height, &channels, srgb ? STBI_rgb : STBI_rgb_alpha);
|
||||||
PM_CORE_ASSERT(m_ImageData.Data, "Could not read image!");
|
if (!m_ImageData.Data) PM_CORE_ERROR("Could not read image file: {0}", path);
|
||||||
m_Format = TextureFormat::RGBA;
|
m_Format = TextureFormat::RGBA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -47,7 +47,12 @@ namespace Prism
|
|||||||
glfwSetCursor(m_Window, m_ImGuiMouseCursors[imgui_cursor] ? m_ImGuiMouseCursors[imgui_cursor] : m_ImGuiMouseCursors[ImGuiMouseCursor_Arrow]);
|
glfwSetCursor(m_Window, m_ImGuiMouseCursors[imgui_cursor] ? m_ImGuiMouseCursors[imgui_cursor] : m_ImGuiMouseCursors[ImGuiMouseCursor_Arrow]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowsWindow::SetVSync(bool enable)
|
void WindowsWindow::Maximize()
|
||||||
|
{
|
||||||
|
glfwMaximizeWindow(m_Window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowsWindow::SetVSync(const bool enable)
|
||||||
{
|
{
|
||||||
if (enable)
|
if (enable)
|
||||||
glfwSwapInterval(1);
|
glfwSwapInterval(1);
|
||||||
|
|||||||
@ -22,6 +22,9 @@ namespace Prism
|
|||||||
inline uint32_t GetHeight() const override { return m_Data.Height; }
|
inline uint32_t GetHeight() const override { return m_Data.Height; }
|
||||||
|
|
||||||
inline void SetEventCallback(const EventCallbackFn& callback) override { m_Data.EventCallback = callback; }
|
inline void SetEventCallback(const EventCallbackFn& callback) override { m_Data.EventCallback = callback; }
|
||||||
|
|
||||||
|
virtual void Maximize() override;
|
||||||
|
|
||||||
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<uint32_t, uint32_t> GetSize() const override { return { m_Data.Width, m_Data.Height }; }
|
||||||
|
|||||||
@ -11,11 +11,40 @@
|
|||||||
|
|
||||||
namespace Prism
|
namespace Prism
|
||||||
{
|
{
|
||||||
enum class FramebufferFormat
|
enum class FramebufferTextureFormat
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
|
|
||||||
|
// Color
|
||||||
RGBA8 = 1,
|
RGBA8 = 1,
|
||||||
RGBA16F = 2
|
RGBA16F = 2,
|
||||||
|
RGBA32F = 3,
|
||||||
|
RG32F = 4,
|
||||||
|
|
||||||
|
// Depth/stencil
|
||||||
|
DEPTH32F = 5,
|
||||||
|
DEPTH24STENCIL8 = 6,
|
||||||
|
|
||||||
|
// Defaults
|
||||||
|
Depth = DEPTH24STENCIL8
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FramebufferTextureSpecification
|
||||||
|
{
|
||||||
|
FramebufferTextureSpecification() = default;
|
||||||
|
FramebufferTextureSpecification(FramebufferTextureFormat format) : TextureFormat(format) {}
|
||||||
|
|
||||||
|
FramebufferTextureFormat TextureFormat;
|
||||||
|
// TODO: filtering/wrap
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FramebufferAttachmentSpecification
|
||||||
|
{
|
||||||
|
FramebufferAttachmentSpecification() = default;
|
||||||
|
FramebufferAttachmentSpecification(const std::initializer_list<FramebufferTextureSpecification>& attachments)
|
||||||
|
: Attachments(attachments) {}
|
||||||
|
|
||||||
|
std::vector<FramebufferTextureSpecification> Attachments;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FramebufferSpecification
|
struct FramebufferSpecification
|
||||||
@ -23,13 +52,17 @@ namespace Prism
|
|||||||
uint32_t Width = 1280;
|
uint32_t Width = 1280;
|
||||||
uint32_t Height = 720;
|
uint32_t Height = 720;
|
||||||
glm::vec4 ClearColor;
|
glm::vec4 ClearColor;
|
||||||
FramebufferFormat Format;
|
FramebufferAttachmentSpecification Attachments;
|
||||||
uint32_t Samples = 1;
|
uint32_t Samples = 1; // multisampling
|
||||||
|
|
||||||
|
// TODO: Temp, needs scale
|
||||||
|
bool NoResize = false;
|
||||||
|
|
||||||
// SwapChainTarget = screen buffer (i.e. no framebuffer)
|
// SwapChainTarget = screen buffer (i.e. no framebuffer)
|
||||||
bool SwapChainTarget = false;
|
bool SwapChainTarget = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class PRISM_API FrameBuffer : public RefCounted
|
class PRISM_API FrameBuffer : public RefCounted
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -44,10 +77,13 @@ namespace Prism
|
|||||||
|
|
||||||
virtual void Resize(uint32_t width, uint32_t height, bool forceReCreate = false) = 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 attachmentIndex = 0, uint32_t slot = 0) const = 0;
|
||||||
|
|
||||||
|
virtual uint32_t GetWidth() const = 0;
|
||||||
|
virtual uint32_t GetHeight() const = 0;
|
||||||
|
|
||||||
virtual RendererID GetRendererID() const = 0;
|
virtual RendererID GetRendererID() const = 0;
|
||||||
virtual RendererID GetColorAttachmentRendererID() const = 0;
|
virtual RendererID GetColorAttachmentRendererID(int index = 0) const = 0;
|
||||||
virtual RendererID GetDepthAttachmentRendererID() const = 0;
|
virtual RendererID GetDepthAttachmentRendererID() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,8 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
None = BIT(0),
|
None = BIT(0),
|
||||||
DepthTest = BIT(1),
|
DepthTest = BIT(1),
|
||||||
Blend = BIT(2)
|
Blend = BIT(2),
|
||||||
|
TwoSided = BIT(3),
|
||||||
};
|
};
|
||||||
|
|
||||||
class PRISM_API Material : public RefCounted
|
class PRISM_API Material : public RefCounted
|
||||||
@ -38,6 +39,9 @@ namespace Prism
|
|||||||
uint32_t GetFlags() const { return m_MaterialFlags; }
|
uint32_t GetFlags() const { return m_MaterialFlags; }
|
||||||
void SetFlag(MaterialFlag flag) { m_MaterialFlags |= (uint32_t)flag; }
|
void SetFlag(MaterialFlag flag) { m_MaterialFlags |= (uint32_t)flag; }
|
||||||
|
|
||||||
|
Ref<Shader> GetShader() { return m_Shader; }
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T& Get(const std::string& name)
|
T& Get(const std::string& name)
|
||||||
{
|
{
|
||||||
@ -83,13 +87,14 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
Set(name, (const Ref<Texture>&)texture);
|
Set(name, (const Ref<Texture>&)texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ShaderResourceDeclaration* FindResourceDeclaration(const std::string& name);
|
||||||
private:
|
private:
|
||||||
void AllocateStorage();
|
void AllocateStorage();
|
||||||
void OnShaderReloaded();
|
void OnShaderReloaded();
|
||||||
void BindTextures() const;
|
void BindTextures() const;
|
||||||
|
|
||||||
ShaderUniformDeclaration* FindUniformDeclaration(const std::string& name);
|
ShaderUniformDeclaration* FindUniformDeclaration(const std::string& name);
|
||||||
ShaderResourceDeclaration* FindResourceDeclaration(const std::string& name);
|
|
||||||
Buffer& GetUniformBufferTarget(ShaderUniformDeclaration* uniformDeclaration);
|
Buffer& GetUniformBufferTarget(ShaderUniformDeclaration* uniformDeclaration);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -153,8 +158,8 @@ namespace Prism
|
|||||||
void Set(const std::string& name, const T& value)
|
void Set(const std::string& name, const T& value)
|
||||||
{
|
{
|
||||||
const auto decl = m_Material->FindUniformDeclaration(name);
|
const auto decl = m_Material->FindUniformDeclaration(name);
|
||||||
if (!decl) PM_CORE_WARN("Could not find uniform with name {0}", name);
|
if (!decl) PM_CORE_ERROR("Could not find uniform with name {0}", name);
|
||||||
auto& buffer = GetUniformBufferTarget(decl);
|
const auto& buffer = GetUniformBufferTarget(decl);
|
||||||
buffer.Write(&value, decl->GetSize(), decl->GetOffset());
|
buffer.Write(&value, decl->GetSize(), decl->GetOffset());
|
||||||
|
|
||||||
m_OverriddenValues.insert(name);
|
m_OverriddenValues.insert(name);
|
||||||
@ -207,6 +212,7 @@ namespace Prism
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
void Material::Set(const std::string& name, const T& value)
|
void Material::Set(const std::string& name, const T& value)
|
||||||
{
|
{
|
||||||
|
|
||||||
auto decl = FindUniformDeclaration(name);
|
auto decl = FindUniformDeclaration(name);
|
||||||
PM_CORE_ASSERT(decl, "Could not find uniform with name x");
|
PM_CORE_ASSERT(decl, "Could not find uniform with name x");
|
||||||
const auto& buffer = GetUniformBufferTarget(decl);
|
const auto& buffer = GetUniformBufferTarget(decl);
|
||||||
|
|||||||
@ -50,7 +50,7 @@ namespace Prism
|
|||||||
|
|
||||||
virtual void write(const char* message) override
|
virtual void write(const char* message) override
|
||||||
{
|
{
|
||||||
PM_CORE_ERROR("Assimp: {0}", message);
|
PM_CORE_WARN("Assimp: {0}", message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -131,10 +131,11 @@ namespace Prism
|
|||||||
submesh.BaseIndex = indexCount;
|
submesh.BaseIndex = indexCount;
|
||||||
submesh.MaterialIndex = mesh->mMaterialIndex;
|
submesh.MaterialIndex = mesh->mMaterialIndex;
|
||||||
submesh.IndexCount = mesh->mNumFaces * 3;
|
submesh.IndexCount = mesh->mNumFaces * 3;
|
||||||
|
submesh.VertexCount = mesh->mNumVertices;
|
||||||
// m_Submeshes.push_back(submesh);
|
// m_Submeshes.push_back(submesh);
|
||||||
submesh.MeshName = mesh->mName.C_Str();
|
submesh.MeshName = mesh->mName.C_Str();
|
||||||
|
|
||||||
vertexCount += mesh->mNumVertices;
|
vertexCount += submesh.VertexCount;
|
||||||
indexCount += submesh.IndexCount;
|
indexCount += submesh.IndexCount;
|
||||||
|
|
||||||
PM_CORE_ASSERT(mesh->HasPositions(), "Meshes require positions.");
|
PM_CORE_ASSERT(mesh->HasPositions(), "Meshes require positions.");
|
||||||
|
|||||||
@ -94,6 +94,7 @@ namespace Prism
|
|||||||
uint32_t BaseIndex;
|
uint32_t BaseIndex;
|
||||||
uint32_t MaterialIndex;
|
uint32_t MaterialIndex;
|
||||||
uint32_t IndexCount;
|
uint32_t IndexCount;
|
||||||
|
uint32_t VertexCount;
|
||||||
|
|
||||||
glm::mat4 Transform;
|
glm::mat4 Transform;
|
||||||
AABB BoundingBox;
|
AABB BoundingBox;
|
||||||
@ -126,6 +127,8 @@ namespace Prism
|
|||||||
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; }
|
||||||
|
|
||||||
|
bool IsAnimated() const { return m_IsAnimated; }
|
||||||
|
|
||||||
std::vector<Triangle> GetTriangleCache(const uint32_t index) const { return m_TriangleCache.at(index); }
|
std::vector<Triangle> GetTriangleCache(const uint32_t index) const { return m_TriangleCache.at(index); }
|
||||||
private:
|
private:
|
||||||
void BoneTransform(float time);
|
void BoneTransform(float time);
|
||||||
|
|||||||
@ -135,31 +135,46 @@ namespace Prism
|
|||||||
void Renderer::SubmitQuad(Ref<MaterialInstance>& material, const glm::mat4& transform)
|
void Renderer::SubmitQuad(Ref<MaterialInstance>& material, const glm::mat4& transform)
|
||||||
{
|
{
|
||||||
bool depthTest = true;
|
bool depthTest = true;
|
||||||
|
bool cullFace = true;
|
||||||
|
|
||||||
if (material)
|
if (material)
|
||||||
{
|
{
|
||||||
material->Bind();
|
material->Bind();
|
||||||
depthTest = material->GetFlag(MaterialFlag::DepthTest);
|
depthTest = material->GetFlag(MaterialFlag::DepthTest);
|
||||||
|
cullFace = !material->GetFlag(MaterialFlag::TwoSided);
|
||||||
|
|
||||||
auto shader = material->GetShader();
|
auto shader = material->GetShader();
|
||||||
shader->SetMat4("u_Transform", transform);
|
shader->SetMat4("u_Transform", transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cullFace)
|
||||||
|
Submit([]() { glEnable(GL_CULL_FACE); });
|
||||||
|
else
|
||||||
|
Submit([]() { glDisable(GL_CULL_FACE); });
|
||||||
|
|
||||||
s_Data.m_FullscreenQuadVertexBuffer->Bind();
|
s_Data.m_FullscreenQuadVertexBuffer->Bind();
|
||||||
s_Data.m_FullscreenQuadPipeline->Bind();
|
s_Data.m_FullscreenQuadPipeline->Bind();
|
||||||
s_Data.m_FullscreenQuadIndexBuffer->Bind();
|
s_Data.m_FullscreenQuadIndexBuffer->Bind();
|
||||||
|
|
||||||
Renderer::DrawIndexed(6, PrimitiveType::Triangles, depthTest);
|
DrawIndexed(6, PrimitiveType::Triangles, depthTest);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::SubmitFullscreenQuad(Ref<MaterialInstance> material)
|
void Renderer::SubmitFullscreenQuad(Ref<MaterialInstance> material)
|
||||||
{
|
{
|
||||||
bool depthTest = true;
|
bool depthTest = true;
|
||||||
|
bool cullFace = true;
|
||||||
if (material)
|
if (material)
|
||||||
{
|
{
|
||||||
material->Bind();
|
material->Bind();
|
||||||
depthTest = material->GetFlag(MaterialFlag::DepthTest);
|
depthTest = material->GetFlag(MaterialFlag::DepthTest);
|
||||||
|
cullFace = !material->GetFlag(MaterialFlag::TwoSided);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cullFace)
|
||||||
|
Submit([]() { glEnable(GL_CULL_FACE); });
|
||||||
|
else
|
||||||
|
Submit([]() { glDisable(GL_CULL_FACE); });
|
||||||
|
|
||||||
s_Data.m_FullscreenQuadVertexBuffer->Bind();
|
s_Data.m_FullscreenQuadVertexBuffer->Bind();
|
||||||
s_Data.m_FullscreenQuadPipeline->Bind();
|
s_Data.m_FullscreenQuadPipeline->Bind();
|
||||||
s_Data.m_FullscreenQuadIndexBuffer->Bind();
|
s_Data.m_FullscreenQuadIndexBuffer->Bind();
|
||||||
@ -201,6 +216,36 @@ namespace Prism
|
|||||||
else
|
else
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
|
if (!material->GetFlag(MaterialFlag::TwoSided))
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
else
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
|
||||||
|
|
||||||
|
glDrawElementsBaseVertex(GL_TRIANGLES, submesh.IndexCount, GL_UNSIGNED_INT, (void*)(sizeof(uint32_t) * submesh.BaseIndex), submesh.BaseVertex);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::SubmitMeshWithShader(Ref<Mesh> mesh, const glm::mat4& transform, Ref<Shader> shader)
|
||||||
|
{
|
||||||
|
mesh->m_VertexBuffer->Bind();
|
||||||
|
mesh->m_Pipeline->Bind();
|
||||||
|
mesh->m_IndexBuffer->Bind();
|
||||||
|
|
||||||
|
for (Submesh& submesh : mesh->m_Submeshes)
|
||||||
|
{
|
||||||
|
if (mesh->m_IsAnimated)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < mesh->m_BoneTransforms.size(); i++)
|
||||||
|
{
|
||||||
|
std::string uniformName = std::string("u_BoneTransforms[") + std::to_string(i) + std::string("]");
|
||||||
|
shader->SetMat4(uniformName, mesh->m_BoneTransforms[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
shader->SetMat4("u_Transform", transform * submesh.Transform);
|
||||||
|
|
||||||
|
Submit([submesh]() {
|
||||||
glDrawElementsBaseVertex(GL_TRIANGLES, submesh.IndexCount, GL_UNSIGNED_INT, (void*)(sizeof(uint32_t) * submesh.BaseIndex), submesh.BaseVertex);
|
glDrawElementsBaseVertex(GL_TRIANGLES, submesh.IndexCount, GL_UNSIGNED_INT, (void*)(sizeof(uint32_t) * submesh.BaseIndex), submesh.BaseVertex);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -55,6 +55,7 @@ namespace Prism
|
|||||||
static void SubmitQuad(Ref<MaterialInstance>& material, const glm::mat4& transform = glm::mat4(1.0f));
|
static void SubmitQuad(Ref<MaterialInstance>& material, const glm::mat4& transform = glm::mat4(1.0f));
|
||||||
static void SubmitFullscreenQuad(Ref<MaterialInstance> material);
|
static void SubmitFullscreenQuad(Ref<MaterialInstance> material);
|
||||||
static void SubmitMesh(Ref<Mesh>& mesh, const glm::mat4& transform, const Ref<MaterialInstance>& overrideMaterial = nullptr);
|
static void SubmitMesh(Ref<Mesh>& mesh, const glm::mat4& transform, const Ref<MaterialInstance>& overrideMaterial = nullptr);
|
||||||
|
static void SubmitMeshWithShader(Ref<Mesh> mesh, const glm::mat4& transform, Ref<Shader> shader);
|
||||||
|
|
||||||
static void DrawAABB(const AABB& aabb, const glm::mat4& transform, 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));
|
static void DrawAABB(const Ref<Mesh>& mesh,const glm::mat4& transform, const glm::vec4& color = glm::vec4(1.0f));
|
||||||
|
|||||||
@ -187,7 +187,7 @@ namespace Prism
|
|||||||
s_Data.QuadVertexBuffer->Bind();
|
s_Data.QuadVertexBuffer->Bind();
|
||||||
s_Data.QuadPipeline->Bind();
|
s_Data.QuadPipeline->Bind();
|
||||||
s_Data.QuadIndexBuffer->Bind();
|
s_Data.QuadIndexBuffer->Bind();
|
||||||
Renderer::DrawIndexed(s_Data.QuadIndexCount, PrimitiveType::Triangles, s_Data.DepthTest);
|
Renderer::DrawIndexed(s_Data.QuadIndexCount, PrimitiveType::Triangles, false);
|
||||||
s_Data.Stats.DrawCalls++;
|
s_Data.Stats.DrawCalls++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
15
Prism/src/Prism/Renderer/SceneEnvironment.cpp
Normal file
15
Prism/src/Prism/Renderer/SceneEnvironment.cpp
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// Created by sfd on 26-1-1.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "SceneEnvironment.h"
|
||||||
|
#include "SceneRenderer.h"
|
||||||
|
|
||||||
|
namespace Prism
|
||||||
|
{
|
||||||
|
Environment Environment::Load(const std::string& filepath)
|
||||||
|
{
|
||||||
|
auto [radiance, irradiance] = SceneRenderer::CreateEnvironmentMap(filepath);
|
||||||
|
return { filepath, radiance, irradiance };
|
||||||
|
}
|
||||||
|
}
|
||||||
24
Prism/src/Prism/Renderer/SceneEnvironment.h
Normal file
24
Prism/src/Prism/Renderer/SceneEnvironment.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
//
|
||||||
|
// Created by sfd on 26-1-1.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SCENEENVIRONMENT_H
|
||||||
|
#define SCENEENVIRONMENT_H
|
||||||
|
#include "Texture.h"
|
||||||
|
#include "Prism/Core/Ref.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Prism
|
||||||
|
{
|
||||||
|
struct Environment
|
||||||
|
{
|
||||||
|
std::string FilePath;
|
||||||
|
Ref<TextureCube> RadianceMap;
|
||||||
|
Ref<TextureCube> IrradianceMap;
|
||||||
|
|
||||||
|
static PRISM_API Environment Load(const std::string& filepath);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif //SCENEENVIRONMENT_H
|
||||||
@ -12,6 +12,7 @@
|
|||||||
#include "Renderer2D.h"
|
#include "Renderer2D.h"
|
||||||
#include "RenderPass.h"
|
#include "RenderPass.h"
|
||||||
#include "glad/glad.h"
|
#include "glad/glad.h"
|
||||||
|
#include "Prism/Core/Timer.h"
|
||||||
|
|
||||||
namespace Prism
|
namespace Prism
|
||||||
{
|
{
|
||||||
@ -21,6 +22,8 @@ namespace Prism
|
|||||||
struct SceneInfo
|
struct SceneInfo
|
||||||
{
|
{
|
||||||
SceneRendererCamera SceneCamera;
|
SceneRendererCamera SceneCamera;
|
||||||
|
float SceneEnvironmentIntensity;
|
||||||
|
LightEnvironment SceneLightEnvironment;
|
||||||
|
|
||||||
// Resources
|
// Resources
|
||||||
Ref<MaterialInstance> SkyboxMaterial;
|
Ref<MaterialInstance> SkyboxMaterial;
|
||||||
@ -30,9 +33,37 @@ namespace Prism
|
|||||||
|
|
||||||
Ref<Texture2D> BRDFLUT;
|
Ref<Texture2D> BRDFLUT;
|
||||||
Ref<Shader> CompositeShader;
|
Ref<Shader> CompositeShader;
|
||||||
|
Ref<Shader> BloomBlurShader;
|
||||||
|
Ref<Shader> BloomBlendShader;
|
||||||
|
|
||||||
Ref<RenderPass> GeoPass;
|
Ref<RenderPass> GeoPass;
|
||||||
Ref<RenderPass> CompositePass;
|
Ref<RenderPass> CompositePass;
|
||||||
|
Ref<RenderPass> BloomBlurPass[2];
|
||||||
|
Ref<RenderPass> BloomBlendPass;
|
||||||
|
|
||||||
|
Ref<Shader> ShadowMapShader, ShadowMapAnimShader;
|
||||||
|
Ref<RenderPass> ShadowMapRenderPass[4];
|
||||||
|
float ShadowMapSize = 20.0f;
|
||||||
|
float LightDistance = 0.1f;
|
||||||
|
glm::mat4 LightMatrices[4];
|
||||||
|
glm::mat4 LightViewMatrix;
|
||||||
|
float CascadeSplitLambda = 0.91f;
|
||||||
|
glm::vec4 CascadeSplits;
|
||||||
|
float CascadeFarPlaneOffset = 15.0f, CascadeNearPlaneOffset = -15.0f;
|
||||||
|
bool ShowCascades = false;
|
||||||
|
bool SoftShadows = true;
|
||||||
|
float LightSize = 0.5f;
|
||||||
|
float MaxShadowDistance = 200.0f;
|
||||||
|
float ShadowFade = 25.0f;
|
||||||
|
float CascadeTransitionFade = 1.0f;
|
||||||
|
bool CascadeFading = true;
|
||||||
|
|
||||||
|
bool EnableBloom = false;
|
||||||
|
float BloomThreshold = 1.5f;
|
||||||
|
|
||||||
|
glm::vec2 FocusPoint = { 0.5f, 0.5f };
|
||||||
|
|
||||||
|
RendererID ShadowMapSampler;
|
||||||
|
|
||||||
struct DrawCommand
|
struct DrawCommand
|
||||||
{
|
{
|
||||||
@ -43,23 +74,34 @@ namespace Prism
|
|||||||
std::vector<DrawCommand> DrawList;
|
std::vector<DrawCommand> DrawList;
|
||||||
std::vector<DrawCommand> SelectedMeshDrawList;
|
std::vector<DrawCommand> SelectedMeshDrawList;
|
||||||
std::vector<DrawCommand> ColliderDrawList;
|
std::vector<DrawCommand> ColliderDrawList;
|
||||||
|
std::vector<DrawCommand> ShadowPassDrawList;
|
||||||
|
|
||||||
// Grid
|
// Grid
|
||||||
Ref<MaterialInstance> GridMaterial;
|
Ref<MaterialInstance> GridMaterial;
|
||||||
Ref<MaterialInstance> OutlineMaterial;
|
Ref<MaterialInstance> OutlineMaterial, OutlineAnimMaterial;
|
||||||
Ref<MaterialInstance> ColliderMaterial;
|
Ref<MaterialInstance> ColliderMaterial;
|
||||||
|
|
||||||
SceneRendererOptions Options;
|
SceneRendererOptions Options;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SceneRendererStats
|
||||||
|
{
|
||||||
|
float ShadowPass = 0.0f;
|
||||||
|
float GeometryPass = 0.0f;
|
||||||
|
float CompositePass = 0.0f;
|
||||||
|
|
||||||
|
Timer ShadowPassTimer;
|
||||||
|
Timer GeometryPassTimer;
|
||||||
|
Timer CompositePassTimer;
|
||||||
|
};
|
||||||
|
|
||||||
static SceneRendererData s_Data;
|
static SceneRendererData s_Data;
|
||||||
|
static SceneRendererStats s_Stats;
|
||||||
|
|
||||||
void SceneRenderer::Init()
|
void SceneRenderer::Init()
|
||||||
{
|
{
|
||||||
FramebufferSpecification geoFramebufferSpec;
|
FramebufferSpecification geoFramebufferSpec;
|
||||||
geoFramebufferSpec.Width = 1280;
|
geoFramebufferSpec.Attachments = { FramebufferTextureFormat::RGBA16F, FramebufferTextureFormat::RGBA16F, FramebufferTextureFormat::Depth };
|
||||||
geoFramebufferSpec.Height = 720;
|
|
||||||
geoFramebufferSpec.Format = FramebufferFormat::RGBA16F;
|
|
||||||
geoFramebufferSpec.Samples = 8;
|
geoFramebufferSpec.Samples = 8;
|
||||||
geoFramebufferSpec.ClearColor = { 0.1f, 0.1f, 0.1f, 1.0f };
|
geoFramebufferSpec.ClearColor = { 0.1f, 0.1f, 0.1f, 1.0f };
|
||||||
|
|
||||||
@ -68,16 +110,34 @@ namespace Prism
|
|||||||
s_Data.GeoPass = RenderPass::Create(geoRenderPassSpec);
|
s_Data.GeoPass = RenderPass::Create(geoRenderPassSpec);
|
||||||
|
|
||||||
FramebufferSpecification compFramebufferSpec;
|
FramebufferSpecification compFramebufferSpec;
|
||||||
compFramebufferSpec.Width = 1280;
|
compFramebufferSpec.Attachments = { FramebufferTextureFormat::RGBA8 };
|
||||||
compFramebufferSpec.Height = 720;
|
compFramebufferSpec.ClearColor = { 0.1f, 0.1f, 0.1f, 1.0f };
|
||||||
compFramebufferSpec.Format = FramebufferFormat::RGBA8;
|
|
||||||
compFramebufferSpec.ClearColor = { 0.5f, 0.1f, 0.1f, 1.0f };
|
|
||||||
|
|
||||||
RenderPassSpecification compRenderPassSpec;
|
RenderPassSpecification compRenderPassSpec;
|
||||||
compRenderPassSpec.TargetFramebuffer = FrameBuffer::Create(compFramebufferSpec);
|
compRenderPassSpec.TargetFramebuffer = FrameBuffer::Create(compFramebufferSpec);
|
||||||
s_Data.CompositePass = RenderPass::Create(compRenderPassSpec);
|
s_Data.CompositePass = RenderPass::Create(compRenderPassSpec);
|
||||||
|
|
||||||
|
FramebufferSpecification bloomBlurFramebufferSpec;
|
||||||
|
bloomBlurFramebufferSpec.Attachments = { FramebufferTextureFormat::RGBA16F };
|
||||||
|
bloomBlurFramebufferSpec.ClearColor = { 0.1f, 0.1f, 0.1f, 1.0f };
|
||||||
|
|
||||||
|
RenderPassSpecification bloomBlurRenderPassSpec;
|
||||||
|
bloomBlurRenderPassSpec.TargetFramebuffer = FrameBuffer::Create(bloomBlurFramebufferSpec);
|
||||||
|
s_Data.BloomBlurPass[0] = RenderPass::Create(bloomBlurRenderPassSpec);
|
||||||
|
bloomBlurRenderPassSpec.TargetFramebuffer = FrameBuffer::Create(bloomBlurFramebufferSpec);
|
||||||
|
s_Data.BloomBlurPass[1] = RenderPass::Create(bloomBlurRenderPassSpec);
|
||||||
|
|
||||||
|
FramebufferSpecification bloomBlendFramebufferSpec;
|
||||||
|
bloomBlendFramebufferSpec.Attachments = { FramebufferTextureFormat::RGBA8 };
|
||||||
|
bloomBlendFramebufferSpec.ClearColor = { 0.1f, 0.1f, 0.1f, 1.0f };
|
||||||
|
|
||||||
|
RenderPassSpecification bloomBlendRenderPassSpec;
|
||||||
|
bloomBlendRenderPassSpec.TargetFramebuffer = FrameBuffer::Create(bloomBlendFramebufferSpec);
|
||||||
|
s_Data.BloomBlendPass = RenderPass::Create(bloomBlendRenderPassSpec);
|
||||||
|
|
||||||
s_Data.CompositeShader = Shader::Create("assets/shaders/SceneComposite.glsl");
|
s_Data.CompositeShader = Shader::Create("assets/shaders/SceneComposite.glsl");
|
||||||
|
s_Data.BloomBlurShader = Shader::Create("assets/shaders/BloomBlur.glsl");
|
||||||
|
s_Data.BloomBlendShader = Shader::Create("assets/shaders/BloomBlend.glsl");
|
||||||
s_Data.BRDFLUT = Texture2D::Create("assets/textures/BRDF_LUT.tga");
|
s_Data.BRDFLUT = Texture2D::Create("assets/textures/BRDF_LUT.tga");
|
||||||
|
|
||||||
|
|
||||||
@ -98,6 +158,41 @@ namespace Prism
|
|||||||
const auto colliderShader = Shader::Create("assets/shaders/Collider.glsl");
|
const auto colliderShader = Shader::Create("assets/shaders/Collider.glsl");
|
||||||
s_Data.ColliderMaterial = MaterialInstance::Create(Material::Create(colliderShader));
|
s_Data.ColliderMaterial = MaterialInstance::Create(Material::Create(colliderShader));
|
||||||
s_Data.ColliderMaterial->SetFlag(MaterialFlag::DepthTest, false);
|
s_Data.ColliderMaterial->SetFlag(MaterialFlag::DepthTest, false);
|
||||||
|
|
||||||
|
auto outlineAnimShader = Shader::Create("assets/shaders/Outline_Anim.glsl");
|
||||||
|
s_Data.OutlineAnimMaterial = MaterialInstance::Create(Material::Create(outlineAnimShader));
|
||||||
|
s_Data.OutlineAnimMaterial->SetFlag(MaterialFlag::DepthTest, false);
|
||||||
|
|
||||||
|
// Shadow Map
|
||||||
|
s_Data.ShadowMapShader = Shader::Create("assets/shaders/ShadowMap.glsl");
|
||||||
|
s_Data.ShadowMapAnimShader = Shader::Create("assets/shaders/ShadowMap_Anim.glsl");
|
||||||
|
|
||||||
|
FramebufferSpecification shadowMapFramebufferSpec;
|
||||||
|
shadowMapFramebufferSpec.Width = 4096;
|
||||||
|
shadowMapFramebufferSpec.Height = 4096;
|
||||||
|
shadowMapFramebufferSpec.Attachments = { FramebufferTextureFormat::DEPTH32F };
|
||||||
|
shadowMapFramebufferSpec.ClearColor = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||||
|
shadowMapFramebufferSpec.NoResize = true;
|
||||||
|
|
||||||
|
// 4 cascades
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
RenderPassSpecification shadowMapRenderPassSpec;
|
||||||
|
shadowMapRenderPassSpec.TargetFramebuffer = FrameBuffer::Create(shadowMapFramebufferSpec);
|
||||||
|
s_Data.ShadowMapRenderPass[i] = RenderPass::Create(shadowMapRenderPassSpec);
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderer::Submit([]()
|
||||||
|
{
|
||||||
|
glGenSamplers(1, &s_Data.ShadowMapSampler);
|
||||||
|
|
||||||
|
// Setup the shadowmap depth sampler
|
||||||
|
glSamplerParameteri(s_Data.ShadowMapSampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glSamplerParameteri(s_Data.ShadowMapSampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glSamplerParameteri(s_Data.ShadowMapSampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glSamplerParameteri(s_Data.ShadowMapSampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneRenderer::SetViewportSize(uint32_t width, uint32_t height)
|
void SceneRenderer::SetViewportSize(uint32_t width, uint32_t height)
|
||||||
@ -115,7 +210,9 @@ namespace Prism
|
|||||||
s_Data.SceneData.SceneCamera = camera;
|
s_Data.SceneData.SceneCamera = 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.SceneEnvironmentIntensity = scene->m_EnvironmentIntensity;
|
||||||
s_Data.SceneData.ActiveLight = scene->m_Light;
|
s_Data.SceneData.ActiveLight = scene->m_Light;
|
||||||
|
s_Data.SceneData.SceneLightEnvironment = scene->m_LightEnvironment;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneRenderer::EndScene()
|
void SceneRenderer::EndScene()
|
||||||
@ -132,11 +229,13 @@ namespace Prism
|
|||||||
// TODO: Culling, sorting, etc.
|
// TODO: Culling, sorting, etc.
|
||||||
|
|
||||||
s_Data.DrawList.push_back({ mesh, overrideMaterial, transform });
|
s_Data.DrawList.push_back({ mesh, overrideMaterial, transform });
|
||||||
|
s_Data.ShadowPassDrawList.push_back({ mesh, overrideMaterial, transform });
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneRenderer::SubmitSelectedMesh(const Ref<Mesh>& mesh, const glm::mat4& transform)
|
void SceneRenderer::SubmitSelectedMesh(const Ref<Mesh>& mesh, const glm::mat4& transform)
|
||||||
{
|
{
|
||||||
s_Data.SelectedMeshDrawList.push_back({ mesh, nullptr, transform });
|
s_Data.SelectedMeshDrawList.push_back({ mesh, nullptr, transform });
|
||||||
|
s_Data.ShadowPassDrawList.push_back({ mesh, nullptr, transform });
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneRenderer::SubmitColliderMesh(const BoxColliderComponent& component, const glm::mat4& parentTransform)
|
void SceneRenderer::SubmitColliderMesh(const BoxColliderComponent& component, const glm::mat4& parentTransform)
|
||||||
@ -156,7 +255,8 @@ namespace Prism
|
|||||||
|
|
||||||
void SceneRenderer::SubmitColliderMesh(const MeshColliderComponent& component, const glm::mat4& parentTransform)
|
void SceneRenderer::SubmitColliderMesh(const MeshColliderComponent& component, const glm::mat4& parentTransform)
|
||||||
{
|
{
|
||||||
s_Data.ColliderDrawList.push_back({ component.ProcessedMesh, nullptr, parentTransform });
|
for (const auto debugMesh : component.ProcessedMeshes)
|
||||||
|
s_Data.ColliderDrawList.push_back({ debugMesh, nullptr, parentTransform });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -237,6 +337,11 @@ namespace Prism
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SceneRenderer::SetFocusPoint(const glm::vec2& point)
|
||||||
|
{
|
||||||
|
s_Data.FocusPoint = point;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t SceneRenderer::GetFinalColorBufferRendererID()
|
uint32_t SceneRenderer::GetFinalColorBufferRendererID()
|
||||||
{
|
{
|
||||||
return s_Data.CompositePass->GetSpecification().TargetFramebuffer->GetColorAttachmentRendererID();
|
return s_Data.CompositePass->GetSpecification().TargetFramebuffer->GetColorAttachmentRendererID();
|
||||||
@ -247,16 +352,54 @@ namespace Prism
|
|||||||
return s_Data.Options;
|
return s_Data.Options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SceneRenderer::FlushDrawList()
|
void SceneRenderer::FlushDrawList()
|
||||||
{
|
{
|
||||||
PM_CORE_ASSERT(!s_Data.ActiveScene);
|
PM_CORE_ASSERT(!s_Data.ActiveScene);
|
||||||
|
|
||||||
|
memset(&s_Stats, 0, sizeof(SceneRendererStats));
|
||||||
|
|
||||||
|
{
|
||||||
|
Renderer::Submit([]()
|
||||||
|
{
|
||||||
|
s_Stats.ShadowPassTimer.Reset();
|
||||||
|
});
|
||||||
|
ShadowMapPass();
|
||||||
|
Renderer::Submit([]
|
||||||
|
{
|
||||||
|
s_Stats.ShadowPass = s_Stats.ShadowPassTimer.ElapsedMillis();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Renderer::Submit([]()
|
||||||
|
{
|
||||||
|
s_Stats.GeometryPassTimer.Reset();
|
||||||
|
});
|
||||||
GeometryPass();
|
GeometryPass();
|
||||||
|
Renderer::Submit([]
|
||||||
|
{
|
||||||
|
s_Stats.GeometryPass = s_Stats.GeometryPassTimer.ElapsedMillis();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Renderer::Submit([]()
|
||||||
|
{
|
||||||
|
s_Stats.CompositePassTimer.Reset();
|
||||||
|
});
|
||||||
|
|
||||||
CompositePass();
|
CompositePass();
|
||||||
|
Renderer::Submit([]
|
||||||
|
{
|
||||||
|
s_Stats.CompositePass = s_Stats.CompositePassTimer.ElapsedMillis();
|
||||||
|
});
|
||||||
|
|
||||||
|
// BloomBlurPass();
|
||||||
|
}
|
||||||
|
|
||||||
s_Data.DrawList.clear();
|
s_Data.DrawList.clear();
|
||||||
s_Data.SelectedMeshDrawList.clear();
|
s_Data.SelectedMeshDrawList.clear();
|
||||||
s_Data.ColliderDrawList.clear();
|
s_Data.ColliderDrawList.clear();
|
||||||
|
s_Data.ShadowPassDrawList.clear();
|
||||||
s_Data.SceneData = {};
|
s_Data.SceneData = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,21 +426,43 @@ namespace Prism
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto viewProjection = s_Data.SceneData.SceneCamera.Camera.GetProjectionMatrix() * s_Data.SceneData.SceneCamera.ViewMatrix;
|
const auto& sceneCamera = s_Data.SceneData.SceneCamera;
|
||||||
glm::vec3 cameraPosition = glm::inverse(s_Data.SceneData.SceneCamera.ViewMatrix)[3];
|
|
||||||
|
const auto viewProjection = sceneCamera.Camera.GetProjectionMatrix() * sceneCamera.ViewMatrix;
|
||||||
|
const glm::vec3 cameraPosition = glm::inverse(s_Data.SceneData.SceneCamera.ViewMatrix)[3]; // TODO: Negate instead
|
||||||
|
|
||||||
|
|
||||||
// Skybox
|
// Skybox
|
||||||
auto skyboxShader = s_Data.SceneData.SkyboxMaterial->GetShader();
|
auto skyboxShader = s_Data.SceneData.SkyboxMaterial->GetShader();
|
||||||
s_Data.SceneData.SkyboxMaterial->Set("u_InverseVP", glm::inverse(viewProjection));
|
s_Data.SceneData.SkyboxMaterial->Set("u_InverseVP", glm::inverse(viewProjection));
|
||||||
|
s_Data.SceneData.SkyboxMaterial->Set("u_SkyIntensity", s_Data.SceneData.SceneEnvironmentIntensity);
|
||||||
// s_Data.SceneInfo.EnvironmentIrradianceMap->Bind(0);
|
// s_Data.SceneInfo.EnvironmentIrradianceMap->Bind(0);
|
||||||
Renderer::SubmitFullscreenQuad(s_Data.SceneData.SkyboxMaterial);
|
Renderer::SubmitFullscreenQuad(s_Data.SceneData.SkyboxMaterial);
|
||||||
|
|
||||||
|
const float aspectRatio = (float)s_Data.GeoPass->GetSpecification().TargetFramebuffer->GetWidth() / (float)s_Data.GeoPass->GetSpecification().TargetFramebuffer->GetHeight();
|
||||||
|
float frustumSize = 2.0f * sceneCamera.Near * glm::tan(sceneCamera.FOV * 0.5f) * aspectRatio;
|
||||||
|
|
||||||
// Render entities
|
// Render entities
|
||||||
for (auto& dc : s_Data.DrawList)
|
for (auto& dc : s_Data.DrawList)
|
||||||
{
|
{
|
||||||
auto baseMaterial = dc.mesh->GetMaterial();
|
auto baseMaterial = dc.mesh->GetMaterial();
|
||||||
baseMaterial->Set("u_ViewProjectionMatrix", viewProjection);
|
baseMaterial->Set("u_ViewProjectionMatrix", viewProjection);
|
||||||
|
baseMaterial->Set("u_ViewMatrix", sceneCamera.ViewMatrix);
|
||||||
baseMaterial->Set("u_CameraPosition", cameraPosition);
|
baseMaterial->Set("u_CameraPosition", cameraPosition);
|
||||||
|
baseMaterial->Set("u_LightMatrixCascade0", s_Data.LightMatrices[0]);
|
||||||
|
baseMaterial->Set("u_LightMatrixCascade1", s_Data.LightMatrices[1]);
|
||||||
|
baseMaterial->Set("u_LightMatrixCascade2", s_Data.LightMatrices[2]);
|
||||||
|
baseMaterial->Set("u_LightMatrixCascade3", s_Data.LightMatrices[3]);
|
||||||
|
baseMaterial->Set("u_ShowCascades", s_Data.ShowCascades);
|
||||||
|
baseMaterial->Set("u_LightView", s_Data.LightViewMatrix);
|
||||||
|
baseMaterial->Set("u_CascadeSplits", s_Data.CascadeSplits);
|
||||||
|
baseMaterial->Set("u_SoftShadows", s_Data.SoftShadows);
|
||||||
|
baseMaterial->Set("u_LightSize", s_Data.LightSize);
|
||||||
|
baseMaterial->Set("u_MaxShadowDistance", s_Data.MaxShadowDistance);
|
||||||
|
baseMaterial->Set("u_ShadowFade", s_Data.ShadowFade);
|
||||||
|
baseMaterial->Set("u_CascadeFading", s_Data.CascadeFading);
|
||||||
|
baseMaterial->Set("u_CascadeTransitionFade", s_Data.CascadeTransitionFade);
|
||||||
|
baseMaterial->Set("u_IBLContribution", s_Data.SceneData.SceneEnvironmentIntensity);
|
||||||
|
|
||||||
// Environment (TODO: don't do this per mesh)
|
// Environment (TODO: don't do this per mesh)
|
||||||
baseMaterial->Set("u_EnvRadianceTex", s_Data.SceneData.SceneEnvironment.RadianceMap);
|
baseMaterial->Set("u_EnvRadianceTex", s_Data.SceneData.SceneEnvironment.RadianceMap);
|
||||||
@ -305,9 +470,106 @@ namespace Prism
|
|||||||
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)
|
// Set lights (TODO: move to light environment and don't do per mesh)
|
||||||
baseMaterial->Set("lights", s_Data.SceneData.ActiveLight);
|
auto directionalLight = s_Data.SceneData.SceneLightEnvironment.DirectionalLights[0];
|
||||||
|
baseMaterial->Set("u_DirectionalLights", directionalLight);
|
||||||
|
|
||||||
auto overrideMaterial = nullptr; // dc.Material;
|
auto rd = baseMaterial->FindResourceDeclaration("u_ShadowMapTexture");
|
||||||
|
if (rd)
|
||||||
|
{
|
||||||
|
auto reg = rd->GetRegister();
|
||||||
|
|
||||||
|
auto tex = s_Data.ShadowMapRenderPass[0]->GetSpecification().TargetFramebuffer->GetDepthAttachmentRendererID();
|
||||||
|
auto tex1 = s_Data.ShadowMapRenderPass[1]->GetSpecification().TargetFramebuffer->GetDepthAttachmentRendererID();
|
||||||
|
auto tex2 = s_Data.ShadowMapRenderPass[2]->GetSpecification().TargetFramebuffer->GetDepthAttachmentRendererID();
|
||||||
|
auto tex3 = s_Data.ShadowMapRenderPass[3]->GetSpecification().TargetFramebuffer->GetDepthAttachmentRendererID();
|
||||||
|
|
||||||
|
Renderer::Submit([reg, tex, tex1, tex2, tex3]() mutable
|
||||||
|
{
|
||||||
|
// 4 cascades
|
||||||
|
glBindTextureUnit(reg, tex);
|
||||||
|
glBindSampler(reg++, s_Data.ShadowMapSampler);
|
||||||
|
|
||||||
|
glBindTextureUnit(reg, tex1);
|
||||||
|
glBindSampler(reg++, s_Data.ShadowMapSampler);
|
||||||
|
|
||||||
|
glBindTextureUnit(reg, tex2);
|
||||||
|
glBindSampler(reg++, s_Data.ShadowMapSampler);
|
||||||
|
|
||||||
|
glBindTextureUnit(reg, tex3);
|
||||||
|
glBindSampler(reg++, s_Data.ShadowMapSampler);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
constexpr auto overrideMaterial = nullptr; // dc.Material;
|
||||||
|
Renderer::SubmitMesh(dc.mesh, dc.Transform, overrideMaterial);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outline)
|
||||||
|
{
|
||||||
|
Renderer::Submit([]()
|
||||||
|
{
|
||||||
|
glStencilFunc(GL_ALWAYS, 1, 0xff);
|
||||||
|
glStencilMask(0xff);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
for (auto& dc : s_Data.SelectedMeshDrawList)
|
||||||
|
{
|
||||||
|
auto baseMaterial = dc.mesh->GetMaterial();
|
||||||
|
baseMaterial->Set("u_ViewProjectionMatrix", viewProjection);
|
||||||
|
baseMaterial->Set("u_ViewMatrix", sceneCamera.ViewMatrix);
|
||||||
|
baseMaterial->Set("u_CameraPosition", cameraPosition);
|
||||||
|
baseMaterial->Set("u_CascadeSplits", s_Data.CascadeSplits);
|
||||||
|
baseMaterial->Set("u_ShowCascades", s_Data.ShowCascades);
|
||||||
|
baseMaterial->Set("u_SoftShadows", s_Data.SoftShadows);
|
||||||
|
baseMaterial->Set("u_LightSize", s_Data.LightSize);
|
||||||
|
baseMaterial->Set("u_MaxShadowDistance", s_Data.MaxShadowDistance);
|
||||||
|
baseMaterial->Set("u_ShadowFade", s_Data.ShadowFade);
|
||||||
|
baseMaterial->Set("u_CascadeFading", s_Data.CascadeFading);
|
||||||
|
baseMaterial->Set("u_CascadeTransitionFade", s_Data.CascadeTransitionFade);
|
||||||
|
baseMaterial->Set("u_IBLContribution", s_Data.SceneData.SceneEnvironmentIntensity);
|
||||||
|
|
||||||
|
// Environment (TODO: don't do this per mesh)
|
||||||
|
baseMaterial->Set("u_EnvRadianceTex", s_Data.SceneData.SceneEnvironment.RadianceMap);
|
||||||
|
baseMaterial->Set("u_EnvIrradianceTex", s_Data.SceneData.SceneEnvironment.IrradianceMap);
|
||||||
|
baseMaterial->Set("u_BRDFLUTTexture", s_Data.BRDFLUT);
|
||||||
|
|
||||||
|
baseMaterial->Set("u_LightMatrixCascade0", s_Data.LightMatrices[0]);
|
||||||
|
baseMaterial->Set("u_LightMatrixCascade1", s_Data.LightMatrices[1]);
|
||||||
|
baseMaterial->Set("u_LightMatrixCascade2", s_Data.LightMatrices[2]);
|
||||||
|
baseMaterial->Set("u_LightMatrixCascade3", s_Data.LightMatrices[3]);
|
||||||
|
|
||||||
|
// Set lights (TODO: move to light environment and don't do per mesh)
|
||||||
|
baseMaterial->Set("u_DirectionalLights", s_Data.SceneData.SceneLightEnvironment.DirectionalLights[0]);
|
||||||
|
|
||||||
|
auto rd = baseMaterial->FindResourceDeclaration("u_ShadowMapTexture");
|
||||||
|
if (rd)
|
||||||
|
{
|
||||||
|
auto reg = rd->GetRegister();
|
||||||
|
|
||||||
|
auto tex = s_Data.ShadowMapRenderPass[0]->GetSpecification().TargetFramebuffer->GetDepthAttachmentRendererID();
|
||||||
|
auto tex1 = s_Data.ShadowMapRenderPass[1]->GetSpecification().TargetFramebuffer->GetDepthAttachmentRendererID();
|
||||||
|
auto tex2 = s_Data.ShadowMapRenderPass[2]->GetSpecification().TargetFramebuffer->GetDepthAttachmentRendererID();
|
||||||
|
auto tex3 = s_Data.ShadowMapRenderPass[3]->GetSpecification().TargetFramebuffer->GetDepthAttachmentRendererID();
|
||||||
|
|
||||||
|
Renderer::Submit([reg, tex, tex1, tex2, tex3]() mutable
|
||||||
|
{
|
||||||
|
// 4 cascades
|
||||||
|
glBindTextureUnit(reg, tex);
|
||||||
|
glBindSampler(reg++, s_Data.ShadowMapSampler);
|
||||||
|
|
||||||
|
glBindTextureUnit(reg, tex1);
|
||||||
|
glBindSampler(reg++, s_Data.ShadowMapSampler);
|
||||||
|
|
||||||
|
glBindTextureUnit(reg, tex2);
|
||||||
|
glBindSampler(reg++, s_Data.ShadowMapSampler);
|
||||||
|
|
||||||
|
glBindTextureUnit(reg, tex3);
|
||||||
|
glBindSampler(reg++, s_Data.ShadowMapSampler);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr auto overrideMaterial = nullptr; // dc.Material;
|
||||||
Renderer::SubmitMesh(dc.mesh, dc.Transform, overrideMaterial);
|
Renderer::SubmitMesh(dc.mesh, dc.Transform, overrideMaterial);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,9 +589,11 @@ namespace Prism
|
|||||||
|
|
||||||
// Draw outline here
|
// Draw outline here
|
||||||
s_Data.OutlineMaterial->Set("u_ViewProjection", viewProjection);
|
s_Data.OutlineMaterial->Set("u_ViewProjection", viewProjection);
|
||||||
|
s_Data.OutlineAnimMaterial->Set("u_ViewProjection", viewProjection);
|
||||||
for (auto& dc : s_Data.SelectedMeshDrawList)
|
for (auto& dc : s_Data.SelectedMeshDrawList)
|
||||||
{
|
{
|
||||||
Renderer::SubmitMesh(dc.mesh, dc.Transform, s_Data.OutlineMaterial);
|
// Renderer::SubmitMesh(dc.mesh, dc.Transform, s_Data.OutlineMaterial);
|
||||||
|
Renderer::SubmitMesh(dc.mesh, dc.Transform, dc.mesh->IsAnimated() ? s_Data.OutlineAnimMaterial : s_Data.OutlineMaterial);
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer::Submit([]()
|
Renderer::Submit([]()
|
||||||
@ -339,7 +603,8 @@ namespace Prism
|
|||||||
});
|
});
|
||||||
for (auto& dc : s_Data.SelectedMeshDrawList)
|
for (auto& dc : s_Data.SelectedMeshDrawList)
|
||||||
{
|
{
|
||||||
Renderer::SubmitMesh(dc.mesh, dc.Transform, s_Data.OutlineMaterial);
|
// Renderer::SubmitMesh(dc.mesh, dc.Transform, s_Data.OutlineMaterial);
|
||||||
|
Renderer::SubmitMesh(dc.mesh, dc.Transform, dc.mesh->IsAnimated() ? s_Data.OutlineAnimMaterial : s_Data.OutlineMaterial);
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer::Submit([]()
|
Renderer::Submit([]()
|
||||||
@ -414,12 +679,303 @@ namespace Prism
|
|||||||
|
|
||||||
void SceneRenderer::CompositePass()
|
void SceneRenderer::CompositePass()
|
||||||
{
|
{
|
||||||
|
auto& compositeBuffer = s_Data.CompositePass->GetSpecification().TargetFramebuffer;
|
||||||
|
|
||||||
Renderer::BeginRenderPass(s_Data.CompositePass);
|
Renderer::BeginRenderPass(s_Data.CompositePass);
|
||||||
s_Data.CompositeShader->Bind();
|
s_Data.CompositeShader->Bind();
|
||||||
s_Data.CompositeShader->SetFloat("u_Exposure", s_Data.SceneData.SceneCamera.Camera.GetExposure());
|
s_Data.CompositeShader->SetFloat("u_Exposure", s_Data.SceneData.SceneCamera.Camera.GetExposure());
|
||||||
s_Data.CompositeShader->SetInt("u_TextureSamples", s_Data.GeoPass->GetSpecification().TargetFramebuffer->GetSpecification().Samples);
|
s_Data.CompositeShader->SetInt("u_TextureSamples", s_Data.GeoPass->GetSpecification().TargetFramebuffer->GetSpecification().Samples);
|
||||||
|
// s_Data.CompositeShader->SetFloat2("u_ViewportSize", glm::vec2(compositeBuffer->GetWidth(), compositeBuffer->GetHeight()));
|
||||||
|
// s_Data.CompositeShader->SetFloat2("u_FocusPoint", s_Data.FocusPoint);
|
||||||
|
s_Data.CompositeShader->SetInt("u_TextureSamples", s_Data.GeoPass->GetSpecification().TargetFramebuffer->GetSpecification().Samples);
|
||||||
|
// s_Data.CompositeShader->SetFloat("u_BloomThreshold", s_Data.BloomThreshold);
|
||||||
|
|
||||||
s_Data.GeoPass->GetSpecification().TargetFramebuffer->BindTexture();
|
s_Data.GeoPass->GetSpecification().TargetFramebuffer->BindTexture();
|
||||||
|
Renderer::Submit([]()
|
||||||
|
{
|
||||||
|
glBindTextureUnit(1, s_Data.GeoPass->GetSpecification().TargetFramebuffer->GetDepthAttachmentRendererID());
|
||||||
|
});
|
||||||
|
|
||||||
|
Renderer::SubmitFullscreenQuad(nullptr);
|
||||||
|
Renderer::EndRenderPass();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneRenderer::BloomBlurPass()
|
||||||
|
{
|
||||||
|
int amount = 10;
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
int horizontalCounter = 0, verticalCounter = 0;
|
||||||
|
for (int i = 0; i < amount; i++)
|
||||||
|
{
|
||||||
|
index = i % 2;
|
||||||
|
Renderer::BeginRenderPass(s_Data.BloomBlurPass[index]);
|
||||||
|
s_Data.BloomBlurShader->Bind();
|
||||||
|
s_Data.BloomBlurShader->SetBool("u_Horizontal", index);
|
||||||
|
if (index)
|
||||||
|
horizontalCounter++;
|
||||||
|
else
|
||||||
|
verticalCounter++;
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
auto fb = s_Data.BloomBlurPass[1 - index]->GetSpecification().TargetFramebuffer;
|
||||||
|
fb->BindTexture();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto fb = s_Data.CompositePass->GetSpecification().TargetFramebuffer;
|
||||||
|
auto id = fb->GetColorAttachmentRendererID(1);
|
||||||
|
Renderer::Submit([id]()
|
||||||
|
{
|
||||||
|
glBindTextureUnit(0, id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Renderer::SubmitFullscreenQuad(nullptr);
|
||||||
|
Renderer::EndRenderPass();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Composite bloom
|
||||||
|
{
|
||||||
|
Renderer::BeginRenderPass(s_Data.BloomBlendPass);
|
||||||
|
s_Data.BloomBlendShader->Bind();
|
||||||
|
s_Data.BloomBlendShader->SetFloat("u_Exposure", s_Data.SceneData.SceneCamera.Camera.GetExposure());
|
||||||
|
s_Data.BloomBlendShader->SetBool("u_EnableBloom", s_Data.EnableBloom);
|
||||||
|
|
||||||
|
s_Data.CompositePass->GetSpecification().TargetFramebuffer->BindTexture(0);
|
||||||
|
s_Data.BloomBlurPass[index]->GetSpecification().TargetFramebuffer->BindTexture(1);
|
||||||
|
|
||||||
Renderer::SubmitFullscreenQuad(nullptr);
|
Renderer::SubmitFullscreenQuad(nullptr);
|
||||||
Renderer::EndRenderPass();
|
Renderer::EndRenderPass();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct FrustumBounds
|
||||||
|
{
|
||||||
|
float r, l, b, t, f, n;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CascadeData
|
||||||
|
{
|
||||||
|
glm::mat4 ViewProj;
|
||||||
|
glm::mat4 View;
|
||||||
|
float SplitDepth;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void CalculateCascades(CascadeData* cascades, const glm::vec3& lightDirection)
|
||||||
|
{
|
||||||
|
// FrustumBounds frustumBounds[3];
|
||||||
|
|
||||||
|
auto& sceneCamera = s_Data.SceneData.SceneCamera;
|
||||||
|
auto viewProjection = sceneCamera.Camera.GetProjectionMatrix() * sceneCamera.ViewMatrix;
|
||||||
|
|
||||||
|
constexpr int SHADOW_MAP_CASCADE_COUNT = 4;
|
||||||
|
float cascadeSplits[SHADOW_MAP_CASCADE_COUNT];
|
||||||
|
|
||||||
|
// TODO: less hard-coding!
|
||||||
|
float nearClip = 0.1f;
|
||||||
|
float farClip = 1000.0f;
|
||||||
|
float clipRange = farClip - nearClip;
|
||||||
|
|
||||||
|
float minZ = nearClip;
|
||||||
|
float maxZ = nearClip + clipRange;
|
||||||
|
|
||||||
|
float range = maxZ - minZ;
|
||||||
|
float ratio = maxZ / minZ;
|
||||||
|
|
||||||
|
// Calculate split depths based on view camera frustum
|
||||||
|
// Based on method presented in https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch10.html
|
||||||
|
for (uint32_t i = 0; i < SHADOW_MAP_CASCADE_COUNT; i++)
|
||||||
|
{
|
||||||
|
float p = (i + 1) / static_cast<float>(SHADOW_MAP_CASCADE_COUNT);
|
||||||
|
float log = minZ * std::pow(ratio, p);
|
||||||
|
float uniform = minZ + range * p;
|
||||||
|
float d = s_Data.CascadeSplitLambda * (log - uniform) + uniform;
|
||||||
|
cascadeSplits[i] = (d - nearClip) / clipRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
cascadeSplits[3] = 0.3f;
|
||||||
|
|
||||||
|
// Manually set cascades here
|
||||||
|
// cascadeSplits[0] = 0.05f;
|
||||||
|
// cascadeSplits[1] = 0.15f;
|
||||||
|
// cascadeSplits[2] = 0.3f;
|
||||||
|
// cascadeSplits[3] = 1.0f;
|
||||||
|
|
||||||
|
// Calculate orthographic projection matrix for each cascade
|
||||||
|
float lastSplitDist = 0.0;
|
||||||
|
for (uint32_t i = 0; i < SHADOW_MAP_CASCADE_COUNT; i++)
|
||||||
|
{
|
||||||
|
float splitDist = cascadeSplits[i];
|
||||||
|
|
||||||
|
glm::vec3 frustumCorners[8] =
|
||||||
|
{
|
||||||
|
glm::vec3(-1.0f, 1.0f, -1.0f),
|
||||||
|
glm::vec3( 1.0f, 1.0f, -1.0f),
|
||||||
|
glm::vec3( 1.0f, -1.0f, -1.0f),
|
||||||
|
glm::vec3(-1.0f, -1.0f, -1.0f),
|
||||||
|
glm::vec3(-1.0f, 1.0f, 1.0f),
|
||||||
|
glm::vec3( 1.0f, 1.0f, 1.0f),
|
||||||
|
glm::vec3( 1.0f, -1.0f, 1.0f),
|
||||||
|
glm::vec3(-1.0f, -1.0f, 1.0f),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Project frustum corners into world space
|
||||||
|
glm::mat4 invCam = glm::inverse(viewProjection);
|
||||||
|
for (uint32_t i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
glm::vec4 invCorner = invCam * glm::vec4(frustumCorners[i], 1.0f);
|
||||||
|
frustumCorners[i] = invCorner / invCorner.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
glm::vec3 dist = frustumCorners[i + 4] - frustumCorners[i];
|
||||||
|
frustumCorners[i + 4] = frustumCorners[i] + (dist * splitDist);
|
||||||
|
frustumCorners[i] = frustumCorners[i] + (dist * lastSplitDist);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get frustum center
|
||||||
|
glm::vec3 frustumCenter = glm::vec3(0.0f);
|
||||||
|
for (uint32_t i = 0; i < 8; i++)
|
||||||
|
frustumCenter += frustumCorners[i];
|
||||||
|
|
||||||
|
frustumCenter /= 8.0f;
|
||||||
|
|
||||||
|
//frustumCenter *= 0.01f;
|
||||||
|
|
||||||
|
float radius = 0.0f;
|
||||||
|
for (uint32_t i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
float distance = glm::length(frustumCorners[i] - frustumCenter);
|
||||||
|
radius = glm::max(radius, distance);
|
||||||
|
}
|
||||||
|
radius = std::ceil(radius * 16.0f) / 16.0f;
|
||||||
|
|
||||||
|
glm::vec3 maxExtents = glm::vec3(radius);
|
||||||
|
glm::vec3 minExtents = -maxExtents;
|
||||||
|
|
||||||
|
glm::vec3 lightDir = -lightDirection;
|
||||||
|
glm::mat4 lightViewMatrix = glm::lookAt(frustumCenter - lightDir * -minExtents.z, frustumCenter, glm::vec3(0.0f, 0.0f, 1.0f));
|
||||||
|
glm::mat4 lightOrthoMatrix = glm::ortho(minExtents.x, maxExtents.x, minExtents.y, maxExtents.y, 0.0f + s_Data.CascadeNearPlaneOffset, maxExtents.z - minExtents.z + s_Data.CascadeFarPlaneOffset);
|
||||||
|
|
||||||
|
// Store split distance and matrix in cascade
|
||||||
|
cascades[i].SplitDepth = (nearClip + splitDist * clipRange) * -1.0f;
|
||||||
|
cascades[i].ViewProj = lightOrthoMatrix * lightViewMatrix;
|
||||||
|
cascades[i].View = lightViewMatrix;
|
||||||
|
|
||||||
|
lastSplitDist = cascadeSplits[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneRenderer::ShadowMapPass()
|
||||||
|
{
|
||||||
|
const auto& directionalLights = s_Data.SceneData.SceneLightEnvironment.DirectionalLights;
|
||||||
|
if (directionalLights[0].Multiplier == 0.0f || !directionalLights[0].CastShadows)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
// Clear shadow maps
|
||||||
|
Renderer::BeginRenderPass(s_Data.ShadowMapRenderPass[i]);
|
||||||
|
Renderer::EndRenderPass();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CascadeData cascades[4];
|
||||||
|
CalculateCascades(cascades, directionalLights[0].Direction);
|
||||||
|
s_Data.LightViewMatrix = cascades[0].View;
|
||||||
|
|
||||||
|
Renderer::Submit([]()
|
||||||
|
{
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
glCullFace(GL_BACK);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
s_Data.CascadeSplits[i] = cascades[i].SplitDepth;
|
||||||
|
|
||||||
|
Renderer::BeginRenderPass(s_Data.ShadowMapRenderPass[i]);
|
||||||
|
|
||||||
|
glm::mat4 shadowMapVP = cascades[i].ViewProj;
|
||||||
|
// s_Data.ShadowMapShader->SetMat4("u_ViewProjection", shadowMapVP);
|
||||||
|
|
||||||
|
static glm::mat4 scaleBiasMatrix = glm::scale(glm::mat4(1.0f), { 0.5f, 0.5f, 0.5f }) * glm::translate(glm::mat4(1.0f), { 1, 1, 1 });
|
||||||
|
s_Data.LightMatrices[i] = scaleBiasMatrix * cascades[i].ViewProj;
|
||||||
|
|
||||||
|
|
||||||
|
// Render entities
|
||||||
|
for (auto& dc : s_Data.ShadowPassDrawList)
|
||||||
|
{
|
||||||
|
Ref<Shader> shader = dc.mesh->IsAnimated() ? s_Data.ShadowMapAnimShader : s_Data.ShadowMapShader;
|
||||||
|
shader->SetMat4("u_ViewProjection", shadowMapVP);
|
||||||
|
Renderer::SubmitMeshWithShader(dc.mesh, dc.Transform, shader);
|
||||||
|
// Renderer::SubmitMeshWithShader(dc.mesh, dc.Transform, s_Data.ShadowMapShader);
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderer::EndRenderPass();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneRenderer::OnImGuiRender()
|
||||||
|
{
|
||||||
|
ImGui::Begin("Scene Renderer");
|
||||||
|
|
||||||
|
if (UI::BeginTreeNode("Shadows"))
|
||||||
|
{
|
||||||
|
UI::BeginPropertyGrid();
|
||||||
|
UI::Property("Soft Shadows", s_Data.SoftShadows);
|
||||||
|
UI::Property("Light Size", s_Data.LightSize, 0.01f);
|
||||||
|
UI::Property("Max Shadow Distance", s_Data.MaxShadowDistance, 1.0f);
|
||||||
|
UI::Property("Shadow Fade", s_Data.ShadowFade, 5.0f);
|
||||||
|
UI::EndPropertyGrid();
|
||||||
|
if (UI::BeginTreeNode("Cascade Settings"))
|
||||||
|
{
|
||||||
|
UI::BeginPropertyGrid();
|
||||||
|
UI::Property("Show Cascades", s_Data.ShowCascades);
|
||||||
|
UI::Property("Cascade Fading", s_Data.CascadeFading);
|
||||||
|
UI::Property("Cascade Transition Fade", s_Data.CascadeTransitionFade, 0.05f, 0.0f, FLT_MAX);
|
||||||
|
UI::Property("Cascade Split", s_Data.CascadeSplitLambda, 0.01f);
|
||||||
|
UI::Property("CascadeNearPlaneOffset", s_Data.CascadeNearPlaneOffset, 0.1f, -FLT_MAX, 0.0f);
|
||||||
|
UI::Property("CascadeFarPlaneOffset", s_Data.CascadeFarPlaneOffset, 0.1f, 0.0f, FLT_MAX);
|
||||||
|
UI::EndPropertyGrid();
|
||||||
|
UI::EndTreeNode();
|
||||||
|
}
|
||||||
|
if (UI::BeginTreeNode("Shadow Map", false))
|
||||||
|
{
|
||||||
|
static int cascadeIndex = 0;
|
||||||
|
auto fb = s_Data.ShadowMapRenderPass[cascadeIndex]->GetSpecification().TargetFramebuffer;
|
||||||
|
auto id = fb->GetDepthAttachmentRendererID();
|
||||||
|
|
||||||
|
float size = ImGui::GetContentRegionAvail().x; // (float)fb->GetWidth() * 0.5f, (float)fb->GetHeight() * 0.5f
|
||||||
|
UI::BeginPropertyGrid();
|
||||||
|
UI::PropertySlider("Cascade Index", cascadeIndex, 0, 3);
|
||||||
|
UI::EndPropertyGrid();
|
||||||
|
ImGui::Image((ImTextureID)id, { size, size }, { 0, 1 }, { 1, 0 });
|
||||||
|
UI::EndTreeNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
UI::EndTreeNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UI::BeginTreeNode("Bloom"))
|
||||||
|
{
|
||||||
|
UI::BeginPropertyGrid();
|
||||||
|
UI::Property("Bloom", s_Data.EnableBloom);
|
||||||
|
UI::Property("Bloom threshold", s_Data.BloomThreshold, 0.05f);
|
||||||
|
UI::EndPropertyGrid();
|
||||||
|
|
||||||
|
auto fb = s_Data.BloomBlurPass[0]->GetSpecification().TargetFramebuffer;
|
||||||
|
auto id = fb->GetColorAttachmentRendererID();
|
||||||
|
|
||||||
|
float size = ImGui::GetContentRegionAvail().x; // (float)fb->GetWidth() * 0.5f, (float)fb->GetHeight() * 0.5f
|
||||||
|
float w = size;
|
||||||
|
float h = w / ((float)fb->GetWidth() / (float)fb->GetHeight());
|
||||||
|
ImGui::Image((ImTextureID)id, { w, h }, { 0, 1 }, { 1, 0 });
|
||||||
|
UI::EndTreeNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -23,6 +23,9 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
Prism::Camera Camera;
|
Prism::Camera Camera;
|
||||||
glm::mat4 ViewMatrix;
|
glm::mat4 ViewMatrix;
|
||||||
|
|
||||||
|
float Near, Far;
|
||||||
|
float FOV;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PRISM_API SceneRenderer
|
class PRISM_API SceneRenderer
|
||||||
@ -48,15 +51,21 @@ namespace Prism
|
|||||||
static Ref<RenderPass> GetFinalRenderPass();
|
static Ref<RenderPass> GetFinalRenderPass();
|
||||||
static Ref<Texture2D> GetFinalColorBuffer();
|
static Ref<Texture2D> GetFinalColorBuffer();
|
||||||
|
|
||||||
|
static void SetFocusPoint(const glm::vec2& point);
|
||||||
|
|
||||||
// TODO: Temp
|
// TODO: Temp
|
||||||
static uint32_t GetFinalColorBufferRendererID();
|
static uint32_t GetFinalColorBufferRendererID();
|
||||||
|
|
||||||
static SceneRendererOptions& GetOptions();
|
static SceneRendererOptions& GetOptions();
|
||||||
|
|
||||||
|
static void OnImGuiRender();
|
||||||
private:
|
private:
|
||||||
static void FlushDrawList();
|
static void FlushDrawList();
|
||||||
static void GeometryPass();
|
static void GeometryPass();
|
||||||
static void CompositePass();
|
static void CompositePass();
|
||||||
|
static void BloomBlurPass();
|
||||||
|
|
||||||
|
static void ShadowMapPass();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -110,9 +110,11 @@ namespace Prism
|
|||||||
virtual void Bind() = 0;
|
virtual void Bind() = 0;
|
||||||
virtual void UploadUniformBuffer(const UniformBufferBase& uniformBuffer) = 0;
|
virtual void UploadUniformBuffer(const UniformBufferBase& uniformBuffer) = 0;
|
||||||
|
|
||||||
virtual void SetFloat(const std::string& name, float value) = 0;
|
|
||||||
virtual void SetFloat3(const std::string& name, const glm::vec3& value) = 0;
|
|
||||||
virtual void SetInt(const std::string& name, int value) = 0;
|
virtual void SetInt(const std::string& name, int value) = 0;
|
||||||
|
virtual void SetBool(const std::string& name, bool value) = 0;
|
||||||
|
virtual void SetFloat(const std::string& name, float value) = 0;
|
||||||
|
virtual void SetFloat2(const std::string& name, const glm::vec2& value) = 0;
|
||||||
|
virtual void SetFloat3(const std::string& name, const glm::vec3& value) = 0;
|
||||||
virtual void SetMat4(const std::string& name, const glm::mat4& value) = 0;
|
virtual void SetMat4(const std::string& name, const glm::mat4& value) = 0;
|
||||||
virtual void SetMat4FromRenderThread(const std::string& name, const glm::mat4& value, bool bind = true) = 0;
|
virtual void SetMat4FromRenderThread(const std::string& name, const glm::mat4& value, bool bind = true) = 0;
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,8 @@
|
|||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
#include <glm/gtx/quaternion.hpp>
|
#include <glm/gtx/quaternion.hpp>
|
||||||
|
|
||||||
|
#include "Prism/Renderer/SceneEnvironment.h"
|
||||||
|
|
||||||
namespace Prism
|
namespace Prism
|
||||||
{
|
{
|
||||||
struct IDComponent
|
struct IDComponent
|
||||||
@ -222,7 +224,9 @@ namespace Prism
|
|||||||
struct MeshColliderComponent
|
struct MeshColliderComponent
|
||||||
{
|
{
|
||||||
Ref<Prism::Mesh> CollisionMesh;
|
Ref<Prism::Mesh> CollisionMesh;
|
||||||
Ref<Prism::Mesh> ProcessedMesh;
|
std::vector<Ref<Prism::Mesh>> ProcessedMeshes;
|
||||||
|
bool IsConvex = false;
|
||||||
|
|
||||||
bool IsTrigger = false;
|
bool IsTrigger = false;
|
||||||
|
|
||||||
MeshColliderComponent() = default;
|
MeshColliderComponent() = default;
|
||||||
@ -235,6 +239,29 @@ namespace Prism
|
|||||||
operator Ref<Prism::Mesh>() { return CollisionMesh; }
|
operator Ref<Prism::Mesh>() { return CollisionMesh; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Lights
|
||||||
|
|
||||||
|
// TODO: Move to renderer
|
||||||
|
enum class LightType
|
||||||
|
{
|
||||||
|
None = 0, Directional = 1, Point = 2, Spot = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DirectionalLightComponent
|
||||||
|
{
|
||||||
|
glm::vec3 Radiance = { 1.0f, 1.0f, 1.0f };
|
||||||
|
float Intensity = 1.0f;
|
||||||
|
bool CastShadows = true;
|
||||||
|
bool SoftShadows = true;
|
||||||
|
float LightSize = 0.5f; // For PCSS
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SkyLightComponent
|
||||||
|
{
|
||||||
|
Environment SceneEnvironment;
|
||||||
|
float Intensity = 1.0f;
|
||||||
|
float Angle = 0.0f;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,8 @@
|
|||||||
#define PX_PHYSX_STATIC_LIB
|
#define PX_PHYSX_STATIC_LIB
|
||||||
#include <PxPhysicsAPI.h>
|
#include <PxPhysicsAPI.h>
|
||||||
|
|
||||||
|
#include "Prism/Core/Input.h"
|
||||||
|
|
||||||
namespace Prism
|
namespace Prism
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -106,11 +108,6 @@ namespace Prism
|
|||||||
ScriptEngine::OnScriptComponentDestroyed(sceneID, entityID);
|
ScriptEngine::OnScriptComponentDestroyed(sceneID, entityID);
|
||||||
}
|
}
|
||||||
|
|
||||||
Environment Environment::Load(const std::string& filepath)
|
|
||||||
{
|
|
||||||
auto [radiance, irradiance] = SceneRenderer::CreateEnvironmentMap(filepath);
|
|
||||||
return { filepath, radiance, irradiance };
|
|
||||||
}
|
|
||||||
|
|
||||||
Scene::Scene(const std::string& debugName, const bool isEditorScene)
|
Scene::Scene(const std::string& debugName, const bool isEditorScene)
|
||||||
: m_SceneID(++s_SceneIDCounter), m_DebugName(debugName)
|
: m_SceneID(++s_SceneIDCounter), m_DebugName(debugName)
|
||||||
@ -160,16 +157,6 @@ namespace Prism
|
|||||||
|
|
||||||
void Scene::OnUpdate(TimeStep ts)
|
void Scene::OnUpdate(TimeStep ts)
|
||||||
{
|
{
|
||||||
// Update all entities
|
|
||||||
{
|
|
||||||
const auto view = m_Registry.view<ScriptComponent>();
|
|
||||||
for (const auto entity : view)
|
|
||||||
{
|
|
||||||
Entity e = { entity, this };
|
|
||||||
if (ScriptEngine::ModuleExists(e.GetComponent<ScriptComponent>().ModuleName))
|
|
||||||
ScriptEngine::OnUpdateEntity(e, ts);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Box2D physics
|
// Box2D physics
|
||||||
|
|
||||||
@ -202,6 +189,17 @@ namespace Prism
|
|||||||
}
|
}
|
||||||
|
|
||||||
Physics3D::Simulate(ts);
|
Physics3D::Simulate(ts);
|
||||||
|
|
||||||
|
// Update all entities
|
||||||
|
{
|
||||||
|
const auto view = m_Registry.view<ScriptComponent>();
|
||||||
|
for (const auto entity : view)
|
||||||
|
{
|
||||||
|
Entity e = { entity, this };
|
||||||
|
if (ScriptEngine::ModuleExists(e.GetComponent<ScriptComponent>().ModuleName))
|
||||||
|
ScriptEngine::OnUpdateEntity(e, ts);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::OnRenderRuntime(TimeStep ts)
|
void Scene::OnRenderRuntime(TimeStep ts)
|
||||||
@ -218,6 +216,39 @@ namespace Prism
|
|||||||
SceneCamera& camera = cameraEntity.GetComponent<CameraComponent>();
|
SceneCamera& camera = cameraEntity.GetComponent<CameraComponent>();
|
||||||
camera.SetViewportSize(m_ViewportWidth, m_ViewportHeight);
|
camera.SetViewportSize(m_ViewportWidth, m_ViewportHeight);
|
||||||
|
|
||||||
|
// Process lights
|
||||||
|
{
|
||||||
|
m_LightEnvironment = LightEnvironment();
|
||||||
|
auto lights = m_Registry.group<DirectionalLightComponent>(entt::get<TransformComponent>);
|
||||||
|
uint32_t directionalLightIndex = 0;
|
||||||
|
for (auto entity : lights)
|
||||||
|
{
|
||||||
|
auto [transformComponent, lightComponent] = lights.get<TransformComponent, DirectionalLightComponent>(entity);
|
||||||
|
glm::vec3 direction = -glm::normalize(glm::mat3(transformComponent.GetTransform()) * glm::vec3(1.0f));
|
||||||
|
m_LightEnvironment.DirectionalLights[directionalLightIndex++] =
|
||||||
|
{
|
||||||
|
direction,
|
||||||
|
lightComponent.Radiance,
|
||||||
|
lightComponent.Intensity,
|
||||||
|
lightComponent.CastShadows
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: only one sky light at the moment!
|
||||||
|
{
|
||||||
|
m_Environment = Environment();
|
||||||
|
auto lights = m_Registry.group<SkyLightComponent>(entt::get<TransformComponent>);
|
||||||
|
for (auto entity : lights)
|
||||||
|
{
|
||||||
|
auto [transformComponent, skyLightComponent] = lights.get<TransformComponent, SkyLightComponent>(entity);
|
||||||
|
m_Environment = skyLightComponent.SceneEnvironment;
|
||||||
|
m_EnvironmentIntensity = skyLightComponent.Intensity;
|
||||||
|
SetSkybox(m_Environment.RadianceMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
m_SkyboxMaterial->Set("u_TextureLod", m_SkyboxLod);
|
m_SkyboxMaterial->Set("u_TextureLod", m_SkyboxLod);
|
||||||
|
|
||||||
auto group = m_Registry.group<MeshComponent>(entt::get<TransformComponent>);
|
auto group = m_Registry.group<MeshComponent>(entt::get<TransformComponent>);
|
||||||
@ -236,6 +267,7 @@ namespace Prism
|
|||||||
SceneRenderer::EndScene();
|
SceneRenderer::EndScene();
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// Render all sprites
|
// Render all sprites
|
||||||
Renderer2D::BeginScene(*camera);
|
Renderer2D::BeginScene(*camera);
|
||||||
@ -260,10 +292,44 @@ namespace Prism
|
|||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
// RENDER 3D SCENE //
|
// RENDER 3D SCENE //
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Process lights
|
||||||
|
{
|
||||||
|
m_LightEnvironment = LightEnvironment();
|
||||||
|
auto lights = m_Registry.group<DirectionalLightComponent>(entt::get<TransformComponent>);
|
||||||
|
uint32_t directionalLightIndex = 0;
|
||||||
|
for (auto entity : lights)
|
||||||
|
{
|
||||||
|
auto [transformComponent, lightComponent] = lights.get<TransformComponent, DirectionalLightComponent>(entity);
|
||||||
|
glm::vec3 direction = -glm::normalize(glm::mat3(transformComponent.GetTransform()) * glm::vec3(1.0f));
|
||||||
|
m_LightEnvironment.DirectionalLights[directionalLightIndex++] =
|
||||||
|
{
|
||||||
|
direction,
|
||||||
|
lightComponent.Radiance,
|
||||||
|
lightComponent.Intensity,
|
||||||
|
lightComponent.CastShadows
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: only one sky light at the moment!
|
||||||
|
{
|
||||||
|
m_Environment = Environment();
|
||||||
|
auto lights = m_Registry.group<SkyLightComponent>(entt::get<TransformComponent>);
|
||||||
|
for (auto entity : lights)
|
||||||
|
{
|
||||||
|
auto [transformComponent, skyLightComponent] = lights.get<TransformComponent, SkyLightComponent>(entity);
|
||||||
|
m_Environment = skyLightComponent.SceneEnvironment;
|
||||||
|
m_EnvironmentIntensity = skyLightComponent.Intensity;
|
||||||
|
SetSkybox(m_Environment.RadianceMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_SkyboxMaterial->Set("u_TextureLod", m_SkyboxLod);
|
m_SkyboxMaterial->Set("u_TextureLod", m_SkyboxLod);
|
||||||
|
|
||||||
auto group = m_Registry.group<MeshComponent>(entt::get<TransformComponent>);
|
auto group = m_Registry.group<MeshComponent>(entt::get<TransformComponent>);
|
||||||
SceneRenderer::BeginScene(this, { static_cast<Camera>(editorCamera), editorCamera.GetViewMatrix() });
|
// SceneRenderer::BeginScene(this, { static_cast<Camera>(editorCamera), editorCamera.GetViewMatrix() });
|
||||||
|
SceneRenderer::BeginScene(this, { static_cast<Camera>(editorCamera), editorCamera.GetViewMatrix(), 0.1f, 1000.0f, 45.0f }); // TODO: real values
|
||||||
for (auto entity : group)
|
for (auto entity : group)
|
||||||
{
|
{
|
||||||
const auto& [transformComponent, meshComponent] = group.get<TransformComponent, MeshComponent>(entity);
|
const auto& [transformComponent, meshComponent] = group.get<TransformComponent, MeshComponent>(entity);
|
||||||
@ -474,6 +540,8 @@ namespace Prism
|
|||||||
|
|
||||||
void Scene::OnRuntimeStop()
|
void Scene::OnRuntimeStop()
|
||||||
{
|
{
|
||||||
|
Input::SetCursorMode(CursorMode::Normal);
|
||||||
|
|
||||||
Physics3D::DestroyScene();
|
Physics3D::DestroyScene();
|
||||||
|
|
||||||
delete[] m_Physics3DBodyEntityBuffer;
|
delete[] m_Physics3DBodyEntityBuffer;
|
||||||
@ -487,12 +555,6 @@ namespace Prism
|
|||||||
m_ViewportHeight = height;
|
m_ViewportHeight = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::SetEnvironment(const Environment& environment)
|
|
||||||
{
|
|
||||||
m_Environment = environment;
|
|
||||||
SetSkybox(environment.RadianceMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scene::SetSkybox(const Ref<TextureCube>& skybox)
|
void Scene::SetSkybox(const Ref<TextureCube>& skybox)
|
||||||
{
|
{
|
||||||
m_SkyboxTexture = skybox;
|
m_SkyboxTexture = skybox;
|
||||||
@ -580,6 +642,8 @@ namespace Prism
|
|||||||
|
|
||||||
CopyComponentIfExists<TransformComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
CopyComponentIfExists<TransformComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||||
CopyComponentIfExists<MeshComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
CopyComponentIfExists<MeshComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||||
|
CopyComponentIfExists<DirectionalLightComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||||
|
CopyComponentIfExists<SkyLightComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||||
CopyComponentIfExists<ScriptComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
CopyComponentIfExists<ScriptComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||||
CopyComponentIfExists<CameraComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
CopyComponentIfExists<CameraComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||||
CopyComponentIfExists<SpriteRendererComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
CopyComponentIfExists<SpriteRendererComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||||
@ -629,6 +693,8 @@ namespace Prism
|
|||||||
CopyComponent<TagComponent>(target->m_Registry, m_Registry, enttMap);
|
CopyComponent<TagComponent>(target->m_Registry, m_Registry, enttMap);
|
||||||
CopyComponent<TransformComponent>(target->m_Registry, m_Registry, enttMap);
|
CopyComponent<TransformComponent>(target->m_Registry, m_Registry, enttMap);
|
||||||
CopyComponent<MeshComponent>(target->m_Registry, m_Registry, enttMap);
|
CopyComponent<MeshComponent>(target->m_Registry, m_Registry, enttMap);
|
||||||
|
CopyComponent<DirectionalLightComponent>(target->m_Registry, m_Registry, enttMap);
|
||||||
|
CopyComponent<SkyLightComponent>(target->m_Registry, m_Registry, enttMap);
|
||||||
CopyComponent<ScriptComponent>(target->m_Registry, m_Registry, enttMap);
|
CopyComponent<ScriptComponent>(target->m_Registry, m_Registry, enttMap);
|
||||||
CopyComponent<CameraComponent>(target->m_Registry, m_Registry, enttMap);
|
CopyComponent<CameraComponent>(target->m_Registry, m_Registry, enttMap);
|
||||||
CopyComponent<SpriteRendererComponent>(target->m_Registry, m_Registry, enttMap);
|
CopyComponent<SpriteRendererComponent>(target->m_Registry, m_Registry, enttMap);
|
||||||
|
|||||||
@ -13,19 +13,11 @@
|
|||||||
|
|
||||||
#include "Prism/Core/UUID.h"
|
#include "Prism/Core/UUID.h"
|
||||||
#include "Prism/Editor/EditorCamera.h"
|
#include "Prism/Editor/EditorCamera.h"
|
||||||
|
#include "Prism/Renderer/SceneEnvironment.h"
|
||||||
|
|
||||||
namespace Prism
|
namespace Prism
|
||||||
{
|
{
|
||||||
|
|
||||||
struct PRISM_API Environment
|
|
||||||
{
|
|
||||||
std::string FilePath;
|
|
||||||
Ref<TextureCube> RadianceMap;
|
|
||||||
Ref<TextureCube> IrradianceMap;
|
|
||||||
|
|
||||||
static Environment Load(const std::string& filepath);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Light
|
struct Light
|
||||||
{
|
{
|
||||||
glm::vec3 Direction{-0.314f, -0.941f, -0.209f};
|
glm::vec3 Direction{-0.314f, -0.941f, -0.209f};
|
||||||
@ -34,6 +26,23 @@ namespace Prism
|
|||||||
float Multiplier = 1.0f;
|
float Multiplier = 1.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DirectionalLight
|
||||||
|
{
|
||||||
|
glm::vec3 Direction = { 0.0f, 0.0f, 0.0f };
|
||||||
|
glm::vec3 Radiance = { 0.0f, 0.0f, 0.0f };
|
||||||
|
float Multiplier = 0.0f;
|
||||||
|
|
||||||
|
// C++ only
|
||||||
|
bool CastShadows = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LightEnvironment
|
||||||
|
{
|
||||||
|
DirectionalLight DirectionalLights[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Entity;
|
class Entity;
|
||||||
using EntityMap = std::unordered_map<UUID, Entity>;
|
using EntityMap = std::unordered_map<UUID, Entity>;
|
||||||
|
|
||||||
@ -56,7 +65,6 @@ namespace Prism
|
|||||||
|
|
||||||
void SetViewportSize(uint32_t width, uint32_t height);
|
void SetViewportSize(uint32_t width, uint32_t height);
|
||||||
|
|
||||||
void SetEnvironment(const Environment& environment);
|
|
||||||
const Environment& GetEnvironment() const { return m_Environment; }
|
const Environment& GetEnvironment() const { return m_Environment; }
|
||||||
void SetSkybox(const Ref<TextureCube>& skybox);
|
void SetSkybox(const Ref<TextureCube>& skybox);
|
||||||
|
|
||||||
@ -115,9 +123,12 @@ namespace Prism
|
|||||||
|
|
||||||
Light m_Light;
|
Light m_Light;
|
||||||
float m_LightMultiplier = 0.3f;
|
float m_LightMultiplier = 0.3f;
|
||||||
|
LightEnvironment m_LightEnvironment;
|
||||||
|
|
||||||
bool m_IsPlaying = false;
|
bool m_IsPlaying = false;
|
||||||
|
|
||||||
Environment m_Environment;
|
Environment m_Environment;
|
||||||
|
float m_EnvironmentIntensity = 1.0f;
|
||||||
Ref<TextureCube> m_SkyboxTexture;
|
Ref<TextureCube> m_SkyboxTexture;
|
||||||
Ref<MaterialInstance> m_SkyboxMaterial;
|
Ref<MaterialInstance> m_SkyboxMaterial;
|
||||||
|
|
||||||
|
|||||||
@ -244,6 +244,33 @@ namespace Prism
|
|||||||
out << YAML::EndMap; // MeshComponent
|
out << YAML::EndMap; // MeshComponent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (entity.HasComponent<DirectionalLightComponent>())
|
||||||
|
{
|
||||||
|
out << YAML::Key << "DirectionalLightComponent";
|
||||||
|
out << YAML::BeginMap; // DirectionalLightComponent
|
||||||
|
|
||||||
|
auto& directionalLightComponent = entity.GetComponent<DirectionalLightComponent>();
|
||||||
|
out << YAML::Key << "Radiance" << YAML::Value << directionalLightComponent.Radiance;
|
||||||
|
out << YAML::Key << "CastShadows" << YAML::Value << directionalLightComponent.CastShadows;
|
||||||
|
out << YAML::Key << "SoftShadows" << YAML::Value << directionalLightComponent.SoftShadows;
|
||||||
|
out << YAML::Key << "LightSize" << YAML::Value << directionalLightComponent.LightSize;
|
||||||
|
|
||||||
|
out << YAML::EndMap; // DirectionalLightComponent
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entity.HasComponent<SkyLightComponent>())
|
||||||
|
{
|
||||||
|
out << YAML::Key << "SkyLightComponent";
|
||||||
|
out << YAML::BeginMap; // SkyLightComponent
|
||||||
|
|
||||||
|
auto& skyLightComponent = entity.GetComponent<SkyLightComponent>();
|
||||||
|
out << YAML::Key << "EnvironmentAssetPath" << YAML::Value << skyLightComponent.SceneEnvironment.FilePath;
|
||||||
|
out << YAML::Key << "Intensity" << YAML::Value << skyLightComponent.Intensity;
|
||||||
|
out << YAML::Key << "Angle" << YAML::Value << skyLightComponent.Angle;
|
||||||
|
|
||||||
|
out << YAML::EndMap; // SkyLightComponent
|
||||||
|
}
|
||||||
|
|
||||||
if (entity.HasComponent<CameraComponent>())
|
if (entity.HasComponent<CameraComponent>())
|
||||||
{
|
{
|
||||||
out << YAML::Key << "CameraComponent";
|
out << YAML::Key << "CameraComponent";
|
||||||
@ -394,6 +421,7 @@ namespace Prism
|
|||||||
|
|
||||||
auto meshColliderComponent = entity.GetComponent<MeshColliderComponent>();
|
auto meshColliderComponent = entity.GetComponent<MeshColliderComponent>();
|
||||||
out << YAML::Key << "AssetPath" << YAML::Value << meshColliderComponent.CollisionMesh->GetFilePath();
|
out << YAML::Key << "AssetPath" << YAML::Value << meshColliderComponent.CollisionMesh->GetFilePath();
|
||||||
|
out << YAML::Key << "IsConvex" << YAML::Value << meshColliderComponent.IsConvex;
|
||||||
out << YAML::Key << "IsTrigger" << YAML::Value << meshColliderComponent.IsTrigger;
|
out << YAML::Key << "IsTrigger" << YAML::Value << meshColliderComponent.IsTrigger;
|
||||||
|
|
||||||
out << YAML::EndMap; // MeshColliderComponent
|
out << YAML::EndMap; // MeshColliderComponent
|
||||||
@ -489,7 +517,7 @@ namespace Prism
|
|||||||
if (environment)
|
if (environment)
|
||||||
{
|
{
|
||||||
std::string envPath = environment["AssetPath"].as<std::string>();
|
std::string envPath = environment["AssetPath"].as<std::string>();
|
||||||
m_Scene->SetEnvironment(Environment::Load(envPath));
|
// m_Scene->SetEnvironment(Environment::Load(envPath));
|
||||||
|
|
||||||
auto lightNode = environment["Light"];
|
auto lightNode = environment["Light"];
|
||||||
if (lightNode)
|
if (lightNode)
|
||||||
@ -606,7 +634,7 @@ namespace Prism
|
|||||||
|
|
||||||
if (auto meshComponent = entity["MeshComponent"])
|
if (auto meshComponent = entity["MeshComponent"])
|
||||||
{
|
{
|
||||||
std::string meshPath = meshComponent["AssetPath"].as<std::string>();
|
const std::string meshPath = meshComponent["AssetPath"].as<std::string>();
|
||||||
// TEMP (because script creates mesh component...)
|
// TEMP (because script creates mesh component...)
|
||||||
if (!deserializedEntity.HasComponent<MeshComponent>())
|
if (!deserializedEntity.HasComponent<MeshComponent>())
|
||||||
deserializedEntity.AddComponent<MeshComponent>(Ref<Mesh>::Create(meshPath));
|
deserializedEntity.AddComponent<MeshComponent>(Ref<Mesh>::Create(meshPath));
|
||||||
@ -614,6 +642,25 @@ namespace Prism
|
|||||||
PM_CORE_INFO(" Mesh Asset Path: {0}", meshPath);
|
PM_CORE_INFO(" Mesh Asset Path: {0}", meshPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (auto directionalLightComponent = entity["DirectionalLightComponent"])
|
||||||
|
{
|
||||||
|
auto& component = deserializedEntity.AddComponent<DirectionalLightComponent>();
|
||||||
|
component.Radiance = directionalLightComponent["Radiance"].as<glm::vec3>();
|
||||||
|
component.CastShadows = directionalLightComponent["CastShadows"].as<bool>();
|
||||||
|
component.SoftShadows = directionalLightComponent["SoftShadows"].as<bool>();
|
||||||
|
component.LightSize = directionalLightComponent["LightSize"].as<float>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto skyLightComponent = entity["SkyLightComponent"])
|
||||||
|
{
|
||||||
|
auto& component = deserializedEntity.AddComponent<SkyLightComponent>();
|
||||||
|
const std::string env = skyLightComponent["EnvironmentAssetPath"].as<std::string>();
|
||||||
|
if (!env.empty())
|
||||||
|
component.SceneEnvironment = Environment::Load(env);
|
||||||
|
component.Intensity = skyLightComponent["Intensity"].as<float>();
|
||||||
|
component.Angle = skyLightComponent["Angle"].as<float>();
|
||||||
|
}
|
||||||
|
|
||||||
if (auto cameraComponent = entity["CameraComponent"])
|
if (auto cameraComponent = entity["CameraComponent"])
|
||||||
{
|
{
|
||||||
auto& component = deserializedEntity.AddComponent<CameraComponent>();
|
auto& component = deserializedEntity.AddComponent<CameraComponent>();
|
||||||
@ -712,8 +759,12 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
auto meshPath = meshColliderComponent["AssetPath"].as<std::string>();
|
auto meshPath = meshColliderComponent["AssetPath"].as<std::string>();
|
||||||
auto& component = deserializedEntity.AddComponent<MeshColliderComponent>(Ref<Mesh>::Create(meshPath));
|
auto& component = deserializedEntity.AddComponent<MeshColliderComponent>(Ref<Mesh>::Create(meshPath));
|
||||||
|
component.IsConvex = meshColliderComponent["IsConvex"] ? meshColliderComponent["IsConvex"].as<bool>() : false;
|
||||||
component.IsTrigger = meshColliderComponent["IsTrigger"] ? meshColliderComponent["IsTrigger"].as<bool>() : false;
|
component.IsTrigger = meshColliderComponent["IsTrigger"] ? meshColliderComponent["IsTrigger"].as<bool>() : false;
|
||||||
|
if (component.IsConvex)
|
||||||
PhysicsWrappers::CreateConvexMesh(component);
|
PhysicsWrappers::CreateConvexMesh(component);
|
||||||
|
else
|
||||||
|
PhysicsWrappers::CreateTriangleMesh(component);
|
||||||
|
|
||||||
PM_CORE_INFO(" Mesh Collider Asset Path: {0}", meshPath);
|
PM_CORE_INFO(" Mesh Collider Asset Path: {0}", meshPath);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user