Compare commits
3 Commits
mono-PhysX
...
forward-re
| Author | SHA1 | Date | |
|---|---|---|---|
| b4d9dee045 | |||
| 4266a0b570 | |||
| ef4ea45edc |
@ -24,3 +24,4 @@ endif ()
|
||||
add_subdirectory(Prism)
|
||||
add_subdirectory(Sandbox)
|
||||
add_subdirectory(Editor)
|
||||
add_subdirectory(PrismRuntime)
|
||||
|
||||
@ -12,7 +12,7 @@ file(COPY ${IMGUI_INI} DESTINATION ${CMAKE_BINARY_DIR})
|
||||
file(GLOB DOTNET_LIBRARY library)
|
||||
file(COPY ${DOTNET_LIBRARY} DESTINATION ${CMAKE_BINARY_DIR})
|
||||
|
||||
file(GLOB_RECURSE SRC_SOURCE ./**.cpp)
|
||||
file(GLOB_RECURSE SRC_SOURCE ./Editor/**.cpp)
|
||||
|
||||
add_executable(${PROJECT_NAME} ${SRC_SOURCE})
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
#include "Prism/Physics/Physics3D.h"
|
||||
#include "Prism/Renderer/Renderer2D.h"
|
||||
#include "Prism/Script/ScriptEngine.h"
|
||||
#include "Prism/Script/ScriptWrappers.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
@ -51,8 +52,17 @@ namespace Prism
|
||||
NewScene();
|
||||
m_CurrentScene = m_EditorScene;
|
||||
|
||||
SceneRenderer::GetOptions().ShowGrid = true;
|
||||
|
||||
AssetEditorPanel::RegisterDefaultEditors();
|
||||
FileSystem::StartWatching();
|
||||
|
||||
m_ConsolePanel = CreateScope<ConsolePanel>();
|
||||
Script::SetLogCallback([this](const std::string& message)
|
||||
{
|
||||
if (m_ConsolePanel)
|
||||
m_ConsolePanel->AddMessage(message, ImVec4(1,1,1,1));
|
||||
});
|
||||
}
|
||||
|
||||
void EditorLayer::OnDetach()
|
||||
@ -105,7 +115,7 @@ namespace Prism
|
||||
Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false);
|
||||
const auto viewProj = m_EditorCamera.GetViewProjection();
|
||||
Renderer2D::BeginScene(viewProj, false);
|
||||
Renderer2D::DrawRotatedRect({ transform.Translation.x + collider.Offset.x, transform.Translation.y + collider.Offset.y }, {transform.Scale.x * collider.Size.x, transform.Scale.y * collider.Size.y}, transform.Rotation.z, { 0.0f, 0.0f, 1.0f, 1.0f });
|
||||
Renderer2D::DrawRotatedRect({ transform.Translation.x + collider.Offset.x, transform.Translation.y + collider.Offset.y , transform.Translation.z}, {transform.Scale.x * collider.Size.x, transform.Scale.y * collider.Size.y}, transform.Rotation.z, { 0.0f, 0.0f, 1.0f, 1.0f });
|
||||
Renderer2D::EndScene();
|
||||
Renderer::EndRenderPass();
|
||||
}
|
||||
@ -117,7 +127,7 @@ namespace Prism
|
||||
Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false);
|
||||
const auto viewProj = m_EditorCamera.GetViewProjection();
|
||||
Renderer2D::BeginScene(viewProj, false);
|
||||
Renderer2D::DrawCircle({ transform.Translation.x + collider.Offset.x, transform.Translation.y + collider.Offset.y}, collider.Radius, { 0.0f, 1.0f, 1.0f, 1.0f });
|
||||
Renderer2D::DrawCircle({ transform.Translation.x + collider.Offset.x, transform.Translation.y + collider.Offset.y, transform.Translation.z}, collider.Radius, { 0.0f, 1.0f, 1.0f, 1.0f });
|
||||
Renderer2D::EndScene();
|
||||
Renderer::EndRenderPass();
|
||||
}
|
||||
@ -144,6 +154,18 @@ namespace Prism
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (m_SceneState == SceneState::Play)
|
||||
{
|
||||
if (Input::GetCursorMode() != CursorMode::Normal)
|
||||
{
|
||||
if (Input::IsKeyPressed(KeyCode::LEFT_CONTROL) && Input::IsKeyPressed(KeyCode::LEFT_ALT) && Input::IsKeyPressed(KeyCode::GRAVE_ACCENT))
|
||||
{
|
||||
Input::SetCursorMode(CursorMode::Normal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EditorLayer::OnImGuiRender()
|
||||
@ -237,7 +259,7 @@ namespace Prism
|
||||
{
|
||||
// temp
|
||||
if (ImGui::MenuItem("Reload C# Assembly"))
|
||||
ScriptEngine::ReloadAssembly("assets/scripts/ExampleApp.dll");
|
||||
ScriptEngine::ReloadAssembly("assets/scripts/Assembly-Script.dll");
|
||||
|
||||
ImGui::MenuItem("Reload assembly on play", nullptr, &m_ReloadScriptOnPlay);
|
||||
ImGui::EndMenu();
|
||||
@ -275,8 +297,9 @@ namespace Prism
|
||||
Entity selectedEntity = m_SelectionContext.front().Entity;
|
||||
if (selectedEntity.HasComponent<MeshComponent>())
|
||||
{
|
||||
Ref<Mesh> mesh = selectedEntity.GetComponent<MeshComponent>().Mesh;
|
||||
if (mesh)
|
||||
auto& meshComponent = selectedEntity.GetComponent<MeshComponent>();
|
||||
|
||||
if (Ref<Mesh> mesh = meshComponent.Mesh)
|
||||
{
|
||||
auto& materials = mesh->GetMaterials();
|
||||
static uint32_t selectedMaterialIndex = 0;
|
||||
@ -304,27 +327,13 @@ namespace Prism
|
||||
}
|
||||
ImGui::EndChild();
|
||||
}
|
||||
/*
|
||||
for (uint32_t i = 0; i < materials.size(); i++)
|
||||
{
|
||||
const auto& materialInstance = materials[i];
|
||||
|
||||
ImGuiTreeNodeFlags node_flags = (selectedMaterialIndex == i ? ImGuiTreeNodeFlags_Selected : 0) | ImGuiTreeNodeFlags_Leaf;
|
||||
bool opened = ImGui::TreeNodeEx((void*)(&materialInstance), node_flags, "%s", materialInstance->GetName().c_str());
|
||||
if (ImGui::IsItemClicked())
|
||||
{
|
||||
selectedMaterialIndex = i;
|
||||
}
|
||||
if (opened)
|
||||
ImGui::TreePop();
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (selectedMaterialIndex < materials.size())
|
||||
{
|
||||
bool shouldUpdate = false;
|
||||
|
||||
auto& materialInstance = materials[selectedMaterialIndex];
|
||||
ImGui::Text("Shader: %s", materialInstance->GetShader()->GetName().c_str());
|
||||
// Textures ------------------------------------------------------------------------------
|
||||
@ -339,6 +348,21 @@ namespace Prism
|
||||
Ref<Texture2D> albedoMap = materialInstance->TryGetResource<Texture2D>("u_AlbedoTexture");
|
||||
|
||||
ImGui::Image(albedoMap ? (ImTextureRef)albedoMap->GetRendererID() : (ImTextureRef)m_CheckerboardTex->GetRendererID(), ImVec2(64, 64));
|
||||
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
if (const auto data = ImGui::AcceptDragDropPayload("asset_payload"))
|
||||
{
|
||||
AssetHandle assetHandle = *(AssetHandle*)data->Data;
|
||||
if (AssetsManager::IsAssetType(assetHandle, AssetType::Texture))
|
||||
{
|
||||
albedoMap = AssetsManager::GetAsset<Texture2D>(assetHandle);
|
||||
shouldUpdate = true;
|
||||
}
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
@ -351,28 +375,23 @@ namespace Prism
|
||||
ImGui::Image((ImTextureRef)albedoMap->GetRendererID(), ImVec2(384, 384));
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
if (ImGui::IsItemClicked())
|
||||
{
|
||||
if (std::string filename = FileSystem::OpenFileSelector("*.png;*.tga;*.jpg;*.jpeg"); !filename.empty())
|
||||
{
|
||||
albedoMap = Texture2D::Create(filename, true/*m_AlbedoInput.SRGB*/);
|
||||
materialInstance->Set("u_AlbedoTexture", albedoMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::BeginGroup();
|
||||
if (ImGui::Checkbox("Use##AlbedoMap", &useAlbedoMap))
|
||||
materialInstance->Set<float>("u_AlbedoTexToggle", useAlbedoMap ? 1.0f : 0.0f);
|
||||
|
||||
/*if (ImGui::Checkbox("sRGB##AlbedoMap", &m_AlbedoInput.SRGB))
|
||||
{
|
||||
if (m_AlbedoInput.TextureMap)
|
||||
m_AlbedoInput.TextureMap = Texture2D::Create(m_AlbedoInput.TextureMap->GetPath(), m_AlbedoInput.SRGB);
|
||||
}*/
|
||||
materialInstance->Set<float>("u_AlbedoTexToggle", useAlbedoMap ? 1.0f : 0.0f);
|
||||
shouldUpdate = true;
|
||||
}
|
||||
|
||||
|
||||
ImGui::EndGroup();
|
||||
ImGui::SameLine();
|
||||
ImGui::ColorEdit3("Color##Albedo", glm::value_ptr(albedoColor), ImGuiColorEditFlags_NoInputs);
|
||||
if (ImGui::ColorEdit3("Color##Albedo", glm::value_ptr(albedoColor), ImGuiColorEditFlags_NoInputs))
|
||||
{
|
||||
meshComponent.UpdateMaterials(selectedMaterialIndex);
|
||||
shouldUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
@ -385,6 +404,21 @@ namespace Prism
|
||||
Ref<Texture2D> normalMap = materialInstance->TryGetResource<Texture2D>("u_NormalTexture");
|
||||
|
||||
ImGui::Image(normalMap ? (ImTextureRef)normalMap->GetRendererID() : (ImTextureRef)m_CheckerboardTex->GetRendererID(), ImVec2(64, 64));
|
||||
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
if (const auto data = ImGui::AcceptDragDropPayload("asset_payload"))
|
||||
{
|
||||
AssetHandle assetHandle = *(AssetHandle*)data->Data;
|
||||
if (AssetsManager::IsAssetType(assetHandle, AssetType::Texture))
|
||||
{
|
||||
normalMap = AssetsManager::GetAsset<Texture2D>(assetHandle);
|
||||
shouldUpdate = true;
|
||||
}
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
@ -403,12 +437,16 @@ namespace Prism
|
||||
{
|
||||
normalMap = Texture2D::Create(filename);
|
||||
materialInstance->Set("u_NormalTexture", normalMap);
|
||||
shouldUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Checkbox("Use##NormalMap", &useNormalMap))
|
||||
{
|
||||
materialInstance->Set<float>("u_NormalTexToggle", useNormalMap ? 1.0f : 0.0f);
|
||||
shouldUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
@ -422,6 +460,21 @@ namespace Prism
|
||||
Ref<Texture2D> metalnessMap = materialInstance->TryGetResource<Texture2D>("u_MetalnessTexture");
|
||||
|
||||
ImGui::Image(metalnessMap ? (ImTextureRef)metalnessMap->GetRendererID() : (ImTextureRef)m_CheckerboardTex->GetRendererID(), ImVec2(64, 64));
|
||||
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
if (const auto data = ImGui::AcceptDragDropPayload("asset_payload"))
|
||||
{
|
||||
AssetHandle assetHandle = *(AssetHandle*)data->Data;
|
||||
if (AssetsManager::IsAssetType(assetHandle, AssetType::Texture))
|
||||
{
|
||||
metalnessMap = AssetsManager::GetAsset<Texture2D>(assetHandle);
|
||||
shouldUpdate = true;
|
||||
}
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
@ -434,20 +487,18 @@ namespace Prism
|
||||
ImGui::Image((ImTextureRef)metalnessMap->GetRendererID(), ImVec2(384, 384));
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
if (ImGui::IsItemClicked())
|
||||
{
|
||||
if (std::string filename = FileSystem::OpenFileSelector("*.png;*.tga;*.jpg;*.jpeg"); !filename.empty())
|
||||
{
|
||||
metalnessMap = Texture2D::Create(filename);
|
||||
materialInstance->Set("u_MetalnessTexture", metalnessMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Checkbox("Use##MetalnessMap", &useMetalnessMap))
|
||||
{
|
||||
materialInstance->Set<float>("u_MetalnessTexToggle", useMetalnessMap ? 1.0f : 0.0f);
|
||||
shouldUpdate = true;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::SliderFloat("Value##MetalnessInput", &metalnessValue, 0.0f, 1.0f);
|
||||
if (ImGui::SliderFloat("Value##MetalnessInput", &metalnessValue, 0.0f, 1.0f))
|
||||
{
|
||||
shouldUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
@ -460,6 +511,20 @@ namespace Prism
|
||||
Ref<Texture2D> roughnessMap = materialInstance->TryGetResource<Texture2D>("u_RoughnessTexture");
|
||||
|
||||
ImGui::Image(roughnessMap ? (ImTextureRef)roughnessMap->GetRendererID() : (ImTextureRef)m_CheckerboardTex->GetRendererID(), ImVec2(64, 64));
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
if (const auto data = ImGui::AcceptDragDropPayload("asset_payload"))
|
||||
{
|
||||
AssetHandle assetHandle = *(AssetHandle*)data->Data;
|
||||
if (AssetsManager::IsAssetType(assetHandle, AssetType::Texture))
|
||||
{
|
||||
roughnessMap = AssetsManager::GetAsset<Texture2D>(assetHandle);
|
||||
shouldUpdate = true;
|
||||
}
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
@ -472,22 +537,21 @@ namespace Prism
|
||||
ImGui::Image((ImTextureRef)roughnessMap->GetRendererID(), ImVec2(384, 384));
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
if (ImGui::IsItemClicked())
|
||||
{
|
||||
if (std::string filename = FileSystem::OpenFileSelector("*.png;*.tga;*.jpg;*.jpeg"); !filename.empty())
|
||||
{
|
||||
roughnessMap = Texture2D::Create(filename);
|
||||
materialInstance->Set("u_RoughnessTexture", roughnessMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Checkbox("Use##RoughnessMap", &useRoughnessMap))
|
||||
{
|
||||
materialInstance->Set<float>("u_RoughnessTexToggle", useRoughnessMap ? 1.0f : 0.0f);
|
||||
shouldUpdate = true;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::SliderFloat("Value##RoughnessInput", &roughnessValue, 0.0f, 1.0f);
|
||||
if (ImGui::SliderFloat("Value##RoughnessInput", &roughnessValue, 0.0f, 1.0f))
|
||||
{
|
||||
shouldUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (shouldUpdate) meshComponent.UpdateMaterials(selectedMaterialIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -505,7 +569,8 @@ namespace Prism
|
||||
m_ObjectsPanel->OnImGuiRender();
|
||||
|
||||
m_SceneHierarchyPanel->OnImGuiRender();
|
||||
m_EditorCamera.OnImGuiRender();
|
||||
// m_EditorCamera.OnImGuiRender();
|
||||
m_ConsolePanel->OnImGuiRender();
|
||||
|
||||
// Editor Panel ------------------------------------------------------------------------------
|
||||
ImGui::Begin("Environment");
|
||||
@ -1054,17 +1119,6 @@ namespace Prism
|
||||
});
|
||||
if (!m_SelectionContext.empty())
|
||||
{
|
||||
if (auto alreadySelectedEntity = m_SceneHierarchyPanel->GetSelected();
|
||||
m_SelectionContext.size() != 1 && alreadySelectedEntity)
|
||||
{
|
||||
const auto alreadySelectedEntityID = alreadySelectedEntity.GetUUID();
|
||||
|
||||
for (const auto& selectedEntity : m_SelectionContext)
|
||||
{
|
||||
if (alreadySelectedEntityID == selectedEntity.Entity.GetUUID()) continue;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
OnSelected(m_SelectionContext[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#ifndef EDITORLAYER_H
|
||||
#define EDITORLAYER_H
|
||||
|
||||
#include "Panels/ConsolePanel.h"
|
||||
#include "Prism.h"
|
||||
#include "Prism/Editor/ContentBrowserPanel.h"
|
||||
#include "Prism/Editor/ObjectsPanel.h"
|
||||
@ -150,6 +151,9 @@ namespace Prism
|
||||
Edit = 0, Play = 1, Pause = 2
|
||||
};
|
||||
SceneState m_SceneState = SceneState::Edit;
|
||||
|
||||
private:
|
||||
Scope<ConsolePanel> m_ConsolePanel;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
66
Editor/Editor/Panels/ConsolePanel.cpp
Normal file
66
Editor/Editor/Panels/ConsolePanel.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/26.
|
||||
//
|
||||
|
||||
#include "ConsolePanel.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
ConsolePanel::ConsolePanel()
|
||||
{
|
||||
// 预留一些空间
|
||||
m_Messages.reserve(1000);
|
||||
}
|
||||
|
||||
void ConsolePanel::OnImGuiRender()
|
||||
{
|
||||
ImGui::Begin("Console");
|
||||
|
||||
// 工具栏
|
||||
if (ImGui::Button("Clear"))
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_Mutex);
|
||||
m_Messages.clear();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox("Auto-scroll", &m_AutoScroll);
|
||||
ImGui::SameLine();
|
||||
m_Filter.Draw("Filter", 200);
|
||||
|
||||
// 消息列表区域
|
||||
ImGui::BeginChild("ScrollingRegion", ImVec2(0, 0), ImGuiChildFlags_Borders, ImGuiWindowFlags_HorizontalScrollbar);
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_Mutex);
|
||||
for (const auto& [msg, color] : m_Messages)
|
||||
{
|
||||
if (m_Filter.PassFilter(msg.c_str()))
|
||||
{
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, color);
|
||||
ImGui::TextUnformatted(msg.c_str());
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_ScrollToBottom)
|
||||
{
|
||||
ImGui::SetScrollHereY(1.0f);
|
||||
m_ScrollToBottom = false;
|
||||
}
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void ConsolePanel::AddMessage(const std::string& message, ImVec4 color)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_Mutex);
|
||||
m_Messages.emplace_back(message, color);
|
||||
while (m_Messages.size() > 5000)
|
||||
m_Messages.erase(m_Messages.begin());
|
||||
|
||||
if (m_AutoScroll && !m_ScrollToBottom)
|
||||
m_ScrollToBottom = true;
|
||||
}
|
||||
}
|
||||
31
Editor/Editor/Panels/ConsolePanel.h
Normal file
31
Editor/Editor/Panels/ConsolePanel.h
Normal file
@ -0,0 +1,31 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/26.
|
||||
//
|
||||
|
||||
#ifndef PRISM_CONSOLEPANEL_H
|
||||
#define PRISM_CONSOLEPANEL_H
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#include "imgui.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
class ConsolePanel
|
||||
{
|
||||
public:
|
||||
ConsolePanel();
|
||||
void OnImGuiRender();
|
||||
|
||||
void AddMessage(const std::string& message, ImVec4 color = ImVec4(1,1,1,1));
|
||||
|
||||
private:
|
||||
std::vector<std::pair<std::string, ImVec4>> m_Messages;
|
||||
ImGuiTextFilter m_Filter;
|
||||
bool m_AutoScroll = true;
|
||||
bool m_ScrollToBottom = false;
|
||||
std::mutex m_Mutex;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //PRISM_CONSOLEPANEL_H
|
||||
336
Editor/assets/scenes/FPS.scene
Normal file
336
Editor/assets/scenes/FPS.scene
Normal file
@ -0,0 +1,336 @@
|
||||
Scene: Scene Name
|
||||
Environment:
|
||||
AssetHandle: 5211537204242875091
|
||||
Entities:
|
||||
- Entity: 8293051279669100759
|
||||
Parent: 0
|
||||
Children:
|
||||
[]
|
||||
TagComponent:
|
||||
Tag: Cube
|
||||
TransformComponent:
|
||||
Position: [1.736814, 1.4724115, -4.2181306]
|
||||
Rotation: [0, 0, 0]
|
||||
Scale: [1, 1, 1]
|
||||
MeshComponent:
|
||||
AssetID: 18328012085543462741
|
||||
AssetPath: assets/meshes/Default/Cube.fbx
|
||||
RigidBodyComponent:
|
||||
BodyType: 1
|
||||
Mass: 1
|
||||
LinearDrag: 0
|
||||
AngularDrag: 0.05
|
||||
DisableGravity: false
|
||||
IsKinematic: false
|
||||
Layer: 0
|
||||
Constraints:
|
||||
LockPositionX: false
|
||||
LockPositionY: false
|
||||
LockPositionZ: false
|
||||
LockRotationX: false
|
||||
LockRotationY: false
|
||||
LockRotationZ: false
|
||||
BoxColliderComponent:
|
||||
Offset: [0, 0, 0]
|
||||
Size: [2, 2, 2]
|
||||
IsTrigger: false
|
||||
Material: 0
|
||||
MaterialPath: ""
|
||||
- Entity: 5834225236589765516
|
||||
Parent: 0
|
||||
Children:
|
||||
[]
|
||||
TagComponent:
|
||||
Tag: Cube
|
||||
TransformComponent:
|
||||
Position: [-2.6417403, 1.4724115, -7.9285727]
|
||||
Rotation: [0.52199936, 0, 0]
|
||||
Scale: [1, 1.0000001, 1.0000001]
|
||||
MeshComponent:
|
||||
AssetID: 18328012085543462741
|
||||
AssetPath: assets/meshes/Default/Cube.fbx
|
||||
RigidBodyComponent:
|
||||
BodyType: 1
|
||||
Mass: 1
|
||||
LinearDrag: 0
|
||||
AngularDrag: 0.05
|
||||
DisableGravity: false
|
||||
IsKinematic: false
|
||||
Layer: 0
|
||||
Constraints:
|
||||
LockPositionX: false
|
||||
LockPositionY: false
|
||||
LockPositionZ: false
|
||||
LockRotationX: false
|
||||
LockRotationY: false
|
||||
LockRotationZ: false
|
||||
BoxColliderComponent:
|
||||
Offset: [0, 0, 0]
|
||||
Size: [2, 2, 2]
|
||||
IsTrigger: false
|
||||
Material: 0
|
||||
MaterialPath: ""
|
||||
- Entity: 8234256119181302872
|
||||
Parent: 0
|
||||
Children:
|
||||
[]
|
||||
TagComponent:
|
||||
Tag: Cube
|
||||
TransformComponent:
|
||||
Position: [1.736814, 1.4724115, -7.9285727]
|
||||
Rotation: [0, 0, 0]
|
||||
Scale: [1, 1, 1]
|
||||
MeshComponent:
|
||||
AssetID: 18328012085543462741
|
||||
AssetPath: assets/meshes/Default/Cube.fbx
|
||||
RigidBodyComponent:
|
||||
BodyType: 1
|
||||
Mass: 1
|
||||
LinearDrag: 0
|
||||
AngularDrag: 0.05
|
||||
DisableGravity: false
|
||||
IsKinematic: false
|
||||
Layer: 0
|
||||
Constraints:
|
||||
LockPositionX: false
|
||||
LockPositionY: false
|
||||
LockPositionZ: false
|
||||
LockRotationX: false
|
||||
LockRotationY: false
|
||||
LockRotationZ: false
|
||||
BoxColliderComponent:
|
||||
Offset: [0, 0, 0]
|
||||
Size: [2, 2, 2]
|
||||
IsTrigger: false
|
||||
Material: 0
|
||||
MaterialPath: ""
|
||||
- Entity: 12935252585493481950
|
||||
Parent: 0
|
||||
Children:
|
||||
[]
|
||||
TagComponent:
|
||||
Tag: Cube
|
||||
TransformComponent:
|
||||
Position: [-1.5106764, 6.237644, -4.2181306]
|
||||
Rotation: [0, 0, 0]
|
||||
Scale: [1, 1, 1]
|
||||
MeshComponent:
|
||||
AssetID: 18328012085543462741
|
||||
AssetPath: assets/meshes/Default/Cube.fbx
|
||||
RigidBodyComponent:
|
||||
BodyType: 1
|
||||
Mass: 1
|
||||
LinearDrag: 0
|
||||
AngularDrag: 0.05
|
||||
DisableGravity: false
|
||||
IsKinematic: false
|
||||
Layer: 0
|
||||
Constraints:
|
||||
LockPositionX: false
|
||||
LockPositionY: false
|
||||
LockPositionZ: false
|
||||
LockRotationX: false
|
||||
LockRotationY: false
|
||||
LockRotationZ: false
|
||||
BoxColliderComponent:
|
||||
Offset: [0, 0, 0]
|
||||
Size: [2, 2, 2]
|
||||
IsTrigger: false
|
||||
Material: 0
|
||||
MaterialPath: ""
|
||||
- Entity: 3328246672296261054
|
||||
Parent: 0
|
||||
Children:
|
||||
[]
|
||||
TagComponent:
|
||||
Tag: Cube
|
||||
TransformComponent:
|
||||
Position: [1.736814, 1.4724115, -0.88378817]
|
||||
Rotation: [0, 0, 0]
|
||||
Scale: [1, 1, 1]
|
||||
MeshComponent:
|
||||
AssetID: 18328012085543462741
|
||||
AssetPath: assets/meshes/Default/Cube.fbx
|
||||
RigidBodyComponent:
|
||||
BodyType: 1
|
||||
Mass: 1
|
||||
LinearDrag: 0
|
||||
AngularDrag: 0.05
|
||||
DisableGravity: false
|
||||
IsKinematic: false
|
||||
Layer: 0
|
||||
Constraints:
|
||||
LockPositionX: false
|
||||
LockPositionY: false
|
||||
LockPositionZ: false
|
||||
LockRotationX: false
|
||||
LockRotationY: false
|
||||
LockRotationZ: false
|
||||
BoxColliderComponent:
|
||||
Offset: [0, 0, 0]
|
||||
Size: [2, 2, 2]
|
||||
IsTrigger: false
|
||||
Material: 0
|
||||
MaterialPath: ""
|
||||
- Entity: 4208267561919679628
|
||||
Parent: 0
|
||||
Children:
|
||||
[]
|
||||
TagComponent:
|
||||
Tag: Cube
|
||||
TransformComponent:
|
||||
Position: [-2.6417403, 1.4724115, -4.8956265]
|
||||
Rotation: [-0.4034239, 0, 0]
|
||||
Scale: [1, 0.99999994, 0.99999994]
|
||||
MeshComponent:
|
||||
AssetID: 18328012085543462741
|
||||
AssetPath: assets/meshes/Default/Cube.fbx
|
||||
RigidBodyComponent:
|
||||
BodyType: 1
|
||||
Mass: 1
|
||||
LinearDrag: 0
|
||||
AngularDrag: 0.05
|
||||
DisableGravity: true
|
||||
IsKinematic: false
|
||||
Layer: 0
|
||||
Constraints:
|
||||
LockPositionX: false
|
||||
LockPositionY: false
|
||||
LockPositionZ: false
|
||||
LockRotationX: false
|
||||
LockRotationY: false
|
||||
LockRotationZ: false
|
||||
BoxColliderComponent:
|
||||
Offset: [0, 0, 0]
|
||||
Size: [2, 2, 2]
|
||||
IsTrigger: false
|
||||
Material: 0
|
||||
MaterialPath: ""
|
||||
- Entity: 8114736924719261351
|
||||
Parent: 0
|
||||
Children:
|
||||
[]
|
||||
TagComponent:
|
||||
Tag: Camera
|
||||
TransformComponent:
|
||||
Position: [0, 0.8097433, 4.573171]
|
||||
Rotation: [0, 0, 0]
|
||||
Scale: [1, 1, 1]
|
||||
CameraComponent:
|
||||
Camera:
|
||||
ProjectionType: 0
|
||||
PerspectiveFOV: 45
|
||||
PerspectiveNear: 0.01
|
||||
PerspectiveFar: 10000
|
||||
OrthographicSize: 10
|
||||
OrthographicNear: -1
|
||||
OrthographicFar: 1
|
||||
Primary: true
|
||||
- Entity: 9267298328378270409
|
||||
Parent: 0
|
||||
Children:
|
||||
[]
|
||||
TagComponent:
|
||||
Tag: Player
|
||||
TransformComponent:
|
||||
Position: [0, 0.70693016, 0]
|
||||
Rotation: [0, 0, 0]
|
||||
Scale: [1, 1, 1]
|
||||
ScriptComponent:
|
||||
ModuleName: FPSExample.FPSPlayer
|
||||
StoredFields:
|
||||
- Name: WalkingSpeed
|
||||
Type: 1
|
||||
Data: 2
|
||||
- Name: RunSpeed
|
||||
Type: 1
|
||||
Data: 5
|
||||
- Name: JumpForce
|
||||
Type: 1
|
||||
Data: 1
|
||||
- Name: MouseSensitivity
|
||||
Type: 1
|
||||
Data: 10
|
||||
- Name: CameraForwardOffset
|
||||
Type: 1
|
||||
Data: -2
|
||||
- Name: CameraYOffset
|
||||
Type: 1
|
||||
Data: 2
|
||||
MeshComponent:
|
||||
AssetID: 3043502408333723884
|
||||
AssetPath: assets/meshes/Default/Capsule.fbx
|
||||
RigidBodyComponent:
|
||||
BodyType: 1
|
||||
Mass: 1
|
||||
LinearDrag: 0
|
||||
AngularDrag: 0.05
|
||||
DisableGravity: false
|
||||
IsKinematic: false
|
||||
Layer: 0
|
||||
Constraints:
|
||||
LockPositionX: false
|
||||
LockPositionY: false
|
||||
LockPositionZ: false
|
||||
LockRotationX: true
|
||||
LockRotationY: false
|
||||
LockRotationZ: true
|
||||
MeshColliderComponent:
|
||||
IsConvex: true
|
||||
IsTrigger: false
|
||||
OverrideMesh: false
|
||||
Material: 0
|
||||
MaterialPath: ""
|
||||
- Entity: 10732070446010033158
|
||||
Parent: 0
|
||||
Children:
|
||||
[]
|
||||
TagComponent:
|
||||
Tag: Cube
|
||||
TransformComponent:
|
||||
Position: [0, -2.6466873, 0]
|
||||
Rotation: [0, 0, 0]
|
||||
Scale: [100, 1, 100]
|
||||
MeshComponent:
|
||||
AssetID: 18328012085543462741
|
||||
AssetPath: assets/meshes/Default/Cube.fbx
|
||||
RigidBodyComponent:
|
||||
BodyType: 0
|
||||
Mass: 1
|
||||
LinearDrag: 0
|
||||
AngularDrag: 0.05
|
||||
DisableGravity: false
|
||||
IsKinematic: false
|
||||
Layer: 0
|
||||
Constraints:
|
||||
LockPositionX: false
|
||||
LockPositionY: false
|
||||
LockPositionZ: false
|
||||
LockRotationX: false
|
||||
LockRotationY: false
|
||||
LockRotationZ: false
|
||||
BoxColliderComponent:
|
||||
Offset: [0, 0, 0]
|
||||
Size: [2, 2, 2]
|
||||
IsTrigger: false
|
||||
Material: 0
|
||||
MaterialPath: ""
|
||||
- Entity: 5099152432245948441
|
||||
Parent: 0
|
||||
Children:
|
||||
[]
|
||||
TagComponent:
|
||||
Tag: venice_dawn_1_4k
|
||||
TransformComponent:
|
||||
Position: [0, 0, 0]
|
||||
Rotation: [0, 0, 0]
|
||||
Scale: [1, 1, 1]
|
||||
SkyLightComponent:
|
||||
EnvironmentMap: 5211537204242875091
|
||||
EnvironmentAssetPath: assets/env/venice_dawn_1_4k.hdr
|
||||
Intensity: 1
|
||||
Angle: 0
|
||||
DynamicSky: false
|
||||
TurbidityAzimuthInclination: [2, 0, 0]
|
||||
PhysicsLayers:
|
||||
[]
|
||||
@ -1,11 +1,50 @@
|
||||
Scene: Scene Name
|
||||
Environment:
|
||||
AssetHandle: 10549690553241162923
|
||||
Light:
|
||||
Direction: [-0.314, -0.941, -0.209]
|
||||
Radiance: [0, 0, 0]
|
||||
Multiplier: 1
|
||||
AssetHandle: 6095149963749185931
|
||||
Entities:
|
||||
- Entity: 6421668200759325475
|
||||
Parent: 0
|
||||
Children:
|
||||
[]
|
||||
TagComponent:
|
||||
Tag: M1911Materials
|
||||
TransformComponent:
|
||||
Position: [0, 3.159583, 0]
|
||||
Rotation: [0, 0, 0]
|
||||
Scale: [1, 1, 1]
|
||||
MeshComponent:
|
||||
AssetID: 7219694555758922702
|
||||
AssetPath: assets/models/m1911/M1911Materials.fbx
|
||||
- Entity: 16992665426857995732
|
||||
Parent: 0
|
||||
Children:
|
||||
[]
|
||||
TagComponent:
|
||||
Tag: Cube
|
||||
TransformComponent:
|
||||
Position: [0, 0, 0]
|
||||
Rotation: [0, 0, 0]
|
||||
Scale: [50, 1, 50]
|
||||
MeshComponent:
|
||||
AssetID: 18328012085543462741
|
||||
AssetPath: assets/meshes/Default/Cube.fbx
|
||||
- Entity: 18182275256052989728
|
||||
Parent: 0
|
||||
Children:
|
||||
[]
|
||||
TagComponent:
|
||||
Tag: Sky Light
|
||||
TransformComponent:
|
||||
Position: [0, 0, 0]
|
||||
Rotation: [0, 0, 0]
|
||||
Scale: [1, 1, 1]
|
||||
SkyLightComponent:
|
||||
EnvironmentMap: 6095149963749185931
|
||||
EnvironmentAssetPath: ""
|
||||
Intensity: 1
|
||||
Angle: 0
|
||||
DynamicSky: true
|
||||
TurbidityAzimuthInclination: [2, 0.15, 0.71]
|
||||
- Entity: 17803125207910630398
|
||||
Parent: 0
|
||||
Children:
|
||||
@ -20,30 +59,6 @@ Entities:
|
||||
Radiance: [1, 1, 1]
|
||||
CastShadows: true
|
||||
SoftShadows: true
|
||||
LightSize: 0.5
|
||||
- Entity: 4315886439647742331
|
||||
Parent: 0
|
||||
Children:
|
||||
[]
|
||||
TagComponent:
|
||||
Tag: Cube
|
||||
TransformComponent:
|
||||
Position: [0, 2.048974, 0]
|
||||
Rotation: [0, 0, 0]
|
||||
Scale: [1, 1, 1]
|
||||
MeshComponent:
|
||||
AssetID: 3580169978473467053
|
||||
- Entity: 16992665426857995732
|
||||
Parent: 0
|
||||
Children:
|
||||
[]
|
||||
TagComponent:
|
||||
Tag: Cube
|
||||
TransformComponent:
|
||||
Position: [0, 0, 0]
|
||||
Rotation: [0, 0, 0]
|
||||
Scale: [50, 1, 50]
|
||||
MeshComponent:
|
||||
AssetID: 3580169978473467053
|
||||
LightSize: 0.9
|
||||
PhysicsLayers:
|
||||
[]
|
||||
@ -1,12 +1,21 @@
|
||||
Scene: Scene Name
|
||||
Environment:
|
||||
AssetHandle: 17073147362577408906
|
||||
Light:
|
||||
Direction: [-0.314, -0.941, -0.209]
|
||||
Radiance: [0, 0, 0]
|
||||
Multiplier: 1
|
||||
AssetHandle: 5211537204242875091
|
||||
Entities:
|
||||
- Entity: 3696833073589069488
|
||||
- Entity: 15706224176559717512
|
||||
Parent: 0
|
||||
Children:
|
||||
[]
|
||||
TagComponent:
|
||||
Tag: Cube
|
||||
TransformComponent:
|
||||
Position: [0, 0, 0]
|
||||
Rotation: [0, 0, 0]
|
||||
Scale: [1, 1, 1]
|
||||
MeshComponent:
|
||||
AssetID: 18328012085543462741
|
||||
AssetPath: assets/meshes/Default/Cube.fbx
|
||||
- Entity: 8041206185299282567
|
||||
Parent: 0
|
||||
Children:
|
||||
[]
|
||||
@ -17,8 +26,11 @@ Entities:
|
||||
Rotation: [0, 0, 0]
|
||||
Scale: [1, 1, 1]
|
||||
SkyLightComponent:
|
||||
EnvironmentMap: 17073147362577408906
|
||||
EnvironmentMap: 5211537204242875091
|
||||
EnvironmentAssetPath: assets/env/venice_dawn_1_4k.hdr
|
||||
Intensity: 1
|
||||
Angle: 0
|
||||
DynamicSky: false
|
||||
TurbidityAzimuthInclination: [2, 0, 0]
|
||||
PhysicsLayers:
|
||||
[]
|
||||
@ -1,6 +1,6 @@
|
||||
[Window][DockSpace Demo]
|
||||
Pos=0,0
|
||||
Size=2560,1566
|
||||
Size=1920,1080
|
||||
Collapsed=0
|
||||
|
||||
[Window][Debug##Default]
|
||||
@ -9,32 +9,32 @@ Size=400,400
|
||||
Collapsed=0
|
||||
|
||||
[Window][Scene Hierarchy]
|
||||
Pos=2089,24
|
||||
Size=471,563
|
||||
Pos=1449,24
|
||||
Size=471,385
|
||||
Collapsed=0
|
||||
DockId=0x00000009,0
|
||||
|
||||
[Window][Properties]
|
||||
Pos=2089,589
|
||||
Size=471,977
|
||||
Pos=1449,411
|
||||
Size=471,669
|
||||
Collapsed=0
|
||||
DockId=0x0000000A,0
|
||||
|
||||
[Window][Scene Renderer]
|
||||
Pos=0,843
|
||||
Size=481,723
|
||||
Pos=0,585
|
||||
Size=481,495
|
||||
Collapsed=0
|
||||
DockId=0x00000006,0
|
||||
|
||||
[Window][Materials]
|
||||
Pos=0,24
|
||||
Size=481,817
|
||||
Size=481,559
|
||||
Collapsed=0
|
||||
DockId=0x00000005,0
|
||||
|
||||
[Window][Script Engine Debug]
|
||||
Pos=2089,589
|
||||
Size=471,977
|
||||
Pos=1449,411
|
||||
Size=471,669
|
||||
Collapsed=0
|
||||
DockId=0x0000000A,2
|
||||
|
||||
@ -52,25 +52,25 @@ DockId=0x00000001,0
|
||||
|
||||
[Window][Viewport]
|
||||
Pos=483,58
|
||||
Size=1604,955
|
||||
Size=964,647
|
||||
Collapsed=0
|
||||
DockId=0x0000000B,0
|
||||
|
||||
[Window][Environment]
|
||||
Pos=2089,589
|
||||
Size=471,977
|
||||
Pos=1449,411
|
||||
Size=471,669
|
||||
Collapsed=0
|
||||
DockId=0x0000000A,1
|
||||
|
||||
[Window][Project]
|
||||
Pos=483,1015
|
||||
Size=1604,551
|
||||
Pos=483,707
|
||||
Size=964,373
|
||||
Collapsed=0
|
||||
DockId=0x0000000C,0
|
||||
|
||||
[Window][Objects]
|
||||
Pos=483,1015
|
||||
Size=1604,551
|
||||
Pos=483,707
|
||||
Size=964,373
|
||||
Collapsed=0
|
||||
DockId=0x0000000C,1
|
||||
|
||||
@ -81,12 +81,18 @@ Collapsed=0
|
||||
|
||||
[Window][##tool_bar]
|
||||
Pos=483,24
|
||||
Size=1604,32
|
||||
Size=964,32
|
||||
Collapsed=0
|
||||
DockId=0x00000001,0
|
||||
|
||||
[Window][Console]
|
||||
Pos=483,707
|
||||
Size=964,373
|
||||
Collapsed=0
|
||||
DockId=0x0000000C,2
|
||||
|
||||
[Docking][Data]
|
||||
DockSpace ID=0xC0DFADC4 Window=0xD0388BC8 Pos=0,58 Size=2560,1542 Split=X Selected=0x0C01D6D5
|
||||
DockSpace ID=0xC0DFADC4 Window=0xD0388BC8 Pos=268,189 Size=1920,1056 Split=X Selected=0x0C01D6D5
|
||||
DockNode ID=0x00000007 Parent=0xC0DFADC4 SizeRef=1557,1542 Split=X
|
||||
DockNode ID=0x00000003 Parent=0x00000007 SizeRef=481,1542 Split=Y Selected=0x5D711C2C
|
||||
DockNode ID=0x00000005 Parent=0x00000003 SizeRef=481,817 Selected=0x5D711C2C
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<InvariantGlobalization>true</InvariantGlobalization>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using Prism;
|
||||
|
||||
namespace FPSExample
|
||||
@ -8,6 +9,8 @@ namespace FPSExample
|
||||
public float RunSpeed = 20.0f;
|
||||
public float JumpForce = 50.0f;
|
||||
|
||||
public float m_Radius = 0.5f;
|
||||
public float TorqueStrength = 10.0f;
|
||||
|
||||
[NonSerialized]
|
||||
public float MouseSensitivity = 10.0f;
|
||||
@ -46,6 +49,9 @@ namespace FPSExample
|
||||
m_LastMousePosition = Input.GetMousePosition();
|
||||
|
||||
Input.SetCursorMode(Input.CursorMode.Locked);
|
||||
|
||||
int size = Marshal.SizeOf<Transform>();
|
||||
Console.WriteLine($"C# size of Transform: {size}");
|
||||
}
|
||||
|
||||
void OnUpdate(float ts)
|
||||
@ -65,14 +71,19 @@ namespace FPSExample
|
||||
UpdateCameraTransform();
|
||||
}
|
||||
|
||||
void OnPhysicsUpdate(float fixedTimeStep)
|
||||
{
|
||||
UpdateMovement();
|
||||
}
|
||||
|
||||
private void UpdateRotation(float ts)
|
||||
{
|
||||
Vec2 currentMousePosition = Input.GetMousePosition();
|
||||
Vec2 delta = m_LastMousePosition - currentMousePosition;
|
||||
|
||||
float m_CurrentYMovement = delta.X * MouseSensitivity * ts;
|
||||
m_CurrentYMovement = delta.X * MouseSensitivity * ts;
|
||||
float xRotation = delta.Y * MouseSensitivity * ts;
|
||||
m_RigidBody.Rotate(new Vec3(0.0f, m_CurrentYMovement, 0.0f));
|
||||
// m_RigidBody.Rotate(new Vec3(0.0f, m_CurrentYMovement, 0.0f));
|
||||
|
||||
if (delta.X != 0 || delta.Y != 0)
|
||||
{
|
||||
@ -86,17 +97,25 @@ namespace FPSExample
|
||||
|
||||
private void UpdateMovementInput()
|
||||
{
|
||||
if (Input.IsKeyPressed(KeyCode.W))
|
||||
m_MovementDirection.Y += 1.0f;
|
||||
else if (Input.IsKeyPressed(KeyCode.S))
|
||||
if (Input.IsKeyPressed(KeyCode.W)){
|
||||
m_MovementDirection.Y -= 1.0f;
|
||||
Debug.Log("KeyPressed: W");
|
||||
}
|
||||
else if (Input.IsKeyPressed(KeyCode.S)){
|
||||
m_MovementDirection.Y += 1.0f;
|
||||
Debug.Log("KeyPressed: S");
|
||||
}
|
||||
else
|
||||
m_MovementDirection.Y = 0.0f;
|
||||
|
||||
if(Input.IsKeyPressed(KeyCode.A))
|
||||
m_MovementDirection.X -= 1.0f;
|
||||
else if (Input.IsKeyPressed(KeyCode.D))
|
||||
if(Input.IsKeyPressed(KeyCode.A)){
|
||||
m_MovementDirection.X += 1.0f;
|
||||
Debug.Log("KeyPressed: A");
|
||||
}
|
||||
else if (Input.IsKeyPressed(KeyCode.D)){
|
||||
m_MovementDirection.X -= 1.0f;
|
||||
Debug.Log("KeyPressed: D");
|
||||
}
|
||||
else
|
||||
m_MovementDirection.X = 0.0f;
|
||||
|
||||
@ -132,26 +151,64 @@ namespace FPSExample
|
||||
|
||||
}
|
||||
|
||||
void OnPhysicsUpdate(float fixedTimeStep)
|
||||
{
|
||||
UpdateMovement();
|
||||
}
|
||||
|
||||
private void UpdateMovement()
|
||||
{
|
||||
m_RigidBody.Rotate(new Vec3(0.0f, m_CurrentYMovement, 0.0f));
|
||||
// 2. 计算期望的移动方向(世界坐标系)
|
||||
Vec3 desiredDirection = Vec3.Zero;
|
||||
|
||||
Vec3 movement = m_CameraTransform.Transform.Right * m_MovementDirection.X + m_CameraTransform.Transform.Forward * m_MovementDirection.Y;
|
||||
if (m_MovementDirection.LengthSquared() != 0.0f)
|
||||
{
|
||||
Vec3 right = m_CameraTransform.Transform.Right;
|
||||
Vec3 forward = m_CameraTransform.Transform.Forward;
|
||||
right.Y = 0; forward.Y = 0;
|
||||
right.Normalize(); forward.Normalize();
|
||||
|
||||
desiredDirection = right * m_MovementDirection.X + forward * m_MovementDirection.Y;
|
||||
desiredDirection.Normalize();
|
||||
|
||||
/*
|
||||
Vec3 movement = right * m_MovementDirection.X + forward * m_MovementDirection.Y;
|
||||
movement.Normalize();
|
||||
Vec3 velocity = movement * m_CurrentSpeed;
|
||||
velocity.Y = m_RigidBody.GetLinearVelocity().Y;
|
||||
m_RigidBody.SetLinearVelocity(velocity);
|
||||
*/
|
||||
}
|
||||
Vec3 targetAngularVelocity = Vec3.Zero;
|
||||
if (desiredDirection.LengthSquared() > 0.01f)
|
||||
{
|
||||
Vec3 up = Vec3.Up;
|
||||
Vec3 rotationAxis = Vec3.Cross(desiredDirection, up).Normalized();
|
||||
float angularSpeed = 2 * (m_CurrentSpeed / m_Radius);
|
||||
targetAngularVelocity = rotationAxis * angularSpeed;
|
||||
|
||||
Vec3 currentAngular = m_RigidBody.GetAngularVelocity();
|
||||
Vec3 angularDiff = targetAngularVelocity - currentAngular;
|
||||
|
||||
float inertia = 0.4f * m_RigidBody.Mass * m_Radius * m_Radius;
|
||||
Vec3 torque = angularDiff * inertia * TorqueStrength;
|
||||
m_RigidBody.AddTorque(torque, RigidBodyComponent.ForceMode.Force);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// 3. 获取当前角速度,计算需要调整的差值
|
||||
Vec3 currentAngular = m_RigidBody.GetAngularVelocity();
|
||||
Vec3 angularDiff = targetAngularVelocity - currentAngular;
|
||||
|
||||
// 4. 施加扭矩:扭矩 = 转动惯量 * 角加速度
|
||||
// 球体的转动惯量 I = (2/5) * m * r^2 (实心球)
|
||||
float inertia = TorqueStrength * m_RigidBody.Mass * m_Radius * m_Radius;
|
||||
// 设定一个系数控制响应速度(可调)
|
||||
float torqueStrength = 5.0f;
|
||||
Vec3 torque = angularDiff * inertia * torqueStrength;
|
||||
m_RigidBody.AddTorque(-torque, RigidBodyComponent.ForceMode.Force);
|
||||
*/
|
||||
|
||||
if (m_ShouldJump && m_Colliding)
|
||||
{
|
||||
Debug.Log("Jump");
|
||||
m_RigidBody.AddForce(Vec3.Up * JumpForce, RigidBodyComponent.ForceMode.Impulse);
|
||||
m_ShouldJump = false;
|
||||
}
|
||||
@ -159,7 +216,7 @@ namespace FPSExample
|
||||
|
||||
private void UpdateCameraTransform(){
|
||||
Vec3 position = m_Transform.Translation + m_CameraTransform.Transform.Forward * CameraForwardOffset;
|
||||
position.Y += m_Transform.Translation.Y + CameraYOffset;
|
||||
position.Y += CameraYOffset;
|
||||
m_CameraTransform.Translation = position;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
<RootNamespace>Prism_ScriptCore</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<InvariantGlobalization>true</InvariantGlobalization>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
15
Prism-ScriptCore/Src/Prism/Engine/Engine.cs
Normal file
15
Prism-ScriptCore/Src/Prism/Engine/Engine.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
public class Debug
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern void Log_Native(string message);
|
||||
|
||||
public static void Log(string message)
|
||||
{
|
||||
Log_Native(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -9,8 +9,8 @@ namespace Prism
|
||||
public Vec3 Rotation;
|
||||
public Vec3 Scale;
|
||||
|
||||
public Vec3 Up { get; }
|
||||
public Vec3 Right { get; }
|
||||
public Vec3 Forward { get; }
|
||||
public Vec3 Up;
|
||||
public Vec3 Right;
|
||||
public Vec3 Forward;
|
||||
}
|
||||
}
|
||||
@ -53,6 +53,15 @@ namespace Prism
|
||||
Z = vec.Z;
|
||||
}
|
||||
|
||||
public static Vec3 Cross(Vec3 a, Vec3 b)
|
||||
{
|
||||
return new Vec3(
|
||||
a.Y * b.Z - a.Z * b.Y,
|
||||
a.Z * b.X - a.X * b.Z,
|
||||
a.X * b.Y - a.Y * b.X
|
||||
);
|
||||
}
|
||||
|
||||
public void Clamp(Vec3 min, Vec3 max)
|
||||
{
|
||||
X = Mathf.Clamp(X, min.X, max.X);
|
||||
@ -60,6 +69,7 @@ namespace Prism
|
||||
Z = Mathf.Clamp(Z, min.Z, max.Z);
|
||||
}
|
||||
|
||||
|
||||
public float LengthSquared()
|
||||
{
|
||||
return X * X + Y * Y + Z * Z;
|
||||
|
||||
@ -197,7 +197,45 @@ set_target_properties(${SHARED_LIBRARY} PROPERTIES
|
||||
)
|
||||
|
||||
|
||||
# static runtime library
|
||||
set(RUNTIME_LIBRARY ${PROJECT_NAME}-Runtime)
|
||||
|
||||
add_library(${RUNTIME_LIBRARY} STATIC ${SRC_SOURCE})
|
||||
|
||||
target_compile_definitions(${RUNTIME_LIBRARY} PRIVATE
|
||||
PRISM_RUNTIME
|
||||
INTERFACE
|
||||
PRISM_STATIC
|
||||
)
|
||||
|
||||
target_include_directories(${RUNTIME_LIBRARY} PUBLIC
|
||||
${TARGET_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
target_link_directories(${RUNTIME_LIBRARY} INTERFACE
|
||||
${PHYSX_LIB_DIR}
|
||||
)
|
||||
|
||||
target_link_libraries(${RUNTIME_LIBRARY}
|
||||
PRIVATE
|
||||
${LINK_LIBRARIES_PRIVATE}
|
||||
PUBLIC
|
||||
${LINK_LIBRARIES_PUBLIC}
|
||||
)
|
||||
target_precompile_headers(${RUNTIME_LIBRARY} PRIVATE
|
||||
src/pmpch.h
|
||||
)
|
||||
|
||||
set_target_properties(${RUNTIME_LIBRARY} PROPERTIES
|
||||
OUTPUT_NAME ${PROJECT_NAME}
|
||||
ARCHIVE_OUTPUT_NAME ${PROJECT_NAME}rd
|
||||
)
|
||||
|
||||
|
||||
|
||||
# alias
|
||||
add_library(Prism::static ALIAS Prism-static)
|
||||
add_library(Prism::shared ALIAS Prism-shared)
|
||||
add_library(Prism ALIAS Prism-shared)
|
||||
|
||||
add_library(Prism::Runtime ALIAS Prism-Runtime)
|
||||
|
||||
25
Prism/src/Prism/Asset/Asset.cpp
Normal file
25
Prism/src/Prism/Asset/Asset.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/26.
|
||||
//
|
||||
|
||||
#include "Asset.h"
|
||||
#include "Prism/Renderer/Texture.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
PhysicsMaterialAsset::PhysicsMaterialAsset(): StaticFriction(0), DynamicFriction(0), Bounciness(0)
|
||||
{
|
||||
Type = AssetType::PhysicsMaterial;
|
||||
}
|
||||
|
||||
PhysicsMaterialAsset::PhysicsMaterialAsset(const float staticFriction, const float dynamicFriction,
|
||||
const float bounciness): StaticFriction(staticFriction), DynamicFriction(dynamicFriction), Bounciness(bounciness)
|
||||
{
|
||||
Type = AssetType::PhysicsMaterial;
|
||||
}
|
||||
|
||||
PBRMaterialAsset::PBRMaterialAsset()
|
||||
{
|
||||
Type = AssetType::Material;
|
||||
}
|
||||
}
|
||||
@ -5,14 +5,20 @@
|
||||
#ifndef PRISM_ASSET_H
|
||||
#define PRISM_ASSET_H
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "Prism/Core/UUID.h"
|
||||
#include "Prism/Core/Ref.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
class Texture2D;
|
||||
class Shader;
|
||||
class MaterialInstance;
|
||||
|
||||
enum class AssetType
|
||||
{
|
||||
Scene = 0, Mesh, Texture, EnvMap, Audio, Script, PhysicsMaterial, Directory, Other, None
|
||||
Scene = 0, Mesh, Texture, EnvMap, Audio, Script, Material, PhysicsMaterial, Directory, Other, None
|
||||
};
|
||||
|
||||
using AssetHandle = UUID;
|
||||
@ -35,20 +41,17 @@ namespace Prism
|
||||
}
|
||||
};
|
||||
|
||||
class PRISM_API PhysicsMaterial : public Asset
|
||||
class PRISM_API PhysicsMaterialAsset : public Asset
|
||||
{
|
||||
public:
|
||||
float StaticFriction;
|
||||
float DynamicFriction;
|
||||
float Bounciness;
|
||||
|
||||
PhysicsMaterial() = default;
|
||||
PhysicsMaterialAsset();
|
||||
|
||||
PhysicsMaterialAsset(const float staticFriction, const float dynamicFriction, const float bounciness);
|
||||
|
||||
PhysicsMaterial(const float staticFriction, const float dynamicFriction, const float bounciness)
|
||||
: StaticFriction(staticFriction), DynamicFriction(dynamicFriction), Bounciness(bounciness)
|
||||
{
|
||||
Type = AssetType::PhysicsMaterial;
|
||||
}
|
||||
};
|
||||
|
||||
// Treating directories as assets simplifies the asset manager window rendering by a lot
|
||||
@ -63,6 +66,34 @@ namespace Prism
|
||||
}
|
||||
};
|
||||
|
||||
class PBRMaterialAsset : public Asset
|
||||
{
|
||||
public:
|
||||
PBRMaterialAsset();
|
||||
virtual ~PBRMaterialAsset() = default;
|
||||
// Albedo
|
||||
glm::vec3 AlbedoColor = glm::vec3(1.0f);
|
||||
float AlbedoTexToggle = 0.0f;
|
||||
Ref<Texture2D> AlbedoTexture;
|
||||
|
||||
// Normal
|
||||
float NormalTexToggle = 0.0f;
|
||||
Ref<Texture2D> NormalTexture;
|
||||
|
||||
// Metalness
|
||||
float Metalness = 0.8f;
|
||||
float MetalnessTexToggle = 0.0f;
|
||||
Ref<Texture2D> MetalnessTexture;
|
||||
|
||||
// Roughness
|
||||
float Roughness = 0.1f;
|
||||
float RoughnessTexToggle = 0.0f;
|
||||
Ref<Texture2D> RoughnessTexture;
|
||||
|
||||
bool IsDirty = true;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif //PRISM_ASSET_H
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
#include "Prism/Renderer/SceneRenderer.h"
|
||||
|
||||
#include "yaml-cpp/yaml.h"
|
||||
#include "Prism/Utilities/SerializeUtils.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
@ -40,15 +41,114 @@ namespace Prism
|
||||
{
|
||||
case Prism::AssetType::PhysicsMaterial:
|
||||
{
|
||||
Ref<PhysicsMaterial> material = Ref<PhysicsMaterial>(asset);
|
||||
out << YAML::Key << "StaticFriction" << material->StaticFriction;
|
||||
out << YAML::Key << "DynamicFriction" << material->DynamicFriction;
|
||||
out << YAML::Key << "Bounciness" << material->Bounciness;
|
||||
Ref<PhysicsMaterialAsset> physicsMaterial = Ref<PhysicsMaterialAsset>(asset);
|
||||
out << YAML::Key << "StaticFriction" << physicsMaterial->StaticFriction;
|
||||
out << YAML::Key << "DynamicFriction" << physicsMaterial->DynamicFriction;
|
||||
out << YAML::Key << "Bounciness" << physicsMaterial->Bounciness;
|
||||
break;
|
||||
}
|
||||
case AssetType::Material:
|
||||
{
|
||||
const auto& material = Ref<PBRMaterialAsset>(asset);
|
||||
|
||||
// Albedo
|
||||
out << YAML::Key << "Albedo";
|
||||
out << YAML::BeginMap;
|
||||
{
|
||||
out << YAML::Key << "Color" << YAML::Value << material->AlbedoColor;
|
||||
out << YAML::Key << "TexToggle" << YAML::Value << material->AlbedoTexToggle;
|
||||
|
||||
out << YAML::Key << "Texture";
|
||||
out << YAML::BeginMap;
|
||||
if (material->AlbedoTexture)
|
||||
{
|
||||
out << YAML::Key << "AssetHandle" << YAML::Value << material->AlbedoTexture->Handle;
|
||||
out << YAML::Key << "AssetPath" << YAML::Value << material->AlbedoTexture->FilePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
out << YAML::Key << "AssetHandle" << YAML::Value << 0;
|
||||
out << YAML::Key << "AssetPath" << YAML::Value << "";
|
||||
}
|
||||
out << YAML::EndMap;
|
||||
}
|
||||
out << YAML::EndMap;
|
||||
|
||||
// Normal
|
||||
out << YAML::Key << "Normal";
|
||||
out << YAML::BeginMap;
|
||||
{
|
||||
out << YAML::Key << "TexToggle" << YAML::Value << material->NormalTexToggle;
|
||||
|
||||
out << YAML::Key << "Texture";
|
||||
out << YAML::BeginMap;
|
||||
if (material->NormalTexture)
|
||||
{
|
||||
out << YAML::Key << "AssetHandle" << YAML::Value << material->NormalTexture->Handle;
|
||||
out << YAML::Key << "AssetPath" << YAML::Value << material->NormalTexture->FilePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
out << YAML::Key << "AssetHandle" << YAML::Value << 0;
|
||||
out << YAML::Key << "AssetPath" << YAML::Value << "";
|
||||
}
|
||||
out << YAML::EndMap;
|
||||
}
|
||||
out << YAML::EndMap;
|
||||
|
||||
// Metalness
|
||||
out << YAML::Key << "Metalness";
|
||||
out << YAML::BeginMap;
|
||||
{
|
||||
out << YAML::Key << "Value" << YAML::Value << material->Metalness; // 金属度数值
|
||||
out << YAML::Key << "TexToggle" << YAML::Value << material->MetalnessTexToggle;
|
||||
|
||||
out << YAML::Key << "Texture";
|
||||
out << YAML::BeginMap;
|
||||
if (material->MetalnessTexture)
|
||||
{
|
||||
out << YAML::Key << "AssetHandle" << YAML::Value << material->MetalnessTexture->Handle;
|
||||
out << YAML::Key << "AssetPath" << YAML::Value << material->MetalnessTexture->FilePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
out << YAML::Key << "AssetHandle" << YAML::Value << 0;
|
||||
out << YAML::Key << "AssetPath" << YAML::Value << "";
|
||||
}
|
||||
out << YAML::EndMap;
|
||||
}
|
||||
out << YAML::EndMap;
|
||||
|
||||
// Roughness
|
||||
out << YAML::Key << "Roughness";
|
||||
out << YAML::BeginMap;
|
||||
{
|
||||
out << YAML::Key << "Value" << YAML::Value << material->Roughness; // 粗糙度数值
|
||||
out << YAML::Key << "TexToggle" << YAML::Value << material->RoughnessTexToggle;
|
||||
|
||||
out << YAML::Key << "Texture";
|
||||
out << YAML::BeginMap;
|
||||
if (material->RoughnessTexture)
|
||||
{
|
||||
out << YAML::Key << "AssetHandle" << YAML::Value << material->RoughnessTexture->Handle;
|
||||
out << YAML::Key << "AssetPath" << YAML::Value << material->RoughnessTexture->FilePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
out << YAML::Key << "AssetHandle" << YAML::Value << 0;
|
||||
out << YAML::Key << "AssetPath" << YAML::Value << "";
|
||||
}
|
||||
out << YAML::EndMap;
|
||||
}
|
||||
out << YAML::EndMap;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out << YAML::EndMap;
|
||||
|
||||
PM_CORE_INFO("Save Asset change...");
|
||||
std::ofstream fout(asset->FilePath);
|
||||
fout << out.c_str();
|
||||
}
|
||||
@ -61,13 +161,125 @@ namespace Prism
|
||||
|
||||
YAML::Node data = YAML::Load(strStream.str());
|
||||
|
||||
if (asset->Type == AssetType::PhysicsMaterial)
|
||||
switch (asset->Type)
|
||||
{
|
||||
float staticFriction = data["StaticFriction"].as<float>();
|
||||
float dynamicFriction = data["DynamicFriction"].as<float>();
|
||||
float bounciness = data["Bounciness"].as<float>();
|
||||
case AssetType::PhysicsMaterial:
|
||||
{
|
||||
float staticFriction = data["StaticFriction"].as<float>();
|
||||
float dynamicFriction = data["DynamicFriction"].as<float>();
|
||||
float bounciness = data["Bounciness"].as<float>();
|
||||
|
||||
return Ref<PhysicsMaterial>::Create(staticFriction, dynamicFriction, bounciness);
|
||||
return Ref<PhysicsMaterialAsset>::Create(staticFriction, dynamicFriction, bounciness);
|
||||
}
|
||||
case AssetType::Material:
|
||||
{
|
||||
Ref<PBRMaterialAsset> material = Ref<PBRMaterialAsset>::Create();
|
||||
|
||||
// ==================== Albedo ====================
|
||||
if (data["Albedo"])
|
||||
{
|
||||
auto albedoNode = data["Albedo"];
|
||||
material->AlbedoColor = albedoNode["Color"].as<glm::vec3>();
|
||||
material->AlbedoTexToggle = albedoNode["TexToggle"].as<float>();
|
||||
|
||||
if (albedoNode["Texture"])
|
||||
{
|
||||
auto texNode = albedoNode["Texture"];
|
||||
UUID texHandle = 0;
|
||||
std::string texPath;
|
||||
if (texNode["AssetHandle"])
|
||||
texHandle = texNode["AssetHandle"].as<uint64_t>();
|
||||
if (texNode["AssetPath"])
|
||||
texPath = texNode["AssetPath"].as<std::string>();
|
||||
|
||||
if (texHandle != 0 && AssetsManager::IsAssetHandleValid(texHandle))
|
||||
material->AlbedoTexture = AssetsManager::GetAsset<Texture2D>(texHandle);
|
||||
else if (!texPath.empty())
|
||||
material->AlbedoTexture = Texture2D::Create(texPath);
|
||||
else
|
||||
material->AlbedoTexture = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== Normal ====================
|
||||
if (data["Normal"])
|
||||
{
|
||||
auto normalNode = data["Normal"];
|
||||
material->NormalTexToggle = normalNode["TexToggle"].as<float>();
|
||||
|
||||
if (normalNode["Texture"])
|
||||
{
|
||||
auto texNode = normalNode["Texture"];
|
||||
UUID texHandle = 0;
|
||||
std::string texPath;
|
||||
if (texNode["AssetHandle"])
|
||||
texHandle = texNode["AssetHandle"].as<uint64_t>();
|
||||
if (texNode["AssetPath"])
|
||||
texPath = texNode["AssetPath"].as<std::string>();
|
||||
|
||||
if (texHandle != 0 && AssetsManager::IsAssetHandleValid(texHandle))
|
||||
material->NormalTexture = AssetsManager::GetAsset<Texture2D>(texHandle);
|
||||
else if (!texPath.empty())
|
||||
material->NormalTexture = Texture2D::Create(texPath);
|
||||
else
|
||||
material->NormalTexture = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== Metalness ====================
|
||||
if (data["Metalness"])
|
||||
{
|
||||
auto metalNode = data["Metalness"];
|
||||
material->Metalness = metalNode["Value"].as<float>();
|
||||
material->MetalnessTexToggle = metalNode["TexToggle"].as<float>();
|
||||
|
||||
if (metalNode["Texture"])
|
||||
{
|
||||
auto texNode = metalNode["Texture"];
|
||||
UUID texHandle = 0;
|
||||
std::string texPath;
|
||||
if (texNode["AssetHandle"])
|
||||
texHandle = texNode["AssetHandle"].as<uint64_t>();
|
||||
if (texNode["AssetPath"])
|
||||
texPath = texNode["AssetPath"].as<std::string>();
|
||||
|
||||
if (texHandle != 0 && AssetsManager::IsAssetHandleValid(texHandle))
|
||||
material->MetalnessTexture = AssetsManager::GetAsset<Texture2D>(texHandle);
|
||||
else if (!texPath.empty())
|
||||
material->MetalnessTexture = Texture2D::Create(texPath);
|
||||
else
|
||||
material->MetalnessTexture = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== Roughness ====================
|
||||
if (data["Roughness"])
|
||||
{
|
||||
auto roughNode = data["Roughness"];
|
||||
material->Roughness = roughNode["Value"].as<float>();
|
||||
material->RoughnessTexToggle = roughNode["TexToggle"].as<float>();
|
||||
|
||||
if (roughNode["Texture"])
|
||||
{
|
||||
auto texNode = roughNode["Texture"];
|
||||
UUID texHandle = 0;
|
||||
std::string texPath;
|
||||
if (texNode["AssetHandle"])
|
||||
texHandle = texNode["AssetHandle"].as<uint64_t>();
|
||||
if (texNode["AssetPath"])
|
||||
texPath = texNode["AssetPath"].as<std::string>();
|
||||
|
||||
if (texHandle != 0 && AssetsManager::IsAssetHandleValid(texHandle))
|
||||
material->RoughnessTexture = AssetsManager::GetAsset<Texture2D>(texHandle);
|
||||
else if (!texPath.empty())
|
||||
material->RoughnessTexture = Texture2D::Create(texPath);
|
||||
else
|
||||
material->RoughnessTexture = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return material;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@ -106,8 +318,10 @@ namespace Prism
|
||||
asset->ParentDirectory = parentHandle;
|
||||
asset->IsDataLoaded = false;
|
||||
|
||||
#ifndef PRISM_RUNTIME
|
||||
if (!hasMeta)
|
||||
CreateMetaFile(asset);
|
||||
#endif
|
||||
|
||||
return asset;
|
||||
}
|
||||
@ -191,7 +405,9 @@ namespace Prism
|
||||
if (asset->FileName == "assets" && asset->Handle == 0)
|
||||
{
|
||||
asset->Handle = AssetHandle();
|
||||
#ifndef PRISM_RUNTIME
|
||||
CreateMetaFile(asset);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
@ -208,4 +424,17 @@ namespace Prism
|
||||
std::ofstream fout(asset->FilePath + ".meta");
|
||||
fout << out.c_str();
|
||||
}
|
||||
|
||||
void AssetSerializer::UpdateMetaFile(const Ref<Asset>& asset)
|
||||
{
|
||||
YAML::Emitter out;
|
||||
out << YAML::BeginMap;
|
||||
out << YAML::Key << "Asset" << YAML::Value << asset->Handle;
|
||||
out << YAML::Key << "FilePath" << YAML::Value << asset->FilePath;
|
||||
out << YAML::Key << "Type" << YAML::Value << (int)asset->Type;
|
||||
out << YAML::EndMap;
|
||||
|
||||
std::ofstream fout(asset->FilePath + ".meta");
|
||||
fout << out.c_str();
|
||||
}
|
||||
}
|
||||
@ -28,6 +28,7 @@ namespace Prism
|
||||
static Ref<Asset> DeserializeYAML(const Ref<Asset>& asset);
|
||||
static void LoadMetaData(Ref<Asset>& asset);
|
||||
static void CreateMetaFile(const Ref<Asset>& asset);
|
||||
static void UpdateMetaFile(const Ref<Asset>& asset);
|
||||
|
||||
private:
|
||||
friend class AssetsManager;
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
#include "AssetSerializer.h"
|
||||
#include "Prism/Core/Application.h"
|
||||
#include "Prism/Renderer/SceneEnvironment.h"
|
||||
#include "Prism/Utilities/StringUtils.h"
|
||||
|
||||
@ -26,9 +27,13 @@ namespace Prism
|
||||
s_Types["dae"] = AssetType::Mesh;
|
||||
s_Types["obj"] = AssetType::Mesh;
|
||||
s_Types["png"] = AssetType::Texture;
|
||||
s_Types["jpg"] = AssetType::Texture;
|
||||
s_Types["jpeg"] = AssetType::Texture;
|
||||
s_Types["bmp"] = AssetType::Texture;
|
||||
s_Types["tga"] = AssetType::Texture;
|
||||
s_Types["hdr"] = AssetType::EnvMap;
|
||||
s_Types["blend"] = AssetType::Mesh;
|
||||
s_Types["pmat"] = AssetType::Material;
|
||||
s_Types["hpm"] = AssetType::PhysicsMaterial;
|
||||
s_Types["wav"] = AssetType::Audio;
|
||||
s_Types["ogg"] = AssetType::Audio;
|
||||
@ -132,25 +137,6 @@ namespace Prism
|
||||
return assetHandle != 0 && s_LoadedAssets.find(assetHandle) != s_LoadedAssets.end();
|
||||
}
|
||||
|
||||
void AssetsManager::Rename(Ref<Asset>& asset, const std::string& newName)
|
||||
{
|
||||
const std::string newFilePath = FileSystem::Rename(asset->FilePath, newName);
|
||||
const std::string oldFilePath = asset->FilePath;
|
||||
asset->FilePath = newFilePath;
|
||||
asset->FileName = newName;
|
||||
|
||||
if (FileSystem::Exists(oldFilePath + ".meta"))
|
||||
{
|
||||
std::string metaFileName = oldFilePath;
|
||||
|
||||
if (!asset->Extension.empty())
|
||||
metaFileName += "." + asset->Extension;
|
||||
|
||||
FileSystem::PrismDeleteFile(oldFilePath + ".meta");
|
||||
AssetSerializer::CreateMetaFile(asset);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Ref<T> AssetsManager::GetAsset(AssetHandle assetHandle, bool loadData)
|
||||
{
|
||||
@ -169,7 +155,7 @@ namespace Prism
|
||||
|
||||
template PRISM_API Ref<Asset> AssetsManager::GetAsset(AssetHandle, bool);
|
||||
template PRISM_API Ref<Mesh> AssetsManager::GetAsset(AssetHandle, bool);
|
||||
template PRISM_API Ref<PhysicsMaterial> AssetsManager::GetAsset(AssetHandle, bool);
|
||||
template PRISM_API Ref<PhysicsMaterialAsset> AssetsManager::GetAsset(AssetHandle, bool);
|
||||
template PRISM_API Ref<Environment> AssetsManager::GetAsset(AssetHandle, bool);
|
||||
template PRISM_API Ref<Directory> AssetsManager::GetAsset(AssetHandle, bool);
|
||||
template PRISM_API Ref<Texture2D> AssetsManager::GetAsset(AssetHandle, bool);
|
||||
@ -180,35 +166,30 @@ namespace Prism
|
||||
return GetAsset<T>(GetAssetHandleFromFilePath(filepath), loadData);
|
||||
}
|
||||
|
||||
|
||||
template PRISM_API Ref<Asset> AssetsManager::GetAsset(const std::string&, bool);
|
||||
template PRISM_API Ref<Mesh> AssetsManager::GetAsset(const std::string&, bool);
|
||||
template PRISM_API Ref<PhysicsMaterial> AssetsManager::GetAsset(const std::string&, bool);
|
||||
template PRISM_API Ref<PhysicsMaterialAsset> AssetsManager::GetAsset(const std::string&, bool);
|
||||
template PRISM_API Ref<PBRMaterialAsset> AssetsManager::GetAsset(const std::string&, bool);
|
||||
template PRISM_API Ref<Environment> AssetsManager::GetAsset(const std::string&, bool);
|
||||
template PRISM_API Ref<Directory> AssetsManager::GetAsset(const std::string&, bool);
|
||||
template PRISM_API Ref<Texture2D> AssetsManager::GetAsset(const std::string&, bool);
|
||||
|
||||
|
||||
// temp
|
||||
Ref<PhysicsMaterial> AssetsManager::CreateAssetPhysicsMaterial(const std::string& filename, const AssetType type, const AssetHandle& directoryHandle, float v1, float v2, float v3)
|
||||
template <typename T>
|
||||
Ref<T> AssetsManager::TryGetAsset(const std::string& filepath, const bool loadData)
|
||||
{
|
||||
|
||||
const auto& directory = GetAsset<Directory>(directoryHandle);
|
||||
|
||||
Ref<PhysicsMaterial> asset = Ref<PhysicsMaterial>::Create(v1, v2, v3);
|
||||
asset->Type = type;
|
||||
asset->FilePath = directory->FilePath + "/" + filename;
|
||||
asset->FileName = Utils::RemoveExtension(Utils::GetFilename(asset->FilePath));
|
||||
asset->Extension = Utils::GetFilename(filename);
|
||||
asset->ParentDirectory = directoryHandle;
|
||||
asset->Handle = std::hash<std::string>()(asset->FilePath);
|
||||
asset->IsDataLoaded = true;
|
||||
s_LoadedAssets[asset->Handle] = asset;
|
||||
|
||||
AssetSerializer::SerializeAsset(asset);
|
||||
AssetSerializer::CreateMetaFile(asset);
|
||||
|
||||
return asset;
|
||||
AssetHandle assetHandle = GetAssetHandleFromFilePath(filepath);
|
||||
if (!assetHandle) return Ref<T>();
|
||||
return GetAsset<T>(assetHandle, loadData);
|
||||
}
|
||||
template PRISM_API Ref<Asset> AssetsManager::TryGetAsset(const std::string&, bool);
|
||||
template PRISM_API Ref<Mesh> AssetsManager::TryGetAsset(const std::string&, bool);
|
||||
template PRISM_API Ref<PhysicsMaterialAsset> AssetsManager::TryGetAsset(const std::string&, bool);
|
||||
template PRISM_API Ref<PBRMaterialAsset> AssetsManager::TryGetAsset(const std::string&, bool);
|
||||
template PRISM_API Ref<Environment> AssetsManager::TryGetAsset(const std::string&, bool);
|
||||
template PRISM_API Ref<Directory> AssetsManager::TryGetAsset(const std::string&, bool);
|
||||
template PRISM_API Ref<Texture2D> AssetsManager::TryGetAsset(const std::string&, bool);
|
||||
|
||||
|
||||
void AssetsManager::RemoveAsset(AssetHandle assetHandle)
|
||||
{
|
||||
@ -252,7 +233,8 @@ namespace Prism
|
||||
asset->FileName = Utils::RemoveExtension(Utils::GetFilename(asset->FilePath));
|
||||
asset->Extension = Utils::GetFilename(filename);
|
||||
asset->ParentDirectory = directoryHandle;
|
||||
asset->Handle = std::hash<std::string>()(asset->FilePath);
|
||||
asset->Handle = std::hash<std::string>()(asset->FilePath + std::to_string(Application::Get().GetTime()));
|
||||
|
||||
asset->IsDataLoaded = true;
|
||||
s_LoadedAssets[asset->Handle] = asset;
|
||||
|
||||
@ -262,6 +244,10 @@ namespace Prism
|
||||
return asset;
|
||||
}
|
||||
|
||||
template PRISM_API Ref<PhysicsMaterialAsset> AssetsManager::CreateAsset<PhysicsMaterialAsset, float, float, float>(const std::string&, AssetType, AssetHandle, float&&, float&&, float&&);
|
||||
template PRISM_API Ref<PhysicsMaterialAsset> AssetsManager::CreateAsset<PhysicsMaterialAsset>( const std::string&, AssetType, AssetHandle);
|
||||
|
||||
template PRISM_API Ref<PBRMaterialAsset> AssetsManager::CreateAsset<PBRMaterialAsset>( const std::string&, AssetType, AssetHandle);
|
||||
|
||||
|
||||
bool AssetsManager::IsAssetType(const AssetHandle assetHandle, const AssetType type)
|
||||
@ -307,7 +293,7 @@ namespace Prism
|
||||
{
|
||||
const std::string extension = Utils::GetExtension(filepath);
|
||||
if (extension == "meta")
|
||||
return Ref<Asset>();
|
||||
return {};
|
||||
|
||||
const AssetType type = AssetTypes::GetAssetTypeFromExtension(extension);
|
||||
Ref<Asset> asset = AssetSerializer::LoadAssetInfo(filepath, parentHandle, type);
|
||||
@ -368,7 +354,9 @@ namespace Prism
|
||||
ProcessDirectory(e.FilePath, parentHandle);
|
||||
else
|
||||
{
|
||||
Ref<Asset> asset = ImportAsset(e.FilePath, parentHandle);
|
||||
AssetHandle assetHandle = GetAssetHandleFromFilePath(e.FilePath);
|
||||
if (!assetHandle)
|
||||
ImportAsset(e.FilePath, parentHandle);
|
||||
}
|
||||
|
||||
}
|
||||
@ -383,41 +371,32 @@ namespace Prism
|
||||
break;
|
||||
case FileSystemAction::Rename:
|
||||
{
|
||||
Ref<Asset> asset;
|
||||
|
||||
for (auto it = s_LoadedAssets.begin(); it != s_LoadedAssets.end(); it++)
|
||||
Ref<Asset> asset = nullptr;
|
||||
{
|
||||
if (it->second->FileName == e.OldName)
|
||||
const std::string oldFilePath = Utils::ReplaceFilePathName(e.FilePath, e.OldName);
|
||||
for (auto& [handle, existingAsset] : s_LoadedAssets)
|
||||
{
|
||||
asset = it->second;
|
||||
if (existingAsset->FilePath == oldFilePath)
|
||||
{
|
||||
asset = existingAsset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (asset)
|
||||
{
|
||||
if (asset->Type != AssetTypes::GetAssetTypeFromExtension(Utils::GetExtension(e.FilePath)))
|
||||
{
|
||||
RemoveAsset(asset->Handle);
|
||||
FileSystem::PrismDeleteFile(asset->FilePath + ".meta");
|
||||
asset = ImportAsset(e.FilePath, parentHandle);
|
||||
}else
|
||||
{
|
||||
std::string oldMetaPath = asset->FilePath + ".meta";
|
||||
std::string newMetaPath = e.FilePath + ".meta";
|
||||
std::string extension = Utils::GetExtension(asset->FilePath);
|
||||
std::string oldMetaPath = asset->FilePath + ".meta";
|
||||
|
||||
std::error_code ec;
|
||||
std::filesystem::rename(oldMetaPath, newMetaPath, ec);
|
||||
if (ec)
|
||||
{
|
||||
PM_CORE_ERROR("Failed to rename meta file: {}", ec.message());
|
||||
}
|
||||
FileSystem::Rename(oldMetaPath, e.NewName + "." + extension);
|
||||
|
||||
asset->FilePath = e.FilePath;
|
||||
asset->FileName = e.NewName;
|
||||
}
|
||||
|
||||
}
|
||||
asset->FilePath = e.FilePath;
|
||||
asset->FileName = e.NewName;
|
||||
asset->Extension = extension;
|
||||
|
||||
AssetSerializer::UpdateMetaFile(asset);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FileSystemAction::Delete:
|
||||
|
||||
@ -45,9 +45,8 @@ namespace Prism
|
||||
static AssetHandle GetAssetHandleFromFilePath(const std::string& filepath);
|
||||
static bool IsAssetHandleValid(const AssetHandle& assetHandle);
|
||||
|
||||
static void Rename(Ref<Asset>& asset, const std::string& newName);
|
||||
|
||||
static Ref<PhysicsMaterial> CreateAssetPhysicsMaterial(const std::string& filename, AssetType type, const AssetHandle& directoryHandle, float v1, float v2, float v3);
|
||||
static Ref<PhysicsMaterialAsset> CreateAssetPhysicsMaterial(const std::string& filename, AssetType type, const AssetHandle& directoryHandle, float v1, float v2, float v3);
|
||||
|
||||
static void RemoveAsset(AssetHandle assetHandle);
|
||||
|
||||
@ -59,6 +58,8 @@ namespace Prism
|
||||
|
||||
template<typename T>
|
||||
static Ref<T> GetAsset(const std::string& filepath, bool loadData = true);
|
||||
template <class T>
|
||||
static Ref<T> TryGetAsset(const std::string& filepath, bool loadData = true);
|
||||
|
||||
static bool IsAssetType(AssetHandle assetHandle, AssetType type);
|
||||
|
||||
|
||||
@ -36,7 +36,6 @@ namespace Prism
|
||||
m_Window = std::unique_ptr<Window>(Window::Create(WindowProps{props.Name, props.Width, props.Height}));
|
||||
m_Window->SetEventCallback(BIND_EVENT_FN(OnEvent));
|
||||
m_Window->SetVSync(true);
|
||||
m_Window->Maximize();
|
||||
|
||||
m_ImGuiLayer = new ImGuiLayer("ImGui Layer");
|
||||
PushOverlay(m_ImGuiLayer);
|
||||
@ -107,6 +106,7 @@ namespace Prism
|
||||
for (Layer* layer : m_LayerStack)
|
||||
layer->OnImGuiRender();
|
||||
|
||||
/*
|
||||
ImGui::Begin("Renderer");
|
||||
const auto& caps = RendererAPI::GetCapabilities();
|
||||
ImGui::Text("Vendor: %s", caps.Vendor.c_str());
|
||||
@ -114,6 +114,7 @@ namespace Prism
|
||||
ImGui::Text("Version: %s", caps.Version.c_str());
|
||||
ImGui::Text("Frame Time: %.2fms\n", m_TimeStep.GetMilliseconds());
|
||||
ImGui::End();
|
||||
*/
|
||||
|
||||
m_ImGuiLayer->End();
|
||||
}
|
||||
|
||||
@ -12,7 +12,19 @@
|
||||
|
||||
extern Prism::Application* Prism::CreateApplication(CommandArgs args);
|
||||
|
||||
int main(int argc, char** argv)
|
||||
#ifdef PRISM_GUI
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
int MainEntry(int argc, char* argv[]);
|
||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
|
||||
{
|
||||
return MainEntry(__argc, __argv);
|
||||
}
|
||||
#endif
|
||||
int MainEntry(int argc, char** argv)
|
||||
#else
|
||||
int main(int argc, char** argv)
|
||||
#endif
|
||||
{
|
||||
//TODO: this will use other method to impl
|
||||
std::cout << std::filesystem::current_path() << std::endl;
|
||||
@ -33,6 +45,7 @@ int main(int argc, char** argv)
|
||||
Prism::ShutdownCore();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif //ENTRYPOINT_H
|
||||
|
||||
@ -45,6 +45,49 @@ namespace Prism {
|
||||
EVENT_CLASS_CATEGORY(EventCategoryApplication)
|
||||
};
|
||||
|
||||
class PRISM_API WindowFocusEvent : public Event
|
||||
{
|
||||
public:
|
||||
WindowFocusEvent() = default;
|
||||
|
||||
EVENT_CLASS_TYPE(WindowFocus)
|
||||
EVENT_CLASS_CATEGORY(EventCategoryApplication)
|
||||
};
|
||||
|
||||
class PRISM_API WindowLostFocusEvent : public Event
|
||||
{
|
||||
public:
|
||||
WindowLostFocusEvent() = default;
|
||||
|
||||
EVENT_CLASS_TYPE(WindowLostFocus)
|
||||
EVENT_CLASS_CATEGORY(EventCategoryApplication)
|
||||
};
|
||||
|
||||
class PRISM_API WindowMovedEvent : public Event
|
||||
{
|
||||
public:
|
||||
WindowMovedEvent(const int32_t x, const int32_t y)
|
||||
: m_X(x), m_Y(y)
|
||||
{
|
||||
}
|
||||
|
||||
inline int32_t GetX() const { return m_X; }
|
||||
inline int32_t GetY() const { return m_Y; }
|
||||
|
||||
std::string ToString() const override
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "WindowMovedEvent: " << m_X << ", " << m_Y;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
EVENT_CLASS_TYPE(WindowMoved)
|
||||
EVENT_CLASS_CATEGORY(EventCategoryApplication)
|
||||
|
||||
private:
|
||||
int32_t m_X, m_Y;
|
||||
};
|
||||
|
||||
class PRISM_API AppTickEvent : public Event
|
||||
{
|
||||
public:
|
||||
|
||||
@ -24,7 +24,6 @@ namespace Prism
|
||||
static std::shared_ptr<spdlog::logger> s_CoreLogger;
|
||||
static std::shared_ptr<spdlog::logger> s_ClientLogger;
|
||||
};
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define PM_CORE_TRACE(...) SPDLOG_LOGGER_TRACE(::Prism::Log::GetCoreLogger(), __VA_ARGS__)
|
||||
@ -41,6 +40,8 @@ namespace Prism
|
||||
#define PM_CORE_ERROR(...) ::Prism::Log::GetCoreLogger()->error(__VA_ARGS__)
|
||||
#define PM_CORE_FATAL(...) ::Prism::Log::GetCoreLogger()->critical(__VA_ARGS__)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define PM_CLIENT_TRACE(...) ::Prism::Log::GetClientLogger()->trace(__VA_ARGS__)
|
||||
|
||||
@ -19,6 +19,10 @@ namespace Prism
|
||||
AABB(const glm::vec3& min, const glm::vec3& max)
|
||||
: Min(min), Max(max) {}
|
||||
|
||||
bool IsValid() const {
|
||||
return Min.x <= Max.x && Min.y <= Max.y && Min.z <= Max.z;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -21,7 +21,7 @@ namespace Prism
|
||||
operator float() { return m_Time; }
|
||||
|
||||
private:
|
||||
float m_Time;
|
||||
float m_Time = 0.0f;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
#include "Ref.h"
|
||||
#include "Events/Event.h"
|
||||
#include "Prism/Core/Core.h"
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
|
||||
namespace Prism
|
||||
@ -39,8 +40,8 @@ namespace Prism
|
||||
virtual void SetEventCallback(const EventCallbackFn& callback) = 0;
|
||||
virtual uint32_t GetWidth() const = 0;
|
||||
virtual uint32_t GetHeight() const = 0;
|
||||
virtual std::pair<uint32_t, uint32_t> GetSize() const = 0;
|
||||
virtual std::pair<float, float> GetWindowPos() const = 0;
|
||||
virtual glm::ivec2 GetSize() const = 0;
|
||||
virtual glm::vec2 GetWindowPos() const = 0;
|
||||
|
||||
virtual void SetVSync(bool enable) = 0;
|
||||
virtual bool const IsVSync() const = 0;
|
||||
|
||||
@ -52,6 +52,7 @@ namespace Prism
|
||||
{
|
||||
RegisterEditor<TextureViewer>(AssetType::Texture);
|
||||
RegisterEditor<PhysicsMaterialEditor>(AssetType::PhysicsMaterial);
|
||||
RegisterEditor<PBRMaterialEditor>(AssetType::Material);
|
||||
}
|
||||
|
||||
void AssetEditorPanel::OnImGuiRender()
|
||||
@ -62,6 +63,11 @@ namespace Prism
|
||||
|
||||
void AssetEditorPanel::OpenEditor(const Ref<Asset>& asset)
|
||||
{
|
||||
if (!asset)
|
||||
{
|
||||
PM_CORE_WARN("asset is Invalid!");
|
||||
return;
|
||||
}
|
||||
if (s_Editors.find(asset->Type) == s_Editors.end())
|
||||
{
|
||||
PM_CORE_WARN("No editor registered for {0} assets", asset->Extension);
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#include "Prism/Core/Application.h"
|
||||
#include "Prism/Core/Input.h"
|
||||
#include "Prism/Core/Log.h"
|
||||
#include "Prism/Utilities/StringUtils.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
@ -32,7 +33,9 @@ namespace Prism
|
||||
m_AssetIconMap["blend"] = AssetsManager::GetAsset<Texture2D>("assets/editor/blend.png");
|
||||
|
||||
// TODO: get a logo for this project
|
||||
m_AssetIconMap["scene"] = Texture2D::Create("assets/editor/asset.png");
|
||||
m_AssetIconMap["scene"] = AssetsManager::GetAsset<Texture2D>("assets/editor/asset.png");
|
||||
|
||||
m_AssetIconMap["pmat"] = AssetsManager::GetAsset<Texture2D>("assets/editor/asset.png");
|
||||
|
||||
m_BackbtnTex = AssetsManager::GetAsset<Texture2D>("assets/editor/btn_back.png");
|
||||
m_FwrdbtnTex = AssetsManager::GetAsset<Texture2D>("assets/editor/btn_fwrd.png");
|
||||
@ -101,16 +104,56 @@ namespace Prism
|
||||
if (ImGui::MenuItem("Folder"))
|
||||
{
|
||||
PM_CORE_INFO("Creating Folder...");
|
||||
const bool created = FileSystem::CreateFolder(m_CurrentDirectory->FilePath + "/New Folder");
|
||||
if (created)
|
||||
const std::string filePath = m_CurrentDirectory->FilePath + "/new folder";
|
||||
FileSystem::CreateFolder(filePath);
|
||||
UpdateCurrentDirectory(m_CurrentDirHandle);
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("PBRMaterial"))
|
||||
{
|
||||
|
||||
const std::string fileName = "Material.pmat";
|
||||
const auto& directory = AssetsManager::GetAsset<Directory>(m_CurrentDirHandle);
|
||||
|
||||
// for hash UUID use
|
||||
std::string baseName = Utils::RemoveExtension(fileName);
|
||||
std::string extension = Utils::GetExtension(fileName, true);
|
||||
std::string finalFilename = fileName;
|
||||
std::string finalPath = directory->FilePath + "/" + finalFilename;
|
||||
|
||||
int counter = 1;
|
||||
while (AssetsManager::GetAssetHandleFromFilePath(finalPath) != 0)
|
||||
{
|
||||
UpdateCurrentDirectory(m_CurrentDirHandle);
|
||||
const auto& createdDirectory = AssetsManager::GetAsset<Directory>(AssetsManager::GetAssetHandleFromFilePath(m_CurrentDirectory->FilePath + "/New Folder"));
|
||||
m_SelectedAssets.Select(createdDirectory->Handle);
|
||||
memset(m_InputBuffer, 0, MAX_INPUT_BUFFER_LENGTH);
|
||||
memcpy(m_InputBuffer, createdDirectory->FileName.c_str(), createdDirectory->FileName.size());
|
||||
m_RenamingSelected = true;
|
||||
finalFilename = baseName + "_" + std::to_string(counter++) + extension;
|
||||
finalPath = directory->FilePath + "/" + finalFilename;
|
||||
}
|
||||
|
||||
|
||||
AssetsManager::CreateAsset<PBRMaterialAsset>(finalFilename, AssetType::Material, m_CurrentDirHandle);
|
||||
UpdateCurrentDirectory(m_CurrentDirHandle);
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Physics Material"))
|
||||
{
|
||||
const std::string fileName = "PhysicsMaterial.hpm";
|
||||
const auto& directory = AssetsManager::GetAsset<Directory>(m_CurrentDirHandle);
|
||||
|
||||
// for hash UUID use
|
||||
std::string baseName = Utils::RemoveExtension(fileName);
|
||||
std::string extension = Utils::GetExtension(fileName, true);
|
||||
std::string finalFilename = fileName;
|
||||
std::string finalPath = directory->FilePath + "/" + finalFilename;
|
||||
|
||||
int counter = 1;
|
||||
while (AssetsManager::GetAssetHandleFromFilePath(finalPath) != 0)
|
||||
{
|
||||
finalFilename = baseName + "_" + std::to_string(counter++) + extension;
|
||||
finalPath = directory->FilePath + "/" + finalFilename;
|
||||
}
|
||||
|
||||
|
||||
AssetsManager::CreateAsset<PhysicsMaterialAsset>(finalFilename, AssetType::PhysicsMaterial, m_CurrentDirHandle, 0.6f, 0.6f, 0.0f);
|
||||
UpdateCurrentDirectory(m_CurrentDirHandle);
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Scene"))
|
||||
@ -123,13 +166,23 @@ namespace Prism
|
||||
PM_CORE_INFO("Creating Script...");
|
||||
}
|
||||
|
||||
/*
|
||||
if (ImGui::MenuItem("Prefab"))
|
||||
{
|
||||
PM_CORE_INFO("Creating Prefab...");
|
||||
}
|
||||
*/
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem("Open In Explorer"))
|
||||
{
|
||||
Ref<Asset> asset = AssetsManager::GetAsset<Asset>(m_CurrentDirHandle);
|
||||
FileSystem::OpenInExplorer(asset->FilePath);
|
||||
}
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem("Import"))
|
||||
{
|
||||
@ -141,12 +194,6 @@ namespace Prism
|
||||
UpdateCurrentDirectory(m_CurrentDirHandle);
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Physics Material"))
|
||||
{
|
||||
// TODO: use template
|
||||
AssetsManager::CreateAssetPhysicsMaterial("New Physics Material.hpm", AssetType::PhysicsMaterial, m_CurrentDirHandle, 0.6f, 0.6f, 0.0f);
|
||||
UpdateCurrentDirectory(m_CurrentDirHandle);
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
@ -300,6 +347,12 @@ namespace Prism
|
||||
|
||||
if (ImGui::BeginPopupContextItem())
|
||||
{
|
||||
if (ImGui::MenuItem("Open In Explorer"))
|
||||
{
|
||||
FileSystem::OpenInExplorer(asset->FilePath);
|
||||
}
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem("Rename"))
|
||||
{
|
||||
m_SelectedAssets.Select(assetHandle);
|
||||
@ -523,7 +576,8 @@ namespace Prism
|
||||
if (ImGui::InputText("##rename_dummy", m_InputBuffer, MAX_INPUT_BUFFER_LENGTH, ImGuiInputTextFlags_EnterReturnsTrue))
|
||||
{
|
||||
PM_CORE_INFO("Renaming to {0}", m_InputBuffer);
|
||||
AssetsManager::Rename(asset, m_InputBuffer);
|
||||
const std::string filename = m_InputBuffer;
|
||||
FileSystem::Rename(asset->FilePath, filename);
|
||||
m_RenamingSelected = false;
|
||||
m_SelectedAssets.Clear();
|
||||
m_UpdateDirectoryNextFrame = true;
|
||||
|
||||
@ -13,6 +13,12 @@ namespace Prism
|
||||
PhysicsMaterialEditor::PhysicsMaterialEditor()
|
||||
: AssetEditor("Edit Physics Material") {}
|
||||
|
||||
void PhysicsMaterialEditor::SetAsset(const Ref<Asset>& asset)
|
||||
{
|
||||
if (m_Asset) AssetSerializer::SerializeAsset(m_Asset);
|
||||
m_Asset = static_cast<Ref<PhysicsMaterialAsset>>(asset);
|
||||
}
|
||||
|
||||
void PhysicsMaterialEditor::Render()
|
||||
{
|
||||
if (!m_Asset)
|
||||
@ -37,6 +43,12 @@ namespace Prism
|
||||
SetMaxSize(500, 1000);
|
||||
}
|
||||
|
||||
void TextureViewer::SetAsset(const Ref<Asset>& asset)
|
||||
{
|
||||
if (m_Asset) AssetSerializer::SerializeAsset(m_Asset);
|
||||
m_Asset = static_cast<Ref<Texture>>(asset);
|
||||
}
|
||||
|
||||
void TextureViewer::Render()
|
||||
{
|
||||
if (!m_Asset)
|
||||
@ -58,4 +70,214 @@ namespace Prism
|
||||
UI::EndPropertyGrid();
|
||||
}
|
||||
|
||||
PBRMaterialEditor::PBRMaterialEditor() : AssetEditor("Material Editor")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// 辅助函数:绘制纹理拖拽槽
|
||||
void DrawTextureSlot(Ref<Texture2D>& texture, const std::function<void(Ref<Texture2D>)>& onDrop)
|
||||
{
|
||||
static Ref<Texture2D> s_Checkerboard = nullptr;
|
||||
if (!s_Checkerboard)
|
||||
s_Checkerboard = AssetsManager::GetAsset<Texture2D>("assets/editor/Checkerboard.tga");
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(10, 10));
|
||||
ImGui::Image(texture ? (ImTextureID)(intptr_t)texture->GetRendererID() : (ImTextureID)(intptr_t)s_Checkerboard->GetRendererID(),
|
||||
ImVec2(64, 64));
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
if (const auto data = ImGui::AcceptDragDropPayload("asset_payload"))
|
||||
{
|
||||
AssetHandle assetHandle = *(AssetHandle*)data->Data;
|
||||
if (AssetsManager::IsAssetType(assetHandle, AssetType::Texture))
|
||||
{
|
||||
Ref<Texture2D> newTex = AssetsManager::GetAsset<Texture2D>(assetHandle);
|
||||
if (onDrop) onDrop(newTex);
|
||||
}
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
if (texture)
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
|
||||
ImGui::TextUnformatted(texture->GetPath().c_str());
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::Image((ImTextureID)(intptr_t)texture->GetRendererID(), ImVec2(384, 384));
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
/*
|
||||
// TODO: how to solve this
|
||||
if (ImGui::IsItemClicked(ImGuiMouseButton_Left))
|
||||
{
|
||||
std::string filename = FileSystem::OpenFileSelector("*.png;*.tga;*.jpg;*.jpeg");
|
||||
if (!filename.empty())
|
||||
{
|
||||
Ref<Texture2D> newTex = Texture2D::Create(filename);
|
||||
if (onDrop) onDrop(newTex);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PBRMaterialEditor::SetAsset(const Ref<Asset>& asset)
|
||||
{
|
||||
if (m_Asset)
|
||||
{
|
||||
if (m_Asset->Handle == asset->Handle) return;
|
||||
if (AssetsManager::IsAssetHandleValid(m_Asset->Handle))
|
||||
AssetSerializer::SerializeAsset(m_Asset);
|
||||
}
|
||||
m_Asset = static_cast<Ref<PBRMaterialAsset>>(asset);
|
||||
}
|
||||
|
||||
void PBRMaterialEditor::Render()
|
||||
{
|
||||
if (!m_Asset) return;
|
||||
|
||||
auto& material = m_Asset;
|
||||
|
||||
if (ImGui::BeginTabBar("MaterialProperties", ImGuiTabBarFlags_None))
|
||||
{
|
||||
// ==================== Parameters ====================
|
||||
if (ImGui::BeginTabItem("Parameters"))
|
||||
{
|
||||
ImGui::Spacing();
|
||||
|
||||
if (ImGui::CollapsingHeader("Albedo", ImGuiTreeNodeFlags_DefaultOpen))
|
||||
{
|
||||
ImGui::Indent();
|
||||
|
||||
if (ImGui::ColorEdit3("Color##Albedo", glm::value_ptr(material->AlbedoColor)))
|
||||
{
|
||||
m_Asset->IsDirty = true;
|
||||
}
|
||||
|
||||
bool useAlbedoMap = (material->AlbedoTexToggle > 0.5f);
|
||||
if (ImGui::Checkbox("Use Texture##Albedo", &useAlbedoMap))
|
||||
{
|
||||
material->AlbedoTexToggle = useAlbedoMap ? 1.0f : 0.0f;
|
||||
m_Asset->IsDirty = true;
|
||||
}
|
||||
|
||||
DrawTextureSlot(material->AlbedoTexture, [&](const Ref<Texture2D>& newTex) {
|
||||
material->AlbedoTexture = newTex;
|
||||
material->AlbedoTexToggle = true;
|
||||
m_Asset->IsDirty = true;
|
||||
});
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("Albedo Texture");
|
||||
|
||||
ImGui::Unindent();
|
||||
}
|
||||
|
||||
// Normal Map
|
||||
if (ImGui::CollapsingHeader("Normal Map", ImGuiTreeNodeFlags_DefaultOpen))
|
||||
{
|
||||
ImGui::Indent();
|
||||
|
||||
bool useNormalMap = (material->NormalTexToggle > 0.5f);
|
||||
if (ImGui::Checkbox("Use Texture##Normal", &useNormalMap))
|
||||
{
|
||||
material->NormalTexToggle = useNormalMap ? 1.0f : 0.0f;
|
||||
m_Asset->IsDirty = true;
|
||||
}
|
||||
|
||||
DrawTextureSlot(material->NormalTexture, [&](const Ref<Texture2D>& newTex) {
|
||||
material->NormalTexture = newTex;
|
||||
material->NormalTexToggle = true;
|
||||
m_Asset->IsDirty = true;
|
||||
});
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("Normal Texture");
|
||||
|
||||
ImGui::Unindent();
|
||||
}
|
||||
|
||||
// Metalness
|
||||
if (ImGui::CollapsingHeader("Metalness", ImGuiTreeNodeFlags_DefaultOpen))
|
||||
{
|
||||
ImGui::Indent();
|
||||
|
||||
if (ImGui::SliderFloat("Value##Metalness", &material->Metalness, 0.0f, 1.0f))
|
||||
{
|
||||
// 自动保存
|
||||
m_Asset->IsDirty = true;
|
||||
}
|
||||
|
||||
bool useMetalnessMap = (material->MetalnessTexToggle > 0.5f);
|
||||
if (ImGui::Checkbox("Use Texture##Metalness", &useMetalnessMap))
|
||||
{
|
||||
material->MetalnessTexToggle = useMetalnessMap ? 1.0f : 0.0f;
|
||||
m_Asset->IsDirty = true;
|
||||
}
|
||||
|
||||
DrawTextureSlot(material->MetalnessTexture, [&](const Ref<Texture2D>& newTex) {
|
||||
material->MetalnessTexture = newTex;
|
||||
material->MetalnessTexToggle = true;
|
||||
m_Asset->IsDirty = true;
|
||||
});
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("Metalness Texture");
|
||||
|
||||
ImGui::Unindent();
|
||||
}
|
||||
|
||||
// Roughness
|
||||
if (ImGui::CollapsingHeader("Roughness", ImGuiTreeNodeFlags_DefaultOpen))
|
||||
{
|
||||
ImGui::Indent();
|
||||
|
||||
if (ImGui::SliderFloat("Value##Roughness", &material->Roughness, 0.0f, 1.0f))
|
||||
{
|
||||
// 自动保存
|
||||
m_Asset->IsDirty = true;
|
||||
}
|
||||
|
||||
bool useRoughnessMap = (material->RoughnessTexToggle > 0.5f);
|
||||
if (ImGui::Checkbox("Use Texture##Roughness", &useRoughnessMap))
|
||||
{
|
||||
material->RoughnessTexToggle = useRoughnessMap ? 1.0f : 0.0f;
|
||||
m_Asset->IsDirty = true;
|
||||
}
|
||||
|
||||
DrawTextureSlot(material->RoughnessTexture, [&](const Ref<Texture2D>& newTex) {
|
||||
material->RoughnessTexture = newTex;
|
||||
material->RoughnessTexToggle = true;
|
||||
m_Asset->IsDirty = true;
|
||||
});
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("Roughness Texture");
|
||||
|
||||
ImGui::Unindent();
|
||||
}
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
// ==================== 预览 ====================
|
||||
if (ImGui::BeginTabItem("Preview"))
|
||||
{
|
||||
// 简单显示纹理预览
|
||||
if (material->AlbedoTexture)
|
||||
{
|
||||
ImGui::Text("Albedo Preview");
|
||||
ImGui::Image((ImTextureID)(intptr_t)material->AlbedoTexture->GetRendererID(), ImVec2(128, 128));
|
||||
}
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -15,14 +15,14 @@ namespace Prism
|
||||
public:
|
||||
PhysicsMaterialEditor();
|
||||
|
||||
virtual Ref<Asset> GetAsset() override { return m_Asset; }
|
||||
virtual void SetAsset(const Ref<Asset>& asset) override { m_Asset = (Ref<PhysicsMaterial>)asset; }
|
||||
Ref<Asset> GetAsset() override { return m_Asset; }
|
||||
void SetAsset(const Ref<Asset>& asset) override;
|
||||
|
||||
private:
|
||||
virtual void Render() override;
|
||||
void Render() override;
|
||||
|
||||
private:
|
||||
Ref<PhysicsMaterial> m_Asset;
|
||||
Ref<PhysicsMaterialAsset> m_Asset;
|
||||
};
|
||||
|
||||
class TextureViewer : public AssetEditor
|
||||
@ -30,16 +30,31 @@ namespace Prism
|
||||
public:
|
||||
TextureViewer();
|
||||
|
||||
virtual Ref<Asset> GetAsset() override { return m_Asset; }
|
||||
virtual void SetAsset(const Ref<Asset>& asset) override { m_Asset = static_cast<Ref<Texture>>(asset); }
|
||||
Ref<Asset> GetAsset() override { return m_Asset; }
|
||||
void SetAsset(const Ref<Asset>& asset) override;
|
||||
|
||||
private:
|
||||
virtual void Render() override;
|
||||
void Render() override;
|
||||
|
||||
private:
|
||||
Ref<Texture> m_Asset;
|
||||
};
|
||||
|
||||
class PBRMaterialEditor : public AssetEditor
|
||||
{
|
||||
public:
|
||||
PBRMaterialEditor();
|
||||
|
||||
Ref<Asset> GetAsset() override { return m_Asset; }
|
||||
void SetAsset(const Ref<Asset>& asset) override;
|
||||
|
||||
private:
|
||||
void Render() override;
|
||||
|
||||
private:
|
||||
Ref<PBRMaterialAsset> m_Asset;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //PRISM_DEFAULTASSETEDITORS_H
|
||||
@ -14,6 +14,7 @@
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
#include <glm/gtx/matrix_decompose.hpp>
|
||||
|
||||
#include "AssetEditorPanel.h"
|
||||
#include "Prism/Core/Application.h"
|
||||
#include "Prism/Core/Math/Math.h"
|
||||
#include "Prism/Physics/PhysicsLayer.h"
|
||||
@ -547,7 +548,7 @@ namespace Prism
|
||||
template<typename T, typename UIFunction>
|
||||
static void DrawComponent(const std::string& name, Entity entity, UIFunction uiFunction)
|
||||
{
|
||||
const ImGuiTreeNodeFlags treeNodeFlags = ImGuiTreeNodeFlags_DefaultOpen |
|
||||
constexpr ImGuiTreeNodeFlags treeNodeFlags = ImGuiTreeNodeFlags_DefaultOpen |
|
||||
ImGuiTreeNodeFlags_Framed |
|
||||
ImGuiTreeNodeFlags_SpanAvailWidth |
|
||||
ImGuiTreeNodeFlags_AllowOverlap |
|
||||
@ -886,13 +887,50 @@ namespace Prism
|
||||
DrawComponent<MeshComponent>("Mesh", entity, [](MeshComponent& meshComponent) {
|
||||
|
||||
UI::BeginPropertyGrid();
|
||||
UI::PropertyAssetReference("Mesh", meshComponent.Mesh, AssetType::Mesh);
|
||||
// UI::Property("AnimationPlaying", meshComponent.Mesh->m_AnimationPlaying);
|
||||
// UI::Property("TimeMultiple", meshComponent.Mesh->m_TimeMultiplier);
|
||||
// UI::Property("AnimationTime", meshComponent.Mesh->m_AnimationTime);
|
||||
// UI::Property("WorldTime", meshComponent.Mesh->m_WorldTime);
|
||||
|
||||
if (UI::PropertyAssetReference("Mesh", meshComponent.Mesh, AssetType::Mesh))
|
||||
{
|
||||
meshComponent.MaterialInstances.clear();
|
||||
meshComponent.MaterialDescs.clear();
|
||||
const auto& materialInstances = meshComponent.Mesh->GetMaterials();
|
||||
for (uint32_t i = 0; i < materialInstances.size(); i++)
|
||||
{
|
||||
Ref<MaterialInstance> materialInstance = MaterialInstance::Copy(materialInstances[i]);
|
||||
meshComponent.MaterialInstances.push_back(materialInstance);
|
||||
}
|
||||
meshComponent.MaterialDescs.resize(materialInstances.size());
|
||||
}
|
||||
UI::EndPropertyGrid();
|
||||
|
||||
for (auto i = 0; i < meshComponent.MaterialDescs.size(); i++)
|
||||
{
|
||||
|
||||
// TODO: 这里通过 MaterialDesc进行存储信息,然后修改后由此处更新MaterialInstances,同时还缺少一个在MeshComponent中MaterialDesc的序列化
|
||||
if (UI::BeginTreeNode((std::string("Slot ") + std::to_string(i)).c_str()))
|
||||
{
|
||||
UI::BeginPropertyGrid();
|
||||
if (meshComponent.MaterialDescs[i])
|
||||
{
|
||||
if (ImGui::Button("X"))
|
||||
{
|
||||
meshComponent.MaterialDescs[i] = nullptr;
|
||||
meshComponent.UpdateMaterials(i);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
}
|
||||
|
||||
if (ImGui::Button("Edit")) AssetEditorPanel::OpenEditor(meshComponent.MaterialDescs[i]);
|
||||
ImGui::SameLine();
|
||||
if (UI::PropertyAssetReference(meshComponent.MaterialInstances[i]->GetName().c_str(), meshComponent.MaterialDescs[i], AssetType::Material))
|
||||
{
|
||||
meshComponent.UpdateMaterials(-1, true);
|
||||
}
|
||||
UI::EndPropertyGrid();
|
||||
|
||||
UI::EndTreeNode();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
DrawComponent<AnimationComponent>("AnimatorController", entity, [this](AnimationComponent& animatorComponent)
|
||||
@ -1090,18 +1128,33 @@ namespace Prism
|
||||
});
|
||||
|
||||
DrawComponent<ScriptComponent>("Script", entity, [=](ScriptComponent& scriptComponent) mutable {
|
||||
UI::BeginPropertyGrid();
|
||||
const std::string oldName = scriptComponent.ModuleName;
|
||||
if (UI::Property("Module Name", scriptComponent.ModuleName, !ScriptEngine::ModuleExists(scriptComponent.ModuleName))) // TODO: no live edit
|
||||
{
|
||||
// Shutdown old script
|
||||
if (ScriptEngine::ModuleExists(oldName))
|
||||
ScriptEngine::ShutdownScriptEntity(entity, oldName);
|
||||
|
||||
if (ScriptEngine::ModuleExists(scriptComponent.ModuleName))
|
||||
ScriptEngine::InitScriptEntity(entity);
|
||||
const std::string oldName = scriptComponent.ModuleName;
|
||||
|
||||
if (ImGui::BeginCombo("Module Name", scriptComponent.ModuleName.c_str()))
|
||||
{
|
||||
const auto& availableScripts = ScriptEngine::GetAvailableScripts();
|
||||
|
||||
for (const auto& script : availableScripts)
|
||||
{
|
||||
const bool isSelected = (scriptComponent.ModuleName == script);
|
||||
if (ImGui::Selectable(script.c_str(), isSelected))
|
||||
{
|
||||
// 切换逻辑
|
||||
if (ScriptEngine::ModuleExists(oldName))
|
||||
ScriptEngine::ShutdownScriptEntity(entity, oldName);
|
||||
scriptComponent.ModuleName = script;
|
||||
if (ScriptEngine::ModuleExists(scriptComponent.ModuleName))
|
||||
ScriptEngine::InitScriptEntity(entity);
|
||||
}
|
||||
if (isSelected)
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
UI::BeginPropertyGrid();
|
||||
|
||||
// Public Fields
|
||||
if (ScriptEngine::ModuleExists(scriptComponent.ModuleName))
|
||||
{
|
||||
@ -1345,7 +1398,7 @@ namespace Prism
|
||||
|
||||
if (UI::Property("Size", bcc.Size))
|
||||
{
|
||||
bcc.DebugMesh = MeshFactory::CreateBox(bcc.Size);
|
||||
bcc.DebugMesh = MeshFactory::CreateBox(bcc.Size * 2.0f);
|
||||
}
|
||||
|
||||
UI::Property("IsTrigger", bcc.IsTrigger);
|
||||
|
||||
@ -85,7 +85,8 @@ namespace Prism
|
||||
|
||||
void Physics3D::Simulate(const TimeStep ts)
|
||||
{
|
||||
|
||||
auto& time = s_SimulationTime;
|
||||
auto& sett = s_Settings;
|
||||
// TODO: Allow projects to control the fixed step amount
|
||||
s_SimulationTime += ts.GetMilliseconds();
|
||||
|
||||
@ -106,7 +107,7 @@ namespace Prism
|
||||
|
||||
void Physics3D::DestroyScene()
|
||||
{
|
||||
PM_CORE_ASSERT(s_Scene);
|
||||
if (!s_Scene) return;
|
||||
|
||||
s_Actors.clear();
|
||||
s_Scene->release();
|
||||
|
||||
@ -11,6 +11,8 @@
|
||||
#include "Prism/Script/ScriptEngine.h"
|
||||
#include <glm/gtx/compatibility.hpp>
|
||||
|
||||
#include "glm/gtx/euler_angles.hpp"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
PhysicsActor::PhysicsActor(Entity entity)
|
||||
@ -177,15 +179,24 @@ namespace Prism
|
||||
Ref<Scene> scene = Scene::GetScene(m_Entity.GetSceneUUID());
|
||||
glm::mat4 transform = scene->GetTransformRelativeToParent(m_Entity);
|
||||
|
||||
if (m_RigidBody.BodyType == RigidBodyComponent::Type::Static)
|
||||
{
|
||||
m_ActorInternal = physics.createRigidStatic(ToPhysXTransform(transform));
|
||||
}
|
||||
else
|
||||
glm::vec3 translation, rotationEuler, scale;
|
||||
Math::DecomposeTransform(transform, translation, rotationEuler, scale);
|
||||
|
||||
const glm::mat4 rotMat = glm::eulerAngleYXZ(rotationEuler.y, rotationEuler.x, rotationEuler.z);
|
||||
const glm::quat rotationQuat = glm::quat_cast(rotMat);
|
||||
|
||||
physx::PxTransform pxTransform(ToPhysXVector(translation), ToPhysXQuat(rotationQuat));
|
||||
|
||||
// PhysicsActor::Initialize 中
|
||||
m_WorldScale = scale;
|
||||
|
||||
|
||||
if (IsDynamic())
|
||||
{
|
||||
|
||||
const PhysicsSettings& settings = Physics3D::GetSettings();
|
||||
|
||||
physx::PxRigidDynamic* actor = physics.createRigidDynamic(ToPhysXTransform(transform));
|
||||
physx::PxRigidDynamic* actor = physics.createRigidDynamic(pxTransform);
|
||||
actor->setLinearDamping(m_RigidBody.LinearDrag);
|
||||
actor->setAngularDamping(m_RigidBody.AngularDrag);
|
||||
actor->setRigidBodyFlag(physx::PxRigidBodyFlag::eKINEMATIC, m_RigidBody.IsKinematic);
|
||||
@ -198,15 +209,26 @@ namespace Prism
|
||||
actor->setActorFlag(physx::PxActorFlag::eDISABLE_GRAVITY, m_RigidBody.DisableGravity);
|
||||
actor->setSolverIterationCounts(settings.SolverIterations, settings.SolverVelocityIterations);
|
||||
|
||||
physx::PxRigidBodyExt::setMassAndUpdateInertia(*actor, m_RigidBody.Mass);
|
||||
m_ActorInternal = actor;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ActorInternal = physics.createRigidStatic(pxTransform);
|
||||
}
|
||||
|
||||
// Add Collider
|
||||
if (m_Entity.HasComponent<BoxColliderComponent>()) PhysicsWrappers::AddBoxCollider(*this);
|
||||
if (m_Entity.HasComponent<SphereColliderComponent>()) PhysicsWrappers::AddSphereCollider(*this);
|
||||
if (m_Entity.HasComponent<CapsuleColliderComponent>()) PhysicsWrappers::AddCapsuleCollider(*this);
|
||||
if (m_Entity.HasComponent<MeshColliderComponent>()) PhysicsWrappers::AddMeshCollider(*this);
|
||||
|
||||
|
||||
if (IsDynamic())
|
||||
{
|
||||
auto* dynamicActor = static_cast<physx::PxRigidDynamic*>(m_ActorInternal);
|
||||
physx::PxRigidBodyExt::setMassAndUpdateInertia(*dynamicActor, m_RigidBody.Mass);
|
||||
}
|
||||
|
||||
if (!PhysicsLayerManager::IsLayerValid(m_RigidBody.Layer))
|
||||
m_RigidBody.Layer = 0;
|
||||
|
||||
|
||||
@ -49,6 +49,8 @@ namespace Prism
|
||||
|
||||
Entity& GetEntity() { return m_Entity; }
|
||||
|
||||
glm::vec3 GetWorldScale() const { return m_WorldScale; }
|
||||
|
||||
private:
|
||||
void Initialize();
|
||||
void Spawn() const;
|
||||
@ -64,6 +66,8 @@ namespace Prism
|
||||
|
||||
physx::PxRigidActor* m_ActorInternal;
|
||||
|
||||
glm::vec3 m_WorldScale = glm::vec3(1.0f);
|
||||
|
||||
friend class Physics3D;
|
||||
friend class PhysicsWrappers;
|
||||
|
||||
|
||||
@ -36,12 +36,12 @@ namespace Prism
|
||||
|
||||
physx::PxVec3 ToPhysXVector(const glm::vec3& vector)
|
||||
{
|
||||
return *(physx::PxVec3*)&vector;
|
||||
return physx::PxVec3(vector.x, vector.y, vector.z);
|
||||
}
|
||||
|
||||
physx::PxVec4 ToPhysXVector(const glm::vec4& vector)
|
||||
{
|
||||
return *(physx::PxVec4*)&vector;
|
||||
return physx::PxVec4(vector.x, vector.y, vector.z, vector.w);
|
||||
}
|
||||
|
||||
physx::PxQuat ToPhysXQuat(const glm::quat& quat)
|
||||
|
||||
@ -184,16 +184,11 @@ namespace Prism
|
||||
auto& collider = actor.m_Entity.GetComponent<BoxColliderComponent>();
|
||||
|
||||
if (!collider.Material)
|
||||
collider.Material = Ref<PhysicsMaterial>::Create(0.6F, 0.6F, 0.0f);
|
||||
collider.Material = Ref<PhysicsMaterialAsset>::Create(0.6F, 0.6F, 0.0f);
|
||||
|
||||
const glm::vec3 scale = actor.m_Entity.Transform().Scale;
|
||||
glm::vec3 colliderSize = collider.Size;
|
||||
glm::vec3 colliderSize = collider.Size * actor.GetWorldScale();
|
||||
|
||||
if (scale.x != 0.0f) colliderSize.x *= scale.x;
|
||||
if (scale.y != 0.0f) colliderSize.y *= scale.y;
|
||||
if (scale.z != 0.0f) colliderSize.z *= scale.z;
|
||||
|
||||
const auto boxGeometry = physx::PxBoxGeometry(colliderSize.x / 2.0f, colliderSize.y / 2.0f, colliderSize.z / 2.0f);
|
||||
const auto boxGeometry = physx::PxBoxGeometry(colliderSize.x, colliderSize.y, colliderSize.z);
|
||||
const physx::PxMaterial* material = s_Physics->createMaterial(collider.Material->StaticFriction, collider.Material->DynamicFriction, collider.Material->Bounciness);
|
||||
physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(*actor.m_ActorInternal, boxGeometry, *material);
|
||||
|
||||
@ -207,7 +202,7 @@ namespace Prism
|
||||
{
|
||||
auto& collider = actor.m_Entity.GetComponent<SphereColliderComponent>();
|
||||
if (!collider.Material)
|
||||
collider.Material = Ref<PhysicsMaterial>::Create(0.6F, 0.6F, 0.0f);
|
||||
collider.Material = Ref<PhysicsMaterialAsset>::Create(0.6F, 0.6F, 0.0f);
|
||||
|
||||
const glm::vec3 scale = actor.m_Entity.Transform().Scale;
|
||||
float colliderRadius = collider.Radius;
|
||||
@ -227,7 +222,7 @@ namespace Prism
|
||||
{
|
||||
auto& collider = actor.m_Entity.GetComponent<CapsuleColliderComponent>();
|
||||
if (!collider.Material)
|
||||
collider.Material = Ref<PhysicsMaterial>::Create(0.6F, 0.6F, 0.0f);
|
||||
collider.Material = Ref<PhysicsMaterialAsset>::Create(0.6F, 0.6F, 0.0f);
|
||||
|
||||
const glm::vec3 scale = actor.m_Entity.Transform().Scale;
|
||||
float colliderRadius = collider.Radius;
|
||||
@ -255,7 +250,7 @@ namespace Prism
|
||||
{
|
||||
auto& collider = actor.m_Entity.GetComponent<MeshColliderComponent>();
|
||||
if (!collider.Material)
|
||||
collider.Material = Ref<PhysicsMaterial>::Create(0.6f, 0.6f, 0.0f);
|
||||
collider.Material = Ref<PhysicsMaterialAsset>::Create(0.6f, 0.6f, 0.0f);
|
||||
|
||||
glm::vec3 scale = actor.m_Entity.Transform().Scale;
|
||||
physx::PxMaterial* material = s_Physics->createMaterial(collider.Material->StaticFriction, collider.Material->DynamicFriction, collider.Material->Bounciness);
|
||||
|
||||
426
Prism/src/Prism/Platform/OpenGL/OpenGLCommandBuffer.cpp
Normal file
426
Prism/src/Prism/Platform/OpenGL/OpenGLCommandBuffer.cpp
Normal file
@ -0,0 +1,426 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/31.
|
||||
//
|
||||
|
||||
#include "OpenGLCommandBuffer.h"
|
||||
|
||||
#include "Prism/Renderer/Texture.h"
|
||||
#include "Prism/Renderer/StorageBuffer.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
GLenum OpenGLCommandBuffer::MapCompareOp(const CompareOp Option)
|
||||
{
|
||||
switch (Option) {
|
||||
case CompareOp::Never: return GL_NEVER;
|
||||
case CompareOp::Less: return GL_LESS;
|
||||
case CompareOp::Equal: return GL_EQUAL;
|
||||
case CompareOp::LessEqual: return GL_LEQUAL;
|
||||
case CompareOp::Greater: return GL_GREATER;
|
||||
case CompareOp::NotEqual: return GL_NOTEQUAL;
|
||||
case CompareOp::GreaterEqual: return GL_GEQUAL;
|
||||
case CompareOp::Always: return GL_ALWAYS;
|
||||
}
|
||||
return GL_ALWAYS;
|
||||
}
|
||||
|
||||
GLenum OpenGLCommandBuffer::MapStencilOp(const StencilOp Option)
|
||||
{
|
||||
switch (Option) {
|
||||
case StencilOp::Keep: return GL_KEEP;
|
||||
case StencilOp::Zero: return GL_ZERO;
|
||||
case StencilOp::Replace: return GL_REPLACE;
|
||||
case StencilOp::Incr: return GL_INCR;
|
||||
case StencilOp::Decr: return GL_DECR;
|
||||
case StencilOp::Invert: return GL_INVERT;
|
||||
case StencilOp::IncrWrap: return GL_INCR_WRAP;
|
||||
case StencilOp::DecrWrap: return GL_DECR_WRAP;
|
||||
}
|
||||
return GL_KEEP;
|
||||
}
|
||||
|
||||
GLenum OpenGLCommandBuffer::MapCullMode(CullMode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case CullMode::None: return GL_NONE;
|
||||
case CullMode::Front: return GL_FRONT;
|
||||
case CullMode::Back: return GL_BACK;
|
||||
}
|
||||
return GL_BACK;
|
||||
}
|
||||
|
||||
GLenum OpenGLCommandBuffer::MapPolygonMode(PolygonMode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case PolygonMode::Fill: return GL_FILL;
|
||||
case PolygonMode::Line: return GL_LINE;
|
||||
case PolygonMode::Point: return GL_POINT;
|
||||
}
|
||||
return GL_FILL;
|
||||
}
|
||||
|
||||
GLenum OpenGLCommandBuffer::MapPrimitiveType(PrimitiveType type)
|
||||
{
|
||||
switch (type) {
|
||||
case PrimitiveType::Triangles: return GL_TRIANGLES;
|
||||
case PrimitiveType::Lines: return GL_LINES;
|
||||
case PrimitiveType::Points: return GL_POINTS;
|
||||
}
|
||||
return GL_TRIANGLES;
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetViewport(const uint32_t x, const uint32_t y, const uint32_t width, const uint32_t height) const
|
||||
{
|
||||
glViewport(x, y, width, height);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetScissor(const uint32_t x, const uint32_t y, const uint32_t width, const uint32_t height) const
|
||||
{
|
||||
glScissor(x, y, width, height);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetDepthTest(const bool enable) const
|
||||
{
|
||||
if (enable) glEnable(GL_DEPTH_TEST);
|
||||
else glDisable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetDepthFunc(const CompareOp func) const
|
||||
{
|
||||
glDepthFunc(MapCompareOp(func));
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetStencilTest(const bool enable) const
|
||||
{
|
||||
if (enable) glEnable(GL_STENCIL_TEST);
|
||||
else glDisable(GL_STENCIL_TEST);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetStencilOp(const StencilOp fail, const StencilOp zFail, const StencilOp zPass) const
|
||||
{
|
||||
glStencilOp(MapStencilOp(fail), MapStencilOp(zFail), MapStencilOp(zPass));
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetStencilMask(uint32_t mask) const
|
||||
{
|
||||
glStencilMask(mask);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetCullMode(CullMode mode) const
|
||||
{
|
||||
if (mode == CullMode::None) glDisable(GL_CULL_FACE);
|
||||
else {
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(MapCullMode(mode));
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetPolygonMode(PolygonMode mode) const
|
||||
{
|
||||
glPolygonMode(GL_FRONT_AND_BACK, MapPolygonMode(mode));
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetLineWidth(const float width) const
|
||||
{
|
||||
glLineWidth(width);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetLineThickness(const float thickness) const
|
||||
{
|
||||
glLineWidth(thickness);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetPointSize(float size) const
|
||||
{
|
||||
glPointSize(size);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::BindFramebuffer(const RendererID rendererId) const
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, rendererId);
|
||||
}
|
||||
|
||||
GLuint FramebufferTargetToOpenGL(const FramebufferTarget target)
|
||||
{
|
||||
switch (target)
|
||||
{
|
||||
case FramebufferTarget::Draw: return GL_DRAW_FRAMEBUFFER;
|
||||
case FramebufferTarget::Read: return GL_READ_FRAMEBUFFER;
|
||||
case FramebufferTarget::Both: return GL_FRAMEBUFFER;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::BindFramebuffer(const FramebufferTarget target, const RendererID rendererId) const
|
||||
{
|
||||
glBindFramebuffer(FramebufferTargetToOpenGL(target), rendererId);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::BindTexture(const uint32_t slot, const uint32_t textureID) const
|
||||
{
|
||||
glBindTextureUnit(slot, textureID);
|
||||
}
|
||||
|
||||
static GLenum MapAccessMode(AccessMode mode) {
|
||||
switch (mode) {
|
||||
case AccessMode::ReadOnly: return GL_READ_ONLY;
|
||||
case AccessMode::WriteOnly: return GL_WRITE_ONLY;
|
||||
case AccessMode::ReadWrite: return GL_READ_WRITE;
|
||||
}
|
||||
return GL_READ_WRITE;
|
||||
}
|
||||
|
||||
static GLenum MapTextureFormat(TextureFormat format) {
|
||||
switch (format)
|
||||
{
|
||||
case TextureFormat::RGB: return GL_RGB8;
|
||||
case TextureFormat::RGBA: return GL_RGBA8;
|
||||
case TextureFormat::RGBA16F: return GL_RGBA16F;
|
||||
}
|
||||
return GL_RGBA8;
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::BindImageTexture(uint32_t unit, uint32_t textureID, int32_t level, bool layered, int32_t layer, AccessMode access, TextureFormat format) const
|
||||
{
|
||||
const GLenum glAccess = MapAccessMode(access); // 将 AccessMode 转为 GL_READ_ONLY, GL_WRITE_ONLY, GL_READ_WRITE
|
||||
const GLenum glFormat = MapTextureFormat(format); // 将 TextureFormat 转为 GL_RGBA16F 等内部格式
|
||||
glBindImageTexture(unit, textureID, level, layered ? GL_TRUE : GL_FALSE, layer, glAccess, glFormat);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::BindTextureUnit(uint32_t i, RendererID rendererId) const
|
||||
{
|
||||
glBindTextureUnit(i, rendererId);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::BindSampler(uint32_t slot, uint32_t samplerID) const
|
||||
{
|
||||
glBindSampler(slot, samplerID);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetDrawBuffer(const uint32_t attachment) const
|
||||
{
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT0 + attachment);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetReadBuffer(const uint32_t attachment) const
|
||||
{
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0 + attachment);
|
||||
}
|
||||
|
||||
GLuint BufferFormatToOpenGL(const BufferFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
case BufferFormat::R32UI: return GL_R32UI;
|
||||
case BufferFormat::RGB16F: return GL_RGB16F;
|
||||
}
|
||||
return GL_RGB16F;
|
||||
}
|
||||
|
||||
GLuint PixelFormatToOpenGL(const PixelFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
case PixelFormat::RED: return GL_RED;
|
||||
case PixelFormat::RGBA: return GL_RGBA;
|
||||
}
|
||||
return GL_RGBA;
|
||||
}
|
||||
|
||||
GLuint DataTypeToOpenGL(const DataType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DataType::UnsignedInt: return GL_UNSIGNED_INT;
|
||||
}
|
||||
|
||||
return GL_UNSIGNED_INT;
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::ClearBufferData(Ref<StorageBuffer> buffer, BufferFormat internalFormat,
|
||||
PixelFormat format, DataType type, const void* data) const
|
||||
{
|
||||
glClearNamedBufferData(buffer->GetRendererID(), BufferFormatToOpenGL(internalFormat), PixelFormatToOpenGL(format), DataTypeToOpenGL(type), data);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::GenerateMipmap(const uint32_t textureID) const
|
||||
{
|
||||
glGenerateTextureMipmap(textureID);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::DrawIndexed(const uint32_t count, const PrimitiveType type, const bool depthTest, const bool faceCulling) const
|
||||
{
|
||||
if (!depthTest)
|
||||
{
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
GLenum glPrimitiveType = 0;
|
||||
switch (type)
|
||||
{
|
||||
case PrimitiveType::Triangles:
|
||||
glPrimitiveType = GL_TRIANGLES;
|
||||
break;
|
||||
case PrimitiveType::Lines:
|
||||
glPrimitiveType = GL_LINES;
|
||||
break;
|
||||
case PrimitiveType::Points:
|
||||
break;
|
||||
}
|
||||
|
||||
if (faceCulling)
|
||||
glEnable(GL_CULL_FACE);
|
||||
else
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
glDrawElements(glPrimitiveType, count, GL_UNSIGNED_INT, nullptr);
|
||||
|
||||
if (!depthTest)
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::DrawIndexed(const PrimitiveType type, const uint32_t indexCount, const uint32_t instanceCount, const uint32_t firstIndex, const int32_t vertexOffset, uint32_t firstInstance) const
|
||||
{
|
||||
const GLenum glType = MapPrimitiveType(type);
|
||||
|
||||
const void* offset = (void*)(firstIndex * sizeof(uint32_t));
|
||||
glDrawElementsInstancedBaseVertex(glType, indexCount, GL_UNSIGNED_INT, offset, instanceCount, vertexOffset);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::Draw(PrimitiveType type, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex,
|
||||
uint32_t firstInstance) const
|
||||
{
|
||||
glDrawArraysInstancedBaseInstance(MapPrimitiveType(type), firstVertex, vertexCount, instanceCount, firstInstance);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::DispatchCompute(uint32_t groupX, uint32_t groupY, uint32_t groupZ) const
|
||||
{
|
||||
glDispatchCompute(groupX, groupY, groupZ);
|
||||
}
|
||||
|
||||
|
||||
GLuint MemoryBarrierMaskToOpenGLFormat(MemoryBarrierMask barrier)
|
||||
{
|
||||
switch (barrier)
|
||||
{
|
||||
case MemoryBarrierMask::VertexAttribArray: return GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT;
|
||||
case MemoryBarrierMask::ElementArray: return GL_ELEMENT_ARRAY_BARRIER_BIT;
|
||||
case MemoryBarrierMask::Uniform: return GL_UNIFORM_BARRIER_BIT;
|
||||
case MemoryBarrierMask::TextureFetch: return GL_TEXTURE_FETCH_BARRIER_BIT;
|
||||
case MemoryBarrierMask::ShaderImageAccess: return GL_SHADER_IMAGE_ACCESS_BARRIER_BIT;
|
||||
case MemoryBarrierMask::Command: return GL_COMMAND_BARRIER_BIT;
|
||||
case MemoryBarrierMask::PixelBuffer: return GL_PIXEL_BUFFER_BARRIER_BIT;
|
||||
case MemoryBarrierMask::TextureUpdate: return GL_TEXTURE_UPDATE_BARRIER_BIT;
|
||||
case MemoryBarrierMask::BufferUpdate: return GL_BUFFER_UPDATE_BARRIER_BIT;
|
||||
case MemoryBarrierMask::Framebuffer: return GL_FRAMEBUFFER_BARRIER_BIT;
|
||||
case MemoryBarrierMask::TransformFeedback: return GL_TRANSFORM_FEEDBACK_BARRIER_BIT;
|
||||
case MemoryBarrierMask::AtomicCounter: return GL_ATOMIC_COUNTER_BARRIER_BIT;
|
||||
case MemoryBarrierMask::ShaderStorage: return GL_SHADER_STORAGE_BARRIER_BIT;
|
||||
case MemoryBarrierMask::None: return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void OpenGLCommandBuffer::MemoryBarrier(const MemoryBarrierMask barriers) const
|
||||
{
|
||||
glMemoryBarrier(MemoryBarrierMaskToOpenGLFormat(barriers));
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::Clear(const glm::vec4& color, bool clearColor, bool clearDepth) const
|
||||
{
|
||||
GLbitfield mask = 0;
|
||||
if (clearColor) {
|
||||
glClearColor(color.r, color.g, color.b, color.a);
|
||||
mask |= GL_COLOR_BUFFER_BIT;
|
||||
}
|
||||
if (clearDepth) mask |= GL_DEPTH_BUFFER_BIT;
|
||||
glClear(mask);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetStencilFunc(const CompareOp compare, const uint32_t ref, const uint32_t mask) const
|
||||
{
|
||||
glStencilFunc(MapCompareOp(compare), ref, mask);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetLineSmooth(const bool enable) const
|
||||
{
|
||||
if (enable) glEnable(GL_LINE_SMOOTH);
|
||||
else glDisable(GL_LINE_SMOOTH);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetDepthWrite(const bool enable) const
|
||||
{
|
||||
glDepthMask(enable ? GL_TRUE : GL_FALSE);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::CopyImageSubData(uint32_t srcTexture, uint32_t dstTexture, uint32_t srcLevel,
|
||||
uint32_t dstLevel, uint32_t srcX, uint32_t srcY, uint32_t srcZ, uint32_t dstX, uint32_t dstY, uint32_t dstZ,
|
||||
uint32_t width, uint32_t height, uint32_t depth) const
|
||||
{
|
||||
glCopyImageSubData(srcTexture, GL_TEXTURE_CUBE_MAP, srcLevel, srcX, srcY, srcZ,
|
||||
dstTexture, GL_TEXTURE_CUBE_MAP, dstLevel, dstX, dstY, dstZ,
|
||||
width, height, depth);
|
||||
}
|
||||
|
||||
int32_t OpenGLCommandBuffer::GetUniformLocation(const uint32_t program, const std::string& name) const {
|
||||
return glGetUniformLocation(program, name.c_str());
|
||||
}
|
||||
|
||||
GLuint BlitMaskToOpenGL(BlitMask mask)
|
||||
{
|
||||
switch (mask) {
|
||||
case BlitMask::Color: return GL_COLOR_BUFFER_BIT;
|
||||
case BlitMask::Depth: return GL_DEPTH_BUFFER_BIT;
|
||||
case BlitMask::Stencila: return GL_STENCIL_BUFFER_BIT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLuint BlitFilterToOpenGL(BlitFilter filter)
|
||||
{
|
||||
switch (filter) {
|
||||
case BlitFilter::Nearest: return GL_NEAREST;
|
||||
case BlitFilter::Linear: return GL_LINEAR;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::BlitFramebuffer(int32_t srcX0, int32_t srcY0, int32_t srcX1, int32_t srcY1, int32_t dstX0,
|
||||
int32_t dstY0, int32_t dstX1, int32_t dstY1, BlitMask mask, BlitFilter filter) const
|
||||
{
|
||||
glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, BlitMaskToOpenGL(mask), BlitFilterToOpenGL(filter));
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::ProgramUniform1f(const uint32_t program, const int32_t location, const float value) const
|
||||
{
|
||||
glProgramUniform1f(program, location, value);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::UseProgram(const uint32_t programID) const
|
||||
{
|
||||
glUseProgram(programID);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::BindStorageBuffer(const uint32_t binding, const Ref<StorageBuffer>& ref) const
|
||||
{
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, binding, ref->GetRendererID());
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::ResolveMultisampleTexture(const Ref<FrameBuffer>& src, const Ref<Texture>& dst) const
|
||||
{
|
||||
uint32_t resolveFBO;
|
||||
glGenFramebuffers(1, &resolveFBO);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
|
||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst->GetRendererID(), 0);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, src->GetRendererID());
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
glBlitFramebuffer(0, 0, src->GetWidth(), src->GetHeight(),
|
||||
0, 0, src->GetWidth(), src->GetHeight(),
|
||||
GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
glDeleteFramebuffers(1, &resolveFBO);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
}
|
||||
}
|
||||
97
Prism/src/Prism/Platform/OpenGL/OpenGLCommandBuffer.h
Normal file
97
Prism/src/Prism/Platform/OpenGL/OpenGLCommandBuffer.h
Normal file
@ -0,0 +1,97 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/31.
|
||||
//
|
||||
|
||||
#ifndef PRISM_OPENGLCOMMANDBUFFER_H
|
||||
#define PRISM_OPENGLCOMMANDBUFFER_H
|
||||
#include "OpenGLRenderPass.h"
|
||||
#include "glad/glad.h"
|
||||
#include "Prism/Renderer/RHI/RHICommandBuffer.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
enum class TextureFormat;
|
||||
|
||||
class OpenGLCommandBuffer : public RHICommandBuffer
|
||||
{
|
||||
public:
|
||||
static GLenum MapCompareOp(CompareOp op);
|
||||
|
||||
static GLenum MapStencilOp(StencilOp op);
|
||||
|
||||
static GLenum MapCullMode(CullMode mode);
|
||||
|
||||
static GLenum MapPolygonMode(PolygonMode mode);
|
||||
|
||||
static GLenum MapPrimitiveType(PrimitiveType type);
|
||||
|
||||
void SetViewport(uint32_t x, uint32_t y, uint32_t width, uint32_t height) const override;
|
||||
|
||||
void SetScissor(uint32_t x, uint32_t y, uint32_t width, uint32_t height) const override;
|
||||
|
||||
void SetDepthTest(bool enable) const override;
|
||||
|
||||
void SetDepthFunc(CompareOp func) const override;
|
||||
|
||||
void SetStencilTest(bool enable) const override;
|
||||
|
||||
void SetStencilOp(StencilOp fail, StencilOp zFail, StencilOp zPass) const override;
|
||||
|
||||
void SetStencilMask(uint32_t mask) const override;
|
||||
|
||||
void SetCullMode(CullMode mode) const override;
|
||||
|
||||
void SetPolygonMode(PolygonMode mode) const override;
|
||||
|
||||
void SetLineWidth(float width) const override;
|
||||
void SetLineThickness(float thickness) const override;
|
||||
|
||||
void SetPointSize(float size) const override;
|
||||
|
||||
void BindFramebuffer(RendererID rendererId) const override;
|
||||
void BindFramebuffer(FramebufferTarget target, RendererID rendererId) const override;
|
||||
void BindTexture(uint32_t slot, uint32_t textureID) const override;
|
||||
void BindImageTexture(uint32_t unit, uint32_t textureID, int32_t level, bool layered, int32_t layer, AccessMode access, TextureFormat format) const override;
|
||||
void BindTextureUnit(uint32_t i, RendererID rendererId) const override;
|
||||
void BindSampler(uint32_t slot, uint32_t samplerID) const override;
|
||||
|
||||
void SetDrawBuffer(uint32_t attachment) const override;
|
||||
void SetReadBuffer(uint32_t attachment) const override;
|
||||
|
||||
void ClearBufferData(Ref<StorageBuffer> buffer, BufferFormat internalFormat, PixelFormat format, DataType type, const void* data) const override;
|
||||
|
||||
void GenerateMipmap(uint32_t textureID) const override;
|
||||
|
||||
|
||||
void DrawIndexed(uint32_t count, PrimitiveType type, bool depthTest, bool faceCulling) const override;
|
||||
|
||||
void DrawIndexed(PrimitiveType type, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) const override;
|
||||
|
||||
void Draw(PrimitiveType type, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) const override;
|
||||
|
||||
void DispatchCompute(uint32_t groupX, uint32_t groupY, uint32_t groupZ) const override;
|
||||
|
||||
void MemoryBarrier(MemoryBarrierMask barriers) const override;
|
||||
|
||||
void Clear(const glm::vec4& color, bool clearColor, bool clearDepth) const override;
|
||||
void SetStencilFunc(CompareOp compare, uint32_t ref, uint32_t mask) const override;
|
||||
void SetLineSmooth(bool enable) const override;
|
||||
void SetDepthWrite(bool enable) const override;
|
||||
|
||||
void CopyImageSubData(uint32_t srcTexture, uint32_t dstTexture, uint32_t srcLevel, uint32_t dstLevel, uint32_t srcX, uint32_t srcY, uint32_t srcZ, uint32_t dstX, uint32_t dstY, uint32_t dstZ, uint32_t width, uint32_t height, uint32_t depth) const override;
|
||||
int32_t GetUniformLocation(uint32_t program, const std::string& name) const override;
|
||||
void BlitFramebuffer(int32_t srcX0, int32_t srcY0, int32_t srcX1, int32_t srcY1, int32_t dstX0, int32_t dstY0, int32_t dstX1, int32_t dstY1, BlitMask mask, BlitFilter filter) const override;
|
||||
|
||||
void ProgramUniform1f(uint32_t program, int32_t location, float value) const override;
|
||||
|
||||
void UseProgram(uint32_t programID) const override;
|
||||
|
||||
void BindStorageBuffer(uint32_t binding, const Ref<StorageBuffer>& ref) const override;
|
||||
|
||||
void ResolveMultisampleTexture(const Ref<FrameBuffer>& src, const Ref<Texture>& dst) const override;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //PRISM_OPENGLCOMMANDBUFFER_H
|
||||
@ -230,4 +230,12 @@ namespace Prism
|
||||
glBindTextureUnit(slot, instance->m_ColorAttachments[attachmentIndex]);
|
||||
});
|
||||
}
|
||||
|
||||
void OpenGLFrameBuffer::BindDepthTexture(uint32_t slot) const
|
||||
{
|
||||
Ref<const OpenGLFrameBuffer> instance = this;
|
||||
Renderer::Submit([instance, slot]() {
|
||||
glBindTextureUnit(slot, instance->m_DepthAttachment);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@ namespace Prism
|
||||
void Resize(uint32_t width, uint32_t height, bool forceReCreate) override;
|
||||
|
||||
void BindTexture(uint32_t attachmentIndex, uint32_t slot) const override;
|
||||
void BindDepthTexture(uint32_t slot = 0) const override;
|
||||
|
||||
uint32_t GetWidth() const override { return m_Specification.Width; }
|
||||
uint32_t GetHeight() const override { return m_Specification.Height; }
|
||||
|
||||
87
Prism/src/Prism/Platform/OpenGL/OpenGLRHIDevice.cpp
Normal file
87
Prism/src/Prism/Platform/OpenGL/OpenGLRHIDevice.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/31.
|
||||
//
|
||||
|
||||
#include "OpenGLRHIDevice.h"
|
||||
|
||||
#include "OpenGLCommandBuffer.h"
|
||||
#include "glm/gtc/type_ptr.hpp"
|
||||
|
||||
#include "Prism/Renderer/RendererAPI.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
static GLenum MapFilterMode(FilterMode mode) {
|
||||
switch (mode) {
|
||||
case FilterMode::Nearest: return GL_NEAREST;
|
||||
case FilterMode::Linear: return GL_LINEAR;
|
||||
case FilterMode::NearestMipmapNearest: return GL_NEAREST_MIPMAP_NEAREST;
|
||||
case FilterMode::LinearMipmapNearest: return GL_LINEAR_MIPMAP_NEAREST;
|
||||
case FilterMode::NearestMipmapLinear: return GL_NEAREST_MIPMAP_LINEAR;
|
||||
case FilterMode::LinearMipmapLinear: return GL_LINEAR_MIPMAP_LINEAR;
|
||||
default: return GL_LINEAR;
|
||||
}
|
||||
}
|
||||
|
||||
static GLenum MapWrapMode(WrapMode mode) {
|
||||
switch (mode) {
|
||||
case WrapMode::Repeat: return GL_REPEAT;
|
||||
case WrapMode::MirroredRepeat: return GL_MIRRORED_REPEAT;
|
||||
case WrapMode::ClampToEdge: return GL_CLAMP_TO_EDGE;
|
||||
case WrapMode::ClampToBorder: return GL_CLAMP_TO_BORDER;
|
||||
case WrapMode::MirrorClampToEdge: return GL_MIRROR_CLAMP_TO_EDGE;
|
||||
default: return GL_REPEAT;
|
||||
}
|
||||
}
|
||||
|
||||
static GLenum MapCompareFunc(CompareFunc func) {
|
||||
switch (func) {
|
||||
case CompareFunc::Never: return GL_NEVER;
|
||||
case CompareFunc::Less: return GL_LESS;
|
||||
case CompareFunc::Equal: return GL_EQUAL;
|
||||
case CompareFunc::LessEqual: return GL_LEQUAL;
|
||||
case CompareFunc::Greater: return GL_GREATER;
|
||||
case CompareFunc::NotEqual: return GL_NOTEQUAL;
|
||||
case CompareFunc::GreaterEqual: return GL_GEQUAL;
|
||||
case CompareFunc::Always: return GL_ALWAYS;
|
||||
default: return GL_ALWAYS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Ref<RHICommandBuffer> OpenGLRHIDevice::CreateCommandBuffer()
|
||||
{
|
||||
return Ref<OpenGLCommandBuffer>::Create();
|
||||
}
|
||||
|
||||
RendererID OpenGLRHIDevice::CreateSampler(const SamplerDesc& desc)
|
||||
{
|
||||
GLuint sampler;
|
||||
glGenSamplers(1, &sampler);
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, MapFilterMode(desc.MinFilter));
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, MapFilterMode(desc.MagFilter));
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, MapWrapMode(desc.WrapU));
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, MapWrapMode(desc.WrapV));
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_WRAP_R, MapWrapMode(desc.WrapW));
|
||||
if (desc.MaxAnisotropy > 1.0f) {
|
||||
glSamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY, desc.MaxAnisotropy);
|
||||
}
|
||||
glSamplerParameterf(sampler, GL_TEXTURE_LOD_BIAS, desc.MipLodBias);
|
||||
if (desc.EnableCompare) {
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_COMPARE_FUNC, MapCompareFunc(desc.CompareFunc));
|
||||
} else {
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
||||
}
|
||||
if (desc.WrapU == WrapMode::ClampToBorder || desc.WrapV == WrapMode::ClampToBorder || desc.WrapW == WrapMode::ClampToBorder) {
|
||||
glSamplerParameterfv(sampler, GL_TEXTURE_BORDER_COLOR, glm::value_ptr(desc.BorderColor));
|
||||
}
|
||||
return sampler;
|
||||
}
|
||||
|
||||
void OpenGLRHIDevice::DestroySampler(const RendererID sampler)
|
||||
{
|
||||
glDeleteSamplers(1, &sampler);
|
||||
}
|
||||
}
|
||||
22
Prism/src/Prism/Platform/OpenGL/OpenGLRHIDevice.h
Normal file
22
Prism/src/Prism/Platform/OpenGL/OpenGLRHIDevice.h
Normal file
@ -0,0 +1,22 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/31.
|
||||
//
|
||||
|
||||
#ifndef PRISM_OPENGLRHIDEVICE_H
|
||||
#define PRISM_OPENGLRHIDEVICE_H
|
||||
#include "Prism/Renderer/RHI/RHIDevice.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
class OpenGLRHIDevice : public RHIDevice
|
||||
{
|
||||
public:
|
||||
Ref<RHICommandBuffer> CreateCommandBuffer() override;
|
||||
|
||||
RendererID CreateSampler(const SamplerDesc& desc) override;
|
||||
void DestroySampler(RendererID sampler) override;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //PRISM_OPENGLRHIDEVICE_H
|
||||
@ -15,8 +15,8 @@ namespace Prism
|
||||
OpenGLRenderPass(const RenderPassSpecification& spec);
|
||||
virtual ~OpenGLRenderPass();
|
||||
|
||||
virtual RenderPassSpecification& GetSpecification() override { return m_Spec; }
|
||||
virtual const RenderPassSpecification& GetSpecification() const { return m_Spec; }
|
||||
RenderPassSpecification& GetSpecification() override { return m_Spec; }
|
||||
const RenderPassSpecification& GetSpecification() const override { return m_Spec; }
|
||||
|
||||
private:
|
||||
RenderPassSpecification m_Spec;
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
|
||||
#include "glad/glad.h"
|
||||
#include "Prism/Core/Log.h"
|
||||
#include "Prism/Renderer/RHI/RHICommandBuffer.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
@ -157,10 +158,13 @@ namespace Prism
|
||||
glClearColor(r, g, b, a);
|
||||
}
|
||||
|
||||
void RendererAPI::DrawIndexed(uint32_t count, PrimitiveType type, bool depthTest, bool faceCulling)
|
||||
void RendererAPI::DrawIndexed(const uint32_t count, const PrimitiveType type, const bool depthTest, const bool faceCulling)
|
||||
{
|
||||
if (!depthTest)
|
||||
{
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
GLenum glPrimitiveType = 0;
|
||||
switch (type)
|
||||
@ -181,7 +185,10 @@ namespace Prism
|
||||
glDrawElements(glPrimitiveType, count, GL_UNSIGNED_INT, nullptr);
|
||||
|
||||
if (!depthTest)
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
}
|
||||
|
||||
void RendererAPI::SetLineThickness(const float thickness)
|
||||
|
||||
@ -54,7 +54,7 @@ namespace Prism
|
||||
// Texture2D
|
||||
// ******************************************
|
||||
|
||||
OpenGLTexture2D::OpenGLTexture2D(TextureFormat format, uint32_t width, uint32_t height, TextureWrap wrap)
|
||||
OpenGLTexture2D::OpenGLTexture2D(const TextureFormat format, const uint32_t width, const uint32_t height, const TextureWrap wrap)
|
||||
: m_Format(format), m_Width(width), m_Height(height), m_Wrap(wrap)
|
||||
{
|
||||
Ref<OpenGLTexture2D> instance = this;
|
||||
@ -83,6 +83,53 @@ namespace Prism
|
||||
m_ImageData.Allocate(width * height * GetBPP(m_Format));
|
||||
}
|
||||
|
||||
OpenGLTexture2D::OpenGLTexture2D(const TextureFormat format, const uint32_t width, const uint32_t height, const void* data, const TextureWrap wrap)
|
||||
: m_Format(format), m_Width(width), m_Height(height), m_Wrap(wrap)
|
||||
{
|
||||
// 计算图像数据大小(假设是 RGBA8,或根据格式动态计算)
|
||||
uint32_t bpp = GetBPP(format);
|
||||
uint32_t dataSize = width * height * bpp;
|
||||
|
||||
// 保存一份数据到 CPU 缓冲区(供后续可能的读取)
|
||||
if (data)
|
||||
{
|
||||
m_ImageData.Allocate(dataSize);
|
||||
memcpy(m_ImageData.Data, data, dataSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ImageData.Allocate(dataSize);
|
||||
memset(m_ImageData.Data, 0, dataSize); // 可选:初始化为0
|
||||
}
|
||||
|
||||
Ref<OpenGLTexture2D> instance = this;
|
||||
Renderer::Submit([instance]() mutable {
|
||||
glGenTextures(1, &instance->m_RendererID);
|
||||
glBindTexture(GL_TEXTURE_2D, instance->m_RendererID);
|
||||
|
||||
// 设置纹理参数
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
GLint wrap = instance->m_Wrap == TextureWrap::Clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT;
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap);
|
||||
glTextureParameterf(instance->m_RendererID, GL_TEXTURE_MAX_ANISOTROPY, RendererAPI::GetCapabilities().MaxAnisotropy);
|
||||
|
||||
// 上传数据(如果已有数据则使用,否则传 nullptr 创建空纹理)
|
||||
glTexImage2D(GL_TEXTURE_2D, 0,
|
||||
SizedInternalFormat(instance->m_Format),
|
||||
(GLint)instance->m_Width, (GLint)instance->m_Height, 0,
|
||||
ImageFormat(instance->m_Format),
|
||||
DataType(instance->m_Format),
|
||||
instance->m_ImageData.Data); // 这里传入数据指针
|
||||
|
||||
// 如果需要生成 mipmap,取消注释下一行
|
||||
// glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
OpenGLTexture2D::OpenGLTexture2D(const std::string& path, bool srgb)
|
||||
: m_FilePath(path)
|
||||
@ -186,7 +233,7 @@ namespace Prism
|
||||
});
|
||||
}
|
||||
|
||||
void OpenGLTexture2D::SetData(const void* data, int count)
|
||||
void OpenGLTexture2D::SetData(const void* data, uint32_t count)
|
||||
{
|
||||
Lock();
|
||||
|
||||
|
||||
@ -14,6 +14,7 @@ namespace Prism
|
||||
{
|
||||
public:
|
||||
OpenGLTexture2D(TextureFormat format, uint32_t width, uint32_t height, TextureWrap wrap);
|
||||
OpenGLTexture2D(TextureFormat format, uint32_t width, uint32_t height, const void* data, TextureWrap wrap = TextureWrap::Clamp);
|
||||
OpenGLTexture2D(const std::string& path, bool srgb);
|
||||
virtual ~OpenGLTexture2D();
|
||||
|
||||
@ -30,7 +31,7 @@ namespace Prism
|
||||
virtual void Lock() override;
|
||||
virtual void Unlock() override;
|
||||
|
||||
virtual void SetData(const void* data, int count) override;
|
||||
virtual void SetData(const void* data, uint32_t count) override;
|
||||
|
||||
virtual void Resize(uint32_t width, uint32_t height) override;
|
||||
virtual Buffer GetWriteableBuffer() override;
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
#include "Prism/Core/Application.h"
|
||||
|
||||
#include "efsw/efsw.hpp"
|
||||
#include "Prism/Utilities/StringUtils.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
@ -30,20 +31,22 @@ namespace Prism
|
||||
public:
|
||||
void handleFileAction(efsw::WatchID watchid,
|
||||
const std::string& dir,
|
||||
const std::string& filename,
|
||||
const std::string& filepath,
|
||||
efsw::Action action,
|
||||
std::string oldFilename = "") override
|
||||
std::string oldFilepath = "") override
|
||||
{
|
||||
// 如果引擎自身操作设置了忽略标志,则跳过本次事件
|
||||
if (FileSystem::s_IgnoreNextChange.load())
|
||||
return;
|
||||
|
||||
std::filesystem::path fullPath = std::filesystem::path(dir) / filename;
|
||||
std::string fullPath = (std::filesystem::path(dir) / filepath).string();
|
||||
|
||||
fullPath = Utils::NormalizePath(fullPath);
|
||||
|
||||
FileSystemChangedEvent e;
|
||||
e.FilePath = fullPath.string();
|
||||
e.NewName = filename;
|
||||
e.OldName = oldFilename; // efsw 在重命名时会提供旧文件名
|
||||
e.FilePath = fullPath;
|
||||
e.NewName = Utils::GetFilename(filepath);
|
||||
e.OldName = Utils::GetFilename(oldFilepath); // efsw 在重命名时会提供旧文件名
|
||||
e.IsDirectory = false; // 稍后根据实际情况判断
|
||||
|
||||
// 判断是否为目录(可能抛出异常,使用 error_code 版本)
|
||||
@ -161,6 +164,30 @@ namespace Prism
|
||||
return result ? std::string(result) : std::string();
|
||||
}
|
||||
|
||||
void FileSystem::OpenInExplorer(const std::string& path)
|
||||
{
|
||||
const std::filesystem::path absPath = std::filesystem::absolute(path);
|
||||
if (!std::filesystem::exists(absPath))
|
||||
{
|
||||
PM_CORE_WARN("Path does not exist: {}", path);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string cmd;
|
||||
if (std::filesystem::is_directory(absPath))
|
||||
{
|
||||
// 打开目录
|
||||
cmd = absPath.string();
|
||||
ShellExecuteA(nullptr, "open", "explorer.exe", cmd.c_str(), NULL, SW_SHOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 打开并选中文件
|
||||
cmd = "/select, \"" + absPath.string() + "\"";
|
||||
ShellExecuteA(nullptr, "open", "explorer.exe", cmd.c_str(), NULL, SW_SHOW);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool FileSystem::CreateFolder(const std::filesystem::path& filepath)
|
||||
{
|
||||
|
||||
@ -62,7 +62,7 @@ namespace Prism
|
||||
m_Data.VSync = enable;
|
||||
}
|
||||
|
||||
std::pair<float, float> WindowsWindow::GetWindowPos() const
|
||||
glm::vec2 WindowsWindow::GetWindowPos() const
|
||||
{
|
||||
int x, y;
|
||||
glfwGetWindowPos(m_Window, &x, &y);
|
||||
@ -91,6 +91,8 @@ namespace Prism
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
|
||||
glfwWindowHint(GLFW_DEPTH_BITS, 24);
|
||||
|
||||
s_GLFWInitialized = true;
|
||||
}
|
||||
|
||||
@ -119,16 +121,37 @@ namespace Prism
|
||||
|
||||
glfwSetWindowCloseCallback(m_Window, [](GLFWwindow* window)
|
||||
{
|
||||
auto& data = *((WindowData*)glfwGetWindowUserPointer(window));
|
||||
const auto& data = *((WindowData*)glfwGetWindowUserPointer(window));
|
||||
|
||||
WindowCloseEvent event;
|
||||
data.EventCallback(event);
|
||||
});
|
||||
|
||||
glfwSetWindowFocusCallback(m_Window, [](GLFWwindow* window, const int focused) {
|
||||
const auto& data = *((WindowData*)glfwGetWindowUserPointer(window));
|
||||
|
||||
if (focused)
|
||||
{
|
||||
WindowFocusEvent event;
|
||||
data.EventCallback(event);
|
||||
}
|
||||
else
|
||||
{
|
||||
WindowLostFocusEvent event;
|
||||
data.EventCallback(event);
|
||||
}
|
||||
});
|
||||
|
||||
glfwSetWindowPosCallback(m_Window, [](GLFWwindow* window, int xpos, int ypos) {
|
||||
const auto& data = *((WindowData*)glfwGetWindowUserPointer(window));
|
||||
|
||||
WindowMovedEvent event(xpos, ypos);
|
||||
data.EventCallback(event);
|
||||
});
|
||||
|
||||
glfwSetKeyCallback(m_Window, [](GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||
{
|
||||
auto& data = *((WindowData*)glfwGetWindowUserPointer(window));
|
||||
const auto& data = *((WindowData*)glfwGetWindowUserPointer(window));
|
||||
|
||||
switch (action)
|
||||
{
|
||||
|
||||
@ -27,8 +27,8 @@ namespace Prism
|
||||
|
||||
bool const IsVSync() const override { return m_Data.VSync; }
|
||||
void SetVSync(bool enable) override;
|
||||
virtual std::pair<uint32_t, uint32_t> GetSize() const override { return { m_Data.Width, m_Data.Height }; }
|
||||
virtual std::pair<float, float> GetWindowPos() const override;
|
||||
virtual glm::ivec2 GetSize() const override { return { m_Data.Width, m_Data.Height }; }
|
||||
virtual glm::vec2 GetWindowPos() const override;
|
||||
|
||||
virtual const std::string& GetTitle() const override { return m_Data.Title; }
|
||||
virtual void SetTitle(const std::string& title) override;
|
||||
|
||||
@ -78,6 +78,7 @@ namespace Prism
|
||||
virtual void Resize(uint32_t width, uint32_t height, bool forceReCreate = false) = 0;
|
||||
|
||||
virtual void BindTexture(uint32_t attachmentIndex = 0, uint32_t slot = 0) const = 0;
|
||||
virtual void BindDepthTexture(uint32_t slot = 0) const = 0;
|
||||
|
||||
virtual uint32_t GetWidth() const = 0;
|
||||
virtual uint32_t GetHeight() const = 0;
|
||||
|
||||
@ -140,6 +140,27 @@ namespace Prism
|
||||
return Ref<MaterialInstance>::Create(material);
|
||||
}
|
||||
|
||||
|
||||
Ref<MaterialInstance> MaterialInstance::Copy(Ref<MaterialInstance> other)
|
||||
{
|
||||
if (!other) return nullptr;
|
||||
|
||||
auto newInstance = Create(other->m_Material);
|
||||
newInstance->m_Name = other->m_Name + "_Override";
|
||||
|
||||
// 复制 uniform 缓冲区
|
||||
newInstance->m_VSUniformStorageBuffer = Buffer::Copy(other->m_VSUniformStorageBuffer.Data, other->m_VSUniformStorageBuffer.GetSize());
|
||||
newInstance->m_PSUniformStorageBuffer = Buffer::Copy(other->m_PSUniformStorageBuffer.Data, other->m_PSUniformStorageBuffer.GetSize());
|
||||
|
||||
// 复制纹理列表(共享纹理引用)
|
||||
newInstance->m_Textures = other->m_Textures;
|
||||
|
||||
// 复制覆盖标记集合
|
||||
newInstance->m_OverriddenValues = other->m_OverriddenValues;
|
||||
|
||||
return newInstance;
|
||||
}
|
||||
|
||||
void MaterialInstance::OnShaderReloaded()
|
||||
{
|
||||
AllocateStorage();
|
||||
|
||||
@ -119,6 +119,11 @@ namespace Prism
|
||||
|
||||
static Ref<MaterialInstance> Create(const Ref<Material>& material);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param other copy other data to a new Data
|
||||
* @return the new Data will as Ref return
|
||||
*/
|
||||
static Ref<MaterialInstance> Copy(Ref<MaterialInstance> other);
|
||||
|
||||
template<typename T>
|
||||
|
||||
@ -64,6 +64,13 @@ namespace Prism
|
||||
return result;
|
||||
}
|
||||
|
||||
static AABB UnionAABB(const AABB& a, const AABB& b) {
|
||||
AABB result;
|
||||
result.Min = glm::min(a.Min, b.Min);
|
||||
result.Max = glm::max(a.Max, b.Max);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void AnimatedVertex::AddBoneData(uint32_t BoneID, float Weight)
|
||||
{
|
||||
@ -300,9 +307,9 @@ namespace Prism
|
||||
std::string texturePath = parentPath.string();
|
||||
|
||||
PM_MESH_LOG(" Albedo map path = {0}", texturePath);
|
||||
auto texture = AssetsManager::GetAsset<Texture2D>(texturePath);
|
||||
auto texture = AssetsManager::TryGetAsset<Texture2D>(texturePath);
|
||||
// auto texture = Texture2D::Create(texturePath, true);
|
||||
if (texture->Loaded())
|
||||
if (texture && texture->Loaded())
|
||||
{
|
||||
m_Textures[i] = texture;
|
||||
mi->Set("u_AlbedoTexture", m_Textures[i]);
|
||||
@ -333,9 +340,9 @@ namespace Prism
|
||||
std::string texturePath = parentPath.string();
|
||||
|
||||
PM_MESH_LOG(" Normal map path = {0}", texturePath);
|
||||
auto texture = AssetsManager::GetAsset<Texture2D>(texturePath);
|
||||
auto texture = AssetsManager::TryGetAsset<Texture2D>(texturePath);
|
||||
// auto texture = Texture2D::Create(texturePath);
|
||||
if (texture->Loaded())
|
||||
if (texture && texture->Loaded())
|
||||
{
|
||||
mi->Set("u_NormalTexture", texture);
|
||||
mi->Set("u_NormalTexToggle", 1.0f);
|
||||
@ -362,9 +369,9 @@ namespace Prism
|
||||
std::string texturePath = parentPath.string();
|
||||
|
||||
PM_MESH_LOG(" Roughness map path = {0}", texturePath);
|
||||
auto texture = AssetsManager::GetAsset<Texture2D>(texturePath);
|
||||
auto texture = AssetsManager::TryGetAsset<Texture2D>(texturePath);
|
||||
// auto texture = Texture2D::Create(texturePath);
|
||||
if (texture->Loaded())
|
||||
if (texture && texture->Loaded())
|
||||
{
|
||||
PM_CORE_TRACE(" Roughness map path = {0}", texturePath);
|
||||
mi->Set("u_RoughnessTexture", texture);
|
||||
@ -458,9 +465,9 @@ namespace Prism
|
||||
|
||||
|
||||
PM_MESH_LOG(" Metalness map path = {0}", texturePath);
|
||||
auto texture = AssetsManager::GetAsset<Texture2D>(texturePath);
|
||||
auto texture = AssetsManager::TryGetAsset<Texture2D>(texturePath);
|
||||
// auto texture = Texture2D::Create(texturePath);
|
||||
if (texture->Loaded())
|
||||
if (texture && texture->Loaded())
|
||||
{
|
||||
mi->Set("u_MetalnessTexture", texture);
|
||||
mi->Set("u_MetalnessTexToggle", 1.0f);
|
||||
@ -517,6 +524,32 @@ namespace Prism
|
||||
PipelineSpecification pipelineSpecification;
|
||||
pipelineSpecification.Layout = vertexBufferLayout;
|
||||
m_Pipeline = Pipeline::Create(pipelineSpecification);
|
||||
|
||||
|
||||
if (!m_IsAnimated)
|
||||
{
|
||||
for (const auto& submesh : m_Submeshes) {
|
||||
glm::vec3 corners[8];
|
||||
corners[0] = submesh.Transform * glm::vec4(submesh.BoundingBox.Min, 1.0f);
|
||||
corners[1] = submesh.Transform * glm::vec4(submesh.BoundingBox.Max, 1.0f);
|
||||
corners[2] = submesh.Transform * glm::vec4(glm::vec3(submesh.BoundingBox.Min.x, submesh.BoundingBox.Min.y, submesh.BoundingBox.Max.z), 1.0f);
|
||||
corners[3] = submesh.Transform * glm::vec4(glm::vec3(submesh.BoundingBox.Min.x, submesh.BoundingBox.Max.y, submesh.BoundingBox.Min.z), 1.0f);
|
||||
corners[4] = submesh.Transform * glm::vec4(glm::vec3(submesh.BoundingBox.Min.x, submesh.BoundingBox.Max.y, submesh.BoundingBox.Max.z), 1.0f);
|
||||
corners[5] = submesh.Transform * glm::vec4(glm::vec3(submesh.BoundingBox.Max.x, submesh.BoundingBox.Min.y, submesh.BoundingBox.Min.z), 1.0f);
|
||||
corners[6] = submesh.Transform * glm::vec4(glm::vec3(submesh.BoundingBox.Max.x, submesh.BoundingBox.Min.y, submesh.BoundingBox.Max.z), 1.0f);
|
||||
corners[7] = submesh.Transform * glm::vec4(glm::vec3(submesh.BoundingBox.Max.x, submesh.BoundingBox.Max.y, submesh.BoundingBox.Min.z), 1.0f);
|
||||
|
||||
AABB transformedAABB;
|
||||
transformedAABB.Min = corners[0];
|
||||
transformedAABB.Max = corners[0];
|
||||
for (int i = 1; i < 8; ++i) {
|
||||
transformedAABB.Min = glm::min(transformedAABB.Min, corners[i]);
|
||||
transformedAABB.Max = glm::max(transformedAABB.Max, corners[i]);
|
||||
}
|
||||
|
||||
m_BoundingBox = UnionAABB(m_BoundingBox, transformedAABB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Mesh::Mesh(const std::vector<Vertex>& vertices, const std::vector<Index>& indices, const glm::mat4& transform)
|
||||
@ -541,6 +574,16 @@ namespace Prism
|
||||
{ ShaderDataType::Float2, "a_TexCoord" },
|
||||
};
|
||||
m_Pipeline = Pipeline::Create(pipelineSpecification);
|
||||
|
||||
|
||||
// boundingbox
|
||||
m_BoundingBox.Min = glm::vec3(FLT_MAX);
|
||||
m_BoundingBox.Max = glm::vec3(-FLT_MAX);
|
||||
for (const auto& vertex : vertices) {
|
||||
glm::vec3 transformedPos = transform * glm::vec4(vertex.Position, 1.0f);
|
||||
m_BoundingBox.Min = glm::min(m_BoundingBox.Min, transformedPos);
|
||||
m_BoundingBox.Max = glm::max(m_BoundingBox.Max, transformedPos);
|
||||
}
|
||||
}
|
||||
|
||||
Mesh::~Mesh() = default;
|
||||
@ -569,6 +612,24 @@ namespace Prism
|
||||
*/
|
||||
}
|
||||
|
||||
void Mesh::TraverseNodes(const aiNode* node, const glm::mat4& parentTransform, uint32_t level)
|
||||
{
|
||||
const glm::mat4 localTransform = parentTransform * Mat4FromAssimpMat4(node->mTransformation);
|
||||
glm::mat4 transform = parentTransform * localTransform;
|
||||
for (uint32_t i = 0; i < node->mNumMeshes; i++)
|
||||
{
|
||||
const uint32_t mesh = node->mMeshes[i];
|
||||
auto& submesh = m_Submeshes[mesh];
|
||||
submesh.NodeName = node->mName.C_Str();
|
||||
submesh.Transform = transform;
|
||||
submesh.LocalTransform = localTransform;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < node->mNumChildren; i++)
|
||||
{
|
||||
TraverseNodes(node->mChildren[i], localTransform, level + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void Mesh::DumpVertexBuffer()
|
||||
{
|
||||
@ -657,24 +718,6 @@ namespace Prism
|
||||
}
|
||||
*/
|
||||
|
||||
void Mesh::TraverseNodes(const aiNode* node, const glm::mat4& parentTransform, uint32_t level)
|
||||
{
|
||||
const glm::mat4 localTransform = parentTransform * Mat4FromAssimpMat4(node->mTransformation);
|
||||
glm::mat4 transform = parentTransform * localTransform;
|
||||
for (uint32_t i = 0; i < node->mNumMeshes; i++)
|
||||
{
|
||||
const uint32_t mesh = node->mMeshes[i];
|
||||
auto& submesh = m_Submeshes[mesh];
|
||||
submesh.NodeName = node->mName.C_Str();
|
||||
submesh.Transform = transform;
|
||||
submesh.LocalTransform = localTransform;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < node->mNumChildren; i++)
|
||||
{
|
||||
TraverseNodes(node->mChildren[i], localTransform, level + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
const aiNodeAnim* Mesh::FindNodeAnim(const aiAnimation* animation, const std::string& nodeName)
|
||||
|
||||
@ -141,6 +141,9 @@ namespace Prism
|
||||
{
|
||||
return m_AnimatorController ? m_AnimatorController->GetFinalBoneTransforms() : m_EmptyTransforms;
|
||||
}
|
||||
|
||||
const AABB& GetBoundingBox() const { return m_BoundingBox; }
|
||||
|
||||
private:
|
||||
void TraverseNodes(const aiNode* node, const glm::mat4& parentTransform = glm::mat4(1.0f), uint32_t level = 0);
|
||||
|
||||
@ -182,6 +185,9 @@ namespace Prism
|
||||
// float m_TimeMultiplier = 1.0f;
|
||||
|
||||
std::string m_FilePath;
|
||||
|
||||
AABB m_BoundingBox;
|
||||
|
||||
private:
|
||||
friend class Renderer;
|
||||
friend class SceneHierarchyPanel;
|
||||
|
||||
5
Prism/src/Prism/Renderer/RHI/RHICommandBuffer.cpp
Normal file
5
Prism/src/Prism/Renderer/RHI/RHICommandBuffer.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/31.
|
||||
//
|
||||
|
||||
#include "RHICommandBuffer.h"
|
||||
123
Prism/src/Prism/Renderer/RHI/RHICommandBuffer.h
Normal file
123
Prism/src/Prism/Renderer/RHI/RHICommandBuffer.h
Normal file
@ -0,0 +1,123 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/31.
|
||||
//
|
||||
|
||||
#ifndef PRISM_RHICOMMANDBUFFER_H
|
||||
#define PRISM_RHICOMMANDBUFFER_H
|
||||
#include "Prism/Core/Ref.h"
|
||||
#include "Prism/Renderer/RendererAPI.h"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
namespace Prism {
|
||||
class FrameBuffer;
|
||||
class StorageBuffer;
|
||||
enum class TextureFormat;
|
||||
class Texture;
|
||||
class IndexBuffer;
|
||||
class VertexBuffer;
|
||||
class Pipeline;
|
||||
class RenderPass;
|
||||
|
||||
enum class CompareOp { Never, Less, Equal, LessEqual, Greater, NotEqual, GreaterEqual, Always };
|
||||
enum class StencilOp { Keep, Zero, Replace, Incr, Decr, Invert, IncrWrap, DecrWrap };
|
||||
enum class CullMode { None, Front, Back };
|
||||
enum class PolygonMode { Fill, Line, Point };
|
||||
enum class PrimitiveType { Triangles, Lines, Points };
|
||||
enum class AccessMode { ReadOnly, WriteOnly, ReadWrite };
|
||||
enum class BufferFormat { R32UI, RGB16F };
|
||||
enum class PixelFormat { RED, RGBA };
|
||||
enum class BlitFilter { Nearest, Linear };
|
||||
enum class DataType { UnsignedInt };
|
||||
enum class BlitMask { Color, Depth, Stencila };
|
||||
|
||||
enum class MemoryBarrierMask {
|
||||
None = 0,
|
||||
VertexAttribArray, // GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT
|
||||
ElementArray, // GL_ELEMENT_ARRAY_BARRIER_BIT
|
||||
Uniform, // GL_UNIFORM_BARRIER_BIT
|
||||
TextureFetch, // GL_TEXTURE_FETCH_BARRIER_BIT
|
||||
ShaderImageAccess, // GL_SHADER_IMAGE_ACCESS_BARRIER_BIT
|
||||
Command, // GL_COMMAND_BARRIER_BIT
|
||||
PixelBuffer, // GL_PIXEL_BUFFER_BARRIER_BIT
|
||||
TextureUpdate, // GL_TEXTURE_UPDATE_BARRIER_BIT
|
||||
BufferUpdate, // GL_BUFFER_UPDATE_BARRIER_BIT
|
||||
Framebuffer, // GL_FRAMEBUFFER_BARRIER_BIT
|
||||
TransformFeedback, // GL_TRANSFORM_FEEDBACK_BARRIER_BIT
|
||||
AtomicCounter, // GL_ATOMIC_COUNTER_BARRIER_BIT
|
||||
ShaderStorage, // GL_SHADER_STORAGE_BARRIER_BIT
|
||||
All // GL_ALL_BARRIER_BITS
|
||||
};
|
||||
|
||||
enum class FramebufferTarget {Read, Draw, Both};
|
||||
|
||||
class PRISM_API RHICommandBuffer : public RefCounted
|
||||
{
|
||||
public:
|
||||
virtual ~RHICommandBuffer() = default;
|
||||
|
||||
// 状态设置
|
||||
virtual void SetViewport(uint32_t x, uint32_t y, uint32_t width, uint32_t height) const = 0;
|
||||
virtual void SetScissor(uint32_t x, uint32_t y, uint32_t width, uint32_t height) const = 0;
|
||||
virtual void SetDepthTest(bool enable) const = 0;
|
||||
virtual void SetDepthFunc(CompareOp func) const = 0;
|
||||
virtual void SetStencilTest(bool enable) const = 0;
|
||||
virtual void SetStencilOp(StencilOp fail, StencilOp zfail, StencilOp zpass) const = 0;
|
||||
virtual void SetStencilMask(uint32_t mask) const = 0;
|
||||
virtual void SetCullMode(CullMode mode) const = 0;
|
||||
virtual void SetPolygonMode(PolygonMode mode) const = 0;
|
||||
virtual void SetLineWidth(float width) const = 0;
|
||||
virtual void SetPointSize(float size) const = 0;
|
||||
virtual void SetLineThickness(float thickness) const = 0;
|
||||
|
||||
virtual void BindFramebuffer(uint32_t fbo) const = 0;
|
||||
virtual void BindFramebuffer(FramebufferTarget target, uint32_t fbo) const = 0;
|
||||
virtual void BindTexture(uint32_t slot, uint32_t textureID) const = 0;
|
||||
virtual void BindImageTexture(uint32_t unit, uint32_t textureID, int32_t level, bool layered, int32_t layer, AccessMode access, TextureFormat format) const = 0;
|
||||
virtual void BindTextureUnit(uint32_t i, RendererID rendererId) const = 0;
|
||||
virtual void BindSampler(uint32_t slot, uint32_t samplerID) const = 0;
|
||||
|
||||
virtual void SetReadBuffer(uint32_t attachment) const = 0;
|
||||
virtual void SetDrawBuffer(uint32_t attachment) const = 0;
|
||||
|
||||
virtual void ClearBufferData(Ref<StorageBuffer> buffer, BufferFormat internalFormat, PixelFormat format, DataType type, const void* data) const = 0;
|
||||
|
||||
virtual void GenerateMipmap(uint32_t textureID) const = 0;
|
||||
|
||||
// 绘制
|
||||
virtual void DrawIndexed(uint32_t count, PrimitiveType type, bool depthTest, bool faceCulling) const = 0;
|
||||
virtual void DrawIndexed(PrimitiveType type, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) const = 0;
|
||||
virtual void Draw(PrimitiveType type, uint32_t vertexCount, uint32_t instanceCount,
|
||||
uint32_t firstVertex, uint32_t firstInstance) const = 0;
|
||||
|
||||
// 计算
|
||||
virtual void DispatchCompute(uint32_t groupX, uint32_t groupY, uint32_t groupZ) const = 0;
|
||||
virtual void MemoryBarrier(MemoryBarrierMask barriers) const = 0;
|
||||
|
||||
virtual void Clear(const glm::vec4& color, bool clearColor = true, bool clearDepth = true) const = 0;
|
||||
virtual void SetStencilFunc(CompareOp compare, uint32_t ref, uint32_t mask) const = 0;
|
||||
virtual void SetLineSmooth(bool enable) const = 0;
|
||||
virtual void SetDepthWrite(bool enable) const = 0;
|
||||
|
||||
virtual void CopyImageSubData(uint32_t srcTexture, uint32_t dstTexture,
|
||||
uint32_t srcLevel, uint32_t dstLevel,
|
||||
uint32_t srcX, uint32_t srcY, uint32_t srcZ,
|
||||
uint32_t dstX, uint32_t dstY, uint32_t dstZ,
|
||||
uint32_t width, uint32_t height, uint32_t depth) const = 0;
|
||||
|
||||
virtual void ProgramUniform1f(uint32_t program, int32_t location, float value) const = 0;
|
||||
virtual void BlitFramebuffer(int32_t srcX0, int32_t srcY0, int32_t srcX1, int32_t srcY1,
|
||||
int32_t dstX0, int32_t dstY0, int32_t dstX1, int32_t dstY1,
|
||||
BlitMask mask, BlitFilter filter) const = 0;
|
||||
|
||||
virtual int32_t GetUniformLocation(uint32_t program, const std::string& name) const = 0;
|
||||
|
||||
virtual void UseProgram(uint32_t programID) const = 0;
|
||||
virtual void BindStorageBuffer(uint32_t binding, const Ref<StorageBuffer>& ref) const = 0;
|
||||
|
||||
virtual void ResolveMultisampleTexture(const Ref<FrameBuffer>& src, const Ref<Texture>& dst) const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //PRISM_RHICOMMANDBUFFER_H
|
||||
23
Prism/src/Prism/Renderer/RHI/RHIDevice.cpp
Normal file
23
Prism/src/Prism/Renderer/RHI/RHIDevice.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/31.
|
||||
//
|
||||
|
||||
#include "RHIDevice.h"
|
||||
|
||||
#include "Prism/Platform/OpenGL/OpenGLRHIDevice.h"
|
||||
#include "Prism/Renderer/RendererAPI.h"
|
||||
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
Ref<RHIDevice> RHIDevice::Create()
|
||||
{
|
||||
switch (RendererAPI::Current())
|
||||
{
|
||||
case RendererAPIType::None: return nullptr;
|
||||
case RendererAPIType::OpenGL: return Ref<OpenGLRHIDevice>::Create();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
95
Prism/src/Prism/Renderer/RHI/RHIDevice.h
Normal file
95
Prism/src/Prism/Renderer/RHI/RHIDevice.h
Normal file
@ -0,0 +1,95 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/31.
|
||||
//
|
||||
|
||||
#ifndef PRISM_RHIDEVICE_H
|
||||
#define PRISM_RHIDEVICE_H
|
||||
#include "Prism/Core/Ref.h"
|
||||
#include "Prism/Renderer/RendererAPI.h"
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
struct FramebufferSpecification;
|
||||
struct RenderPassSpecification;
|
||||
class RHICommandBuffer;
|
||||
class StorageBuffer;
|
||||
class RenderPass;
|
||||
class FrameBuffer;
|
||||
class Pipeline;
|
||||
class Shader;
|
||||
class Texture;
|
||||
class IndexBuffer;
|
||||
class VertexBuffer;
|
||||
|
||||
struct BufferDesc {
|
||||
uint32_t Size;
|
||||
uint32_t Usage; // GL_STATIC_DRAW, GL_DYNAMIC_DRAW, etc.
|
||||
// 对于 OpenGL,还需要 target (GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER)
|
||||
uint32_t Target;
|
||||
};
|
||||
|
||||
struct TextureDesc {
|
||||
uint32_t Width, Height, Depth;
|
||||
uint32_t MipLevels;
|
||||
uint32_t Format; // GL_RGBA8, GL_RGBA16F, etc.
|
||||
bool IsCubeMap = false;
|
||||
bool IsArray = false;
|
||||
uint32_t Layers = 1;
|
||||
};
|
||||
|
||||
enum class FilterMode {
|
||||
Nearest, // GL_NEAREST
|
||||
Linear, // GL_LINEAR
|
||||
NearestMipmapNearest, // GL_NEAREST_MIPMAP_NEAREST
|
||||
LinearMipmapNearest, // GL_LINEAR_MIPMAP_NEAREST
|
||||
NearestMipmapLinear, // GL_NEAREST_MIPMAP_LINEAR
|
||||
LinearMipmapLinear // GL_LINEAR_MIPMAP_LINEAR
|
||||
};
|
||||
|
||||
enum class WrapMode {
|
||||
Repeat, // GL_REPEAT
|
||||
MirroredRepeat, // GL_MIRRORED_REPEAT
|
||||
ClampToEdge, // GL_CLAMP_TO_EDGE
|
||||
ClampToBorder, // GL_CLAMP_TO_BORDER
|
||||
MirrorClampToEdge // GL_MIRROR_CLAMP_TO_EDGE (可选)
|
||||
};
|
||||
|
||||
enum class CompareFunc {
|
||||
Never, // GL_NEVER
|
||||
Less, // GL_LESS
|
||||
Equal, // GL_EQUAL
|
||||
LessEqual, // GL_LEQUAL
|
||||
Greater, // GL_GREATER
|
||||
NotEqual, // GL_NOTEQUAL
|
||||
GreaterEqual, // GL_GEQUAL
|
||||
Always // GL_ALWAYS
|
||||
};
|
||||
|
||||
struct SamplerDesc {
|
||||
FilterMode MinFilter = FilterMode::Linear; // 缩小过滤
|
||||
FilterMode MagFilter = FilterMode::Linear; // 放大过滤
|
||||
WrapMode WrapU = WrapMode::Repeat; // U 方向包裹模式
|
||||
WrapMode WrapV = WrapMode::Repeat; // V 方向包裹模式
|
||||
WrapMode WrapW = WrapMode::Repeat; // W 方向包裹模式(3D/数组纹理)
|
||||
float MaxAnisotropy = 1.0f; // 各向异性过滤(1.0 表示禁用)
|
||||
float MipLodBias = 0.0f; // Mipmap LOD 偏移
|
||||
CompareFunc CompareFunc = CompareFunc::Never; // 用于阴影比较的采样器
|
||||
bool EnableCompare = false; // 是否启用比较模式(阴影贴图)
|
||||
glm::vec4 BorderColor = glm::vec4(0.0f); // ClampToBorder 时的边界颜色
|
||||
};
|
||||
|
||||
class PRISM_API RHIDevice : public RefCounted
|
||||
{
|
||||
public:
|
||||
static Ref<RHIDevice> Create();
|
||||
|
||||
virtual ~RHIDevice() = default;
|
||||
virtual Ref<RHICommandBuffer> CreateCommandBuffer() = 0;
|
||||
virtual RendererID CreateSampler(const SamplerDesc& desc) = 0;
|
||||
virtual void DestroySampler(RendererID sampler) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //PRISM_RHIDEVICE_H
|
||||
@ -20,6 +20,7 @@ namespace Prism
|
||||
virtual ~RenderPass() = default;
|
||||
|
||||
virtual RenderPassSpecification& GetSpecification() = 0;
|
||||
virtual const RenderPassSpecification& GetSpecification() const = 0;
|
||||
|
||||
static Ref<RenderPass> Create(const RenderPassSpecification& spec);
|
||||
};
|
||||
|
||||
@ -9,11 +9,16 @@
|
||||
#include "RendererAPI.h"
|
||||
#include "SceneRenderer.h"
|
||||
#include "glad/glad.h"
|
||||
#include "RHI/RHICommandBuffer.h"
|
||||
#include "RHI/RHIDevice.h"
|
||||
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
RendererAPIType RendererAPI::s_CurrentRendererAPI = RendererAPIType::OpenGL;
|
||||
Ref<RHIDevice> Renderer::s_Device;
|
||||
Ref<RHICommandBuffer> Renderer::s_CommandBuffer;
|
||||
|
||||
|
||||
struct RendererData
|
||||
{
|
||||
@ -30,6 +35,9 @@ namespace Prism
|
||||
|
||||
void Renderer::Init()
|
||||
{
|
||||
s_Device = RHIDevice::Create();
|
||||
s_CommandBuffer = s_Device->CreateCommandBuffer();
|
||||
|
||||
s_Data.m_ShaderLibrary = Ref<ShaderLibrary>::Create();
|
||||
Submit([](){ RendererAPI::Init(); });
|
||||
|
||||
@ -42,8 +50,8 @@ namespace Prism
|
||||
// FullScreen Quad
|
||||
static float fullScreenQuadVertex[] = {
|
||||
-1.0f, -1.0f, 0.1f, 0.0f, 0.0f,
|
||||
1.0f, -1.0f, 0.1f, 1.0f, 0.0f,
|
||||
1.0f, 1.0f, 0.1f, 1.0f, 1.0f,
|
||||
1.0f, -1.0f, 0.1f, 1.0f, 0.0f,
|
||||
1.0f, 1.0f, 0.1f, 1.0f, 1.0f,
|
||||
-1.0f, 1.0f, 0.1f, 0.0f, 1.0f
|
||||
};
|
||||
static uint32_t fullScreenQuadIndices[] = {
|
||||
@ -62,18 +70,30 @@ namespace Prism
|
||||
s_Data.m_FullscreenQuadIndexBuffer = IndexBuffer::Create(fullScreenQuadIndices, sizeof(fullScreenQuadIndices[0]) * sizeof(fullScreenQuadIndices));
|
||||
}
|
||||
|
||||
Ref<RHICommandBuffer> Renderer::GetCommandBuffer()
|
||||
{
|
||||
return s_CommandBuffer;
|
||||
}
|
||||
|
||||
Ref<RHIDevice> Renderer::GetDevice()
|
||||
{
|
||||
return s_Device;
|
||||
}
|
||||
|
||||
void Renderer::Clear()
|
||||
{
|
||||
Submit([]()
|
||||
auto cmd = s_CommandBuffer;
|
||||
Submit([cmd]()
|
||||
{
|
||||
RendererAPI::Clear(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
cmd->Clear({0.0f, 0.0f, 0.0f, 1.0f});
|
||||
});
|
||||
}
|
||||
|
||||
void Renderer::Clear(float r, float g, float b, float a)
|
||||
{
|
||||
Submit([=](){
|
||||
RendererAPI::Clear(r, g, b, a);
|
||||
auto cmd = s_CommandBuffer;
|
||||
Submit([r, g, b, a, cmd](){
|
||||
cmd->Clear({r, g, b, a});
|
||||
});
|
||||
}
|
||||
|
||||
@ -81,24 +101,27 @@ namespace Prism
|
||||
{
|
||||
}
|
||||
|
||||
void Renderer::DrawIndexed(const uint32_t count, const PrimitiveType type, const bool depthTest, bool cullFace)
|
||||
Ref<ShaderLibrary> Renderer::GetShaderLibrary()
|
||||
{
|
||||
Submit([=]() {
|
||||
RendererAPI::DrawIndexed(count, type, depthTest, cullFace);
|
||||
});
|
||||
return s_Data.m_ShaderLibrary;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Ref<ShaderLibrary> Renderer::GetShaderLibrary()
|
||||
void Renderer::DrawIndexed(const uint32_t count, const PrimitiveType type, const bool depthTest, bool cullFace)
|
||||
{
|
||||
return s_Data.m_ShaderLibrary;
|
||||
|
||||
auto cmd = s_CommandBuffer;
|
||||
Submit([cmd, count, type, depthTest, cullFace]() {
|
||||
cmd->DrawIndexed(count, type, depthTest, cullFace);
|
||||
});
|
||||
}
|
||||
|
||||
void Renderer::SetLineThickness(const float thickness)
|
||||
{
|
||||
Submit([=]() {
|
||||
RendererAPI::SetLineThickness(thickness);
|
||||
auto cmd = s_CommandBuffer;
|
||||
Submit([cmd, thickness]() {
|
||||
cmd->SetLineThickness(thickness);
|
||||
});
|
||||
}
|
||||
|
||||
@ -116,26 +139,32 @@ namespace Prism
|
||||
|
||||
renderPass->GetSpecification().TargetFramebuffer->Bind();
|
||||
|
||||
if (clear)
|
||||
{
|
||||
const glm::vec4& clearColor = renderPass->GetSpecification().TargetFramebuffer->GetSpecification().ClearColor;
|
||||
Submit([=]() {
|
||||
RendererAPI::Clear(clearColor.r, clearColor.g, clearColor.b, clearColor.a);
|
||||
});
|
||||
}
|
||||
auto cmd = s_CommandBuffer;
|
||||
auto fb = renderPass->GetSpecification().TargetFramebuffer;
|
||||
Submit([cmd, fb, clear]() {
|
||||
cmd->BindFramebuffer(fb->GetRendererID());
|
||||
if (clear)
|
||||
{
|
||||
const glm::vec4& clearColor = fb->GetSpecification().ClearColor;
|
||||
cmd->Clear(clearColor, true, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Renderer::EndRenderPass()
|
||||
{
|
||||
PM_CORE_ASSERT(s_Data.m_ActiveRenderPass, "No active render pass! Have you called Renderer::EndRenderPass twice?");
|
||||
s_Data.m_ActiveRenderPass->GetSpecification().TargetFramebuffer->Unbind();
|
||||
PM_CORE_ASSERT(s_Data.m_ActiveRenderPass, "No active render pass!");
|
||||
auto cmd = s_CommandBuffer;
|
||||
Submit([cmd]() {
|
||||
cmd->BindFramebuffer(0);
|
||||
});
|
||||
s_Data.m_ActiveRenderPass = nullptr;
|
||||
}
|
||||
|
||||
void Renderer::SubmitQuad(Ref<MaterialInstance>& material, const glm::mat4& transform)
|
||||
{
|
||||
bool depthTest = true;
|
||||
bool cullFace = true;
|
||||
bool cullFace = true;
|
||||
|
||||
if (material)
|
||||
{
|
||||
@ -169,7 +198,49 @@ namespace Prism
|
||||
s_Data.m_FullscreenQuadPipeline->Bind();
|
||||
s_Data.m_FullscreenQuadIndexBuffer->Bind();
|
||||
|
||||
Renderer::DrawIndexed(6, PrimitiveType::Triangles, depthTest, cullFace);
|
||||
DrawIndexed(6, PrimitiveType::Triangles, depthTest, cullFace);
|
||||
}
|
||||
|
||||
void Renderer::SubmitMesh(Ref<Mesh>& mesh, const glm::mat4& transform, const std::vector<Ref<MaterialInstance>>& overrideMaterials)
|
||||
{
|
||||
// auto material = overrideMaterial ? overrideMaterial : mesh->GetMaterialInstance();
|
||||
// auto shader = material->GetShader();
|
||||
|
||||
// TODO: Sort this out
|
||||
mesh->m_VertexBuffer->Bind();
|
||||
mesh->m_Pipeline->Bind();
|
||||
mesh->m_IndexBuffer->Bind();
|
||||
|
||||
const auto& materials = mesh->GetMaterials();
|
||||
for (Submesh& submesh : mesh->m_Submeshes)
|
||||
{
|
||||
// Material
|
||||
auto material = overrideMaterials.empty() ? materials[submesh.MaterialIndex] : overrideMaterials[submesh.MaterialIndex];
|
||||
auto shader = material->GetShader();
|
||||
material->Bind();
|
||||
|
||||
if (mesh->m_IsAnimated)
|
||||
{
|
||||
const auto& boneTransform = mesh->GetBoneTransforms();
|
||||
for (size_t i = 0; i < boneTransform.size(); i++)
|
||||
{
|
||||
std::string uniformName = std::string("u_BoneTransforms[") + std::to_string(i) + std::string("]");
|
||||
shader->SetMat4(uniformName, boneTransform[i]);
|
||||
}
|
||||
}
|
||||
shader->SetMat4("u_Transform", transform * submesh.Transform);
|
||||
|
||||
auto cmd = s_CommandBuffer;
|
||||
Submit([cmd, submesh, material]() {
|
||||
// 状态设置通过 cmd
|
||||
cmd->SetDepthTest(material->GetFlag(MaterialFlag::DepthTest));
|
||||
cmd->SetDepthFunc(CompareOp::LessEqual); // 对应 GL_LEQUAL
|
||||
cmd->SetCullMode(material->GetFlag(MaterialFlag::TwoSided) ? CullMode::None : CullMode::Back);
|
||||
|
||||
// 绘制
|
||||
cmd->DrawIndexed(PrimitiveType::Triangles, submesh.IndexCount, 1, submesh.BaseIndex, submesh.BaseVertex, 0);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::SubmitMesh(Ref<Mesh>& mesh, const glm::mat4& transform, const Ref<MaterialInstance>& overrideMaterial)
|
||||
@ -201,19 +272,12 @@ namespace Prism
|
||||
}
|
||||
shader->SetMat4("u_Transform", transform * submesh.Transform);
|
||||
|
||||
Renderer::Submit([submesh, material]() {
|
||||
if (material->GetFlag(MaterialFlag::DepthTest))
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
else
|
||||
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);
|
||||
auto cmd = s_CommandBuffer;
|
||||
Submit([cmd, submesh, material]() {
|
||||
cmd->SetDepthTest(material->GetFlag(MaterialFlag::DepthTest));
|
||||
cmd->SetDepthFunc(CompareOp::LessEqual);
|
||||
cmd->SetCullMode(material->GetFlag(MaterialFlag::TwoSided) ? CullMode::None : CullMode::Back);
|
||||
cmd->DrawIndexed(PrimitiveType::Triangles, submesh.IndexCount, 1, submesh.BaseIndex, submesh.BaseVertex, 0);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -237,38 +301,13 @@ namespace Prism
|
||||
}
|
||||
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);
|
||||
auto cmd = s_CommandBuffer;
|
||||
Submit([cmd, submesh]() {
|
||||
cmd->DrawIndexed(PrimitiveType::Triangles, submesh.IndexCount, 1, submesh.BaseIndex, submesh.BaseVertex, 0);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::DrawAABB(const Ref<Mesh>& mesh, const glm::mat4& transform, const glm::vec4& color)
|
||||
{
|
||||
for (const Submesh& submesh : mesh->m_Submeshes)
|
||||
{
|
||||
const auto& aabb = submesh.BoundingBox;
|
||||
auto aabbTransform = transform * submesh.Transform;
|
||||
DrawAABB(aabb, aabbTransform, color);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::DispatchCompute(int x, int y, int z)
|
||||
{
|
||||
Submit([x, y, z]()
|
||||
{
|
||||
RendererAPI::DispatchCompute(x, y, z);
|
||||
});
|
||||
}
|
||||
|
||||
void Renderer::MemoryBarrier(int barrier)
|
||||
{
|
||||
Submit([barrier]()
|
||||
{
|
||||
RendererAPI::MemoryBarrier(barrier);
|
||||
});
|
||||
}
|
||||
|
||||
void Renderer::DrawAABB(const AABB& aabb, const glm::mat4& transform, const glm::vec4& color)
|
||||
{
|
||||
glm::vec4 min = { aabb.Min.x, aabb.Min.y, aabb.Min.z, 1.0f };
|
||||
@ -297,6 +336,27 @@ namespace Prism
|
||||
Renderer2D::DrawLine(corners[i], corners[i + 4], color);
|
||||
}
|
||||
|
||||
void Renderer::DrawAABB(const Ref<Mesh>& mesh, const glm::mat4& transform, const glm::vec4& color)
|
||||
{
|
||||
for (const Submesh& submesh : mesh->m_Submeshes)
|
||||
{
|
||||
const auto& aabb = submesh.BoundingBox;
|
||||
auto aabbTransform = transform * submesh.Transform;
|
||||
DrawAABB(aabb, aabbTransform, color);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::DispatchCompute(int x, int y, int z)
|
||||
{
|
||||
auto cmd = s_CommandBuffer;
|
||||
Submit([x, y, z, cmd]()
|
||||
{
|
||||
cmd->DispatchCompute(x, y, z);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
RenderCommandQueue& Renderer::GetRenderCommandQueue()
|
||||
{
|
||||
return s_Data.m_CommandQueue;
|
||||
|
||||
@ -13,12 +13,19 @@
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
class PRISM_API Renderer
|
||||
enum class PrimitiveType;
|
||||
class RHICommandBuffer;
|
||||
class RHIDevice;
|
||||
|
||||
class PRISM_API Renderer
|
||||
{
|
||||
public:
|
||||
typedef void(*RenderCommandFn)(void*);
|
||||
static void Init();
|
||||
|
||||
static Ref<RHICommandBuffer> GetCommandBuffer();
|
||||
static Ref<RHIDevice> GetDevice();
|
||||
|
||||
static void Clear();
|
||||
static void Clear(float r, float g, float b, float a = 1.0f);
|
||||
static void SetClearColor(float r, float g, float b, float a);
|
||||
@ -54,16 +61,19 @@ namespace Prism
|
||||
|
||||
static void SubmitQuad(Ref<MaterialInstance>& material, const glm::mat4& transform = glm::mat4(1.0f));
|
||||
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 std::vector<Ref<MaterialInstance>>& overrideMaterials = {});
|
||||
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 Ref<Mesh>& mesh,const glm::mat4& transform, const glm::vec4& color = glm::vec4(1.0f));
|
||||
static void DispatchCompute(int x, int y, int z);
|
||||
static void MemoryBarrier(int barrier);
|
||||
|
||||
private:
|
||||
static RenderCommandQueue& GetRenderCommandQueue();
|
||||
|
||||
static Ref<RHIDevice> s_Device;
|
||||
static Ref<RHICommandBuffer> s_CommandBuffer;
|
||||
};
|
||||
|
||||
#if 0
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include "Renderer.h"
|
||||
#include "Shader.h"
|
||||
#include "VertexArray.h"
|
||||
#include "RHI/RHICommandBuffer.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -33,8 +33,8 @@ namespace Prism
|
||||
static void BeginScene(const Scene* scene, const SceneRendererCamera& camera);
|
||||
static void EndScene(Ref<RenderPass>& renderPass);
|
||||
|
||||
static void SubmitMesh(const Ref<Mesh>& mesh, const glm::mat4& transform = glm::mat4(1.0f), const Ref<MaterialInstance>& overrideMaterial = nullptr);
|
||||
static void SubmitSelectedMesh(const Ref<Mesh>& mesh, const glm::mat4& transform = glm::mat4(1.0f));
|
||||
static void SubmitMesh(const Ref<Mesh>& mesh, const glm::mat4& transform = glm::mat4(1.0f), const std::vector<Ref<MaterialInstance>>& overrideMaterials = {});
|
||||
static void SubmitSelectedMesh(const Ref<Mesh>& mesh, const glm::mat4& transform = glm::mat4(1.0f), const std::vector<Ref<MaterialInstance>>& overrideMaterials = {});
|
||||
|
||||
static void SubmitColliderMesh(const BoxColliderComponent& component, const glm::mat4& parentTransform = glm::mat4(1.0f));
|
||||
static void SubmitColliderMesh(const SphereColliderComponent& component, const glm::mat4& parentTransform = glm::mat4(1.0f));
|
||||
@ -54,6 +54,7 @@ namespace Prism
|
||||
|
||||
static SceneRendererOptions& GetOptions();
|
||||
static Ref<TextureCube> GetBlackCubeTexture();
|
||||
static Ref<Texture2D> GetBlackTexture();
|
||||
|
||||
private:
|
||||
static void FlushDrawList(Ref<RenderPass>& outRenderPass);
|
||||
@ -62,7 +63,7 @@ namespace Prism
|
||||
static void ShadowMapPass();
|
||||
static void GeometryPass();
|
||||
static void BloomBlurPass();
|
||||
static void OverlayPass();
|
||||
static void GridPass();
|
||||
|
||||
static void CompositePass(const Ref<RenderPass>& outRenderPass);
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
enum class PrimitiveType;
|
||||
|
||||
using RendererID = unsigned int;
|
||||
|
||||
@ -16,12 +17,6 @@ namespace Prism
|
||||
OpenGL
|
||||
};
|
||||
|
||||
// TODO: move into separate header
|
||||
enum class PrimitiveType
|
||||
{
|
||||
None = 0, Triangles, Lines
|
||||
};
|
||||
|
||||
struct RenderAPICapabilities
|
||||
{
|
||||
std::string Vendor;
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
#include "Renderer3D.h"
|
||||
|
||||
#include "RenderPass.h"
|
||||
#include "glad/glad.h"
|
||||
|
||||
|
||||
namespace Prism
|
||||
@ -26,7 +27,7 @@ namespace Prism
|
||||
void SceneRenderer::Init()
|
||||
{
|
||||
FramebufferSpecification finalFramebufferSpec;
|
||||
finalFramebufferSpec.Attachments = { FramebufferTextureFormat::RGBA16F, FramebufferTextureFormat::Depth};
|
||||
finalFramebufferSpec.Attachments = { FramebufferTextureFormat::RGBA32F, FramebufferTextureFormat::DEPTH24STENCIL8};
|
||||
finalFramebufferSpec.ClearColor = { 0.1f, 0.1f, 0.1f, 1.0f };
|
||||
|
||||
RenderPassSpecification finalRenderPassSpec;
|
||||
@ -141,14 +142,14 @@ namespace Prism
|
||||
|
||||
//////////////////// 3D API ////////////////////
|
||||
|
||||
void SceneRenderer::SubmitMesh(const Ref<Mesh>& mesh, const glm::mat4& transform, const Ref<MaterialInstance>& overrideMaterial)
|
||||
void SceneRenderer::SubmitMesh(const Ref<Mesh>& mesh, const glm::mat4& transform, const std::vector<Ref<MaterialInstance>>& overrideMaterials)
|
||||
{
|
||||
Renderer3D::SubmitMesh(mesh, transform, overrideMaterial);
|
||||
Renderer3D::SubmitMesh(mesh, transform, overrideMaterials);
|
||||
}
|
||||
|
||||
void SceneRenderer::SubmitSelectedMesh(const Ref<Mesh>& mesh, const glm::mat4& transform)
|
||||
void SceneRenderer::SubmitSelectedMesh(const Ref<Mesh>& mesh, const glm::mat4& transform, const std::vector<Ref<MaterialInstance>>& overrideMaterials)
|
||||
{
|
||||
Renderer3D::SubmitSelectedMesh(mesh, transform);
|
||||
Renderer3D::SubmitSelectedMesh(mesh, transform, overrideMaterials);
|
||||
}
|
||||
|
||||
void SceneRenderer::SubmitColliderMesh(const BoxColliderComponent& component, const glm::mat4& parentTransform)
|
||||
@ -207,4 +208,24 @@ namespace Prism
|
||||
{
|
||||
return Renderer3D::GetOptions();
|
||||
}
|
||||
|
||||
void SceneRenderer::FlushToScreen()
|
||||
{
|
||||
const auto fb = s_Data.FinalPass->GetSpecification().TargetFramebuffer;
|
||||
const auto fbWidth = fb->GetWidth();
|
||||
const auto fbHeight = fb->GetHeight();
|
||||
|
||||
|
||||
|
||||
Renderer::Submit([fb, fbWidth, fbHeight]()
|
||||
{
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, fb->GetColorAttachmentRendererID());
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
|
||||
glBlitFramebuffer(0, 0, fbWidth, fbHeight,
|
||||
0, 0, fbWidth, fbHeight,
|
||||
GL_COLOR_BUFFER_BIT,
|
||||
GL_NEAREST);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,7 +15,7 @@ namespace Prism
|
||||
{
|
||||
struct SceneRendererOptions
|
||||
{
|
||||
bool ShowGrid = true;
|
||||
bool ShowGrid = false;
|
||||
bool ShowBoundingBoxes = false;
|
||||
};
|
||||
|
||||
@ -70,8 +70,8 @@ namespace Prism
|
||||
|
||||
|
||||
// Renderer3D
|
||||
static void SubmitMesh(const Ref<Mesh>& mesh, const glm::mat4& transform = glm::mat4(1.0f), const Ref<MaterialInstance>& overrideMaterial = nullptr);
|
||||
static void SubmitSelectedMesh(const Ref<Mesh>& mesh, const glm::mat4& transform = glm::mat4(1.0f));
|
||||
static void SubmitMesh(const Ref<Mesh>& mesh, const glm::mat4& transform = glm::mat4(1.0f), const std::vector<Ref<MaterialInstance>>& overrideMaterials = {});
|
||||
static void SubmitSelectedMesh(const Ref<Mesh>& mesh, const glm::mat4& transform = glm::mat4(1.0f), const std::vector<Ref<MaterialInstance>>& overrideMaterials = {});
|
||||
|
||||
static void SubmitColliderMesh(const BoxColliderComponent& component, const glm::mat4& parentTransform = glm::mat4(1.0f));
|
||||
static void SubmitColliderMesh(const SphereColliderComponent& component, const glm::mat4& parentTransform = glm::mat4(1.0f));
|
||||
@ -90,7 +90,9 @@ namespace Prism
|
||||
static uint32_t GetFinalColorBufferRendererID();
|
||||
static SceneRendererOptions& GetOptions();
|
||||
static void OnImGuiRender();
|
||||
private:
|
||||
|
||||
|
||||
static void FlushToScreen();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -38,6 +38,16 @@ namespace Prism
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Ref<Texture2D> Texture2D::Create(TextureFormat format, unsigned int width, unsigned int height, const void* data, TextureWrap wrap)
|
||||
{
|
||||
switch (RendererAPI::Current())
|
||||
{
|
||||
case RendererAPIType::None: return nullptr;
|
||||
case RendererAPIType::OpenGL: return Ref<OpenGLTexture2D>::Create(format, width, height, data, wrap);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
Ref<Texture2D> Texture2D::Create(const std::string& path, bool srgb)
|
||||
{
|
||||
|
||||
@ -5,9 +5,9 @@
|
||||
#ifndef TEXTURE_H
|
||||
#define TEXTURE_H
|
||||
#include "RendererAPI.h"
|
||||
#include "Prism/Asset/Asset.h"
|
||||
#include "Prism/Core/Buffer.h"
|
||||
#include "Prism/Core/Ref.h"
|
||||
#include "../Asset/Asset.h"
|
||||
|
||||
|
||||
namespace Prism
|
||||
@ -53,6 +53,7 @@ namespace Prism
|
||||
{
|
||||
public:
|
||||
static Ref<Texture2D> Create(TextureFormat format, unsigned int width, unsigned int height, TextureWrap wrap = TextureWrap::Clamp);
|
||||
static Ref<Texture2D> Create(TextureFormat format, unsigned int width, unsigned int height, const void* data, TextureWrap wrap = TextureWrap::Clamp);
|
||||
static Ref<Texture2D> Create(const std::string& path, bool srgb = false);
|
||||
|
||||
|
||||
@ -62,7 +63,7 @@ namespace Prism
|
||||
|
||||
virtual void Lock() = 0;
|
||||
virtual void Unlock() = 0;
|
||||
virtual void SetData(const void* data, int count) = 0;
|
||||
virtual void SetData(const void* data, uint32_t count) = 0;
|
||||
virtual void Resize(uint32_t width, uint32_t height) = 0;
|
||||
virtual Buffer GetWriteableBuffer() = 0;
|
||||
|
||||
|
||||
@ -81,8 +81,9 @@ namespace Prism
|
||||
}
|
||||
glm::mat4 GetTransform() const
|
||||
{
|
||||
|
||||
return glm::translate(glm::mat4(1.0f), Translation)
|
||||
* glm::toMat4(glm::quat((Rotation)))
|
||||
* glm::toMat4(glm::quat(Rotation))
|
||||
* glm::scale(glm::mat4(1.0f), Scale);
|
||||
}
|
||||
};
|
||||
@ -91,32 +92,112 @@ namespace Prism
|
||||
struct MeshComponent
|
||||
{
|
||||
Ref<Mesh> Mesh;
|
||||
// std::vector<Ref<MaterialInstance>> Materials;
|
||||
std::vector<Ref<MaterialInstance>> MaterialInstances;
|
||||
std::vector<Ref<PBRMaterialAsset>> MaterialDescs;
|
||||
|
||||
MeshComponent() = default;
|
||||
MeshComponent(const MeshComponent& other) = default;
|
||||
MeshComponent(const MeshComponent& other)
|
||||
: Mesh(other.Mesh)
|
||||
{
|
||||
MaterialInstances.clear();
|
||||
MaterialDescs.clear();
|
||||
for (auto i = 0; i < other.MaterialInstances.size(); i ++)
|
||||
{
|
||||
Ref<MaterialInstance> materialInstance = MaterialInstance::Copy(other.MaterialInstances[i]);
|
||||
MaterialInstances.push_back(materialInstance);
|
||||
MaterialDescs.push_back(other.MaterialDescs[i]);
|
||||
}
|
||||
UpdateMaterials();
|
||||
}
|
||||
MeshComponent(const Ref<Prism::Mesh>& mesh)
|
||||
: Mesh(mesh) {}
|
||||
|
||||
operator Ref<Prism::Mesh> () { return Mesh; }
|
||||
|
||||
/*
|
||||
MeshComponent(Ref<Prism::Mesh> mesh)
|
||||
: Mesh(mesh)
|
||||
{
|
||||
// 复制 Mesh 的材质实例,每个实体拥有独立副本
|
||||
if (mesh)
|
||||
MaterialInstances.clear();
|
||||
MaterialDescs.clear();
|
||||
const auto& materialInstances = Mesh->GetMaterials();
|
||||
for (const auto & i : materialInstances)
|
||||
{
|
||||
const auto& srcMaterials = mesh->GetMaterials();
|
||||
Materials.reserve(srcMaterials.size());
|
||||
for (auto& srcMat : srcMaterials)
|
||||
Ref<MaterialInstance> materialInstance = MaterialInstance::Copy(i);
|
||||
MaterialInstances.push_back(materialInstance);
|
||||
}
|
||||
MaterialDescs.resize(materialInstances.size());
|
||||
}
|
||||
|
||||
void UpdateMaterials(const int index = -1, bool forceUpdate = false)
|
||||
{
|
||||
if (index <= -1)
|
||||
{
|
||||
for (uint32_t i = 0; i < MaterialInstances.size(); i++)
|
||||
{
|
||||
auto newMat = MaterialInstance::Copy(srcMat);
|
||||
Materials.push_back(newMat);
|
||||
if (auto& desc = MaterialDescs[i])
|
||||
{
|
||||
if (!desc->IsDirty && !forceUpdate) continue;
|
||||
MaterialInstances[i]->Set("u_AlbedoColor", desc->AlbedoColor);
|
||||
MaterialInstances[i]->Set("u_AlbedoTexToggle", desc->AlbedoTexToggle);
|
||||
MaterialInstances[i]->Set("u_AlbedoTexture", desc->AlbedoTexture);
|
||||
MaterialInstances[i]->Set("u_NormalTexToggle", desc->NormalTexToggle);
|
||||
MaterialInstances[i]->Set("u_NormalTexture", desc->NormalTexture);
|
||||
MaterialInstances[i]->Set("u_Metalness", desc->Metalness);
|
||||
MaterialInstances[i]->Set("u_MetalnessTexToggle", desc->MetalnessTexToggle);
|
||||
MaterialInstances[i]->Set("u_MetalnessTexture", desc->MetalnessTexture);
|
||||
MaterialInstances[i]->Set("u_Roughness", desc->Roughness);
|
||||
MaterialInstances[i]->Set("u_RoughnessTexToggle", desc->RoughnessTexToggle);
|
||||
MaterialInstances[i]->Set("u_RoughnessTexture", desc->RoughnessTexture);
|
||||
}else
|
||||
{
|
||||
auto& baseMaterial = Mesh->GetMaterials();
|
||||
|
||||
MaterialInstances[i]->Set("u_AlbedoColor", baseMaterial[i]->Get<glm::vec3>("u_AlbedoColor"));
|
||||
MaterialInstances[i]->Set("u_AlbedoTexToggle", baseMaterial[i]->Get<float>("u_AlbedoTexToggle"));
|
||||
MaterialInstances[i]->Set("u_AlbedoTexture", baseMaterial[i]->TryGetResource<Texture2D>("u_AlbedoTexture"));
|
||||
MaterialInstances[i]->Set("u_NormalTexToggle", baseMaterial[i]->Get<float>("u_NormalTexToggle"));
|
||||
MaterialInstances[i]->Set("u_NormalTexture", baseMaterial[i]->TryGetResource<Texture2D>("u_NormalTexture"));
|
||||
MaterialInstances[i]->Set("u_Metalness", baseMaterial[i]->Get<float>("u_Metalness"));
|
||||
MaterialInstances[i]->Set("u_MetalnessTexToggle", baseMaterial[i]->Get<float>("u_MetalnessTexToggle"));
|
||||
MaterialInstances[i]->Set("u_MetalnessTexture", baseMaterial[i]->TryGetResource<Texture2D>("u_MetalnessTexture"));
|
||||
MaterialInstances[i]->Set("u_Roughness", baseMaterial[0]->Get<float>("u_Roughness"));
|
||||
MaterialInstances[i]->Set("u_RoughnessTexToggle", baseMaterial[i]->Get<float>("u_RoughnessTexToggle"));
|
||||
MaterialInstances[i]->Set("u_RoughnessTexture", baseMaterial[i]->TryGetResource<Texture2D>("u_RoughnessTexture"));
|
||||
}
|
||||
}
|
||||
}else
|
||||
{
|
||||
if (index >= MaterialInstances.size()) return;
|
||||
const auto& desc = MaterialDescs[index];
|
||||
if (desc)
|
||||
{
|
||||
MaterialInstances[index]->Set("u_AlbedoColor", desc->AlbedoColor);
|
||||
MaterialInstances[index]->Set("u_AlbedoTexToggle", desc->AlbedoTexToggle);
|
||||
MaterialInstances[index]->Set("u_AlbedoTexture", desc->AlbedoTexture);
|
||||
MaterialInstances[index]->Set("u_NormalTexToggle", desc->NormalTexToggle);
|
||||
MaterialInstances[index]->Set("u_NormalTexture", desc->NormalTexture);
|
||||
MaterialInstances[index]->Set("u_Metalness", desc->Metalness);
|
||||
MaterialInstances[index]->Set("u_MetalnessTexToggle", desc->MetalnessTexToggle);
|
||||
MaterialInstances[index]->Set("u_MetalnessTexture", desc->MetalnessTexture);
|
||||
MaterialInstances[index]->Set("u_Roughness", desc->Roughness);
|
||||
MaterialInstances[index]->Set("u_RoughnessTexToggle", desc->RoughnessTexToggle);
|
||||
MaterialInstances[index]->Set("u_RoughnessTexture", desc->RoughnessTexture);
|
||||
}else
|
||||
{
|
||||
auto& baseMaterial = Mesh->GetMaterials();
|
||||
|
||||
MaterialInstances[index]->Set("u_AlbedoColor", baseMaterial[index]->Get<glm::vec3>("u_AlbedoColor"));
|
||||
MaterialInstances[index]->Set("u_AlbedoTexToggle", baseMaterial[index]->Get<float>("u_AlbedoTexToggle"));
|
||||
MaterialInstances[index]->Set("u_AlbedoTexture", baseMaterial[index]->TryGetResource<Texture2D>("u_AlbedoTexture"));
|
||||
MaterialInstances[index]->Set("u_NormalTexToggle", baseMaterial[index]->Get<float>("u_NormalTexToggle"));
|
||||
MaterialInstances[index]->Set("u_NormalTexture", baseMaterial[index]->TryGetResource<Texture2D>("u_NormalTexture"));
|
||||
MaterialInstances[index]->Set("u_Metalness", baseMaterial[index]->Get<float>("u_Metalness"));
|
||||
MaterialInstances[index]->Set("u_MetalnessTexToggle", baseMaterial[index]->Get<float>("u_MetalnessTexToggle"));
|
||||
MaterialInstances[index]->Set("u_MetalnessTexture", baseMaterial[index]->TryGetResource<Texture2D>("u_MetalnessTexture"));
|
||||
MaterialInstances[index]->Set("u_Roughness", baseMaterial[0]->Get<float>("u_Roughness"));
|
||||
MaterialInstances[index]->Set("u_RoughnessTexToggle", baseMaterial[index]->Get<float>("u_RoughnessTexToggle"));
|
||||
MaterialInstances[index]->Set("u_RoughnessTexture", baseMaterial[index]->TryGetResource<Texture2D>("u_RoughnessTexture"));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
operator Ref<Prism::Mesh> () { return Mesh; }
|
||||
};
|
||||
|
||||
struct AnimationComponent
|
||||
@ -305,7 +386,7 @@ namespace Prism
|
||||
{
|
||||
float Radius = 0.5f;
|
||||
bool IsTrigger = false;
|
||||
Ref<PhysicsMaterial> Material;
|
||||
Ref<PhysicsMaterialAsset> Material;
|
||||
|
||||
// The mesh that will be drawn in the editor to show the collision bounds
|
||||
Ref<Mesh> DebugMesh;
|
||||
@ -344,7 +425,7 @@ namespace Prism
|
||||
glm::vec3 Size = { 1.0f, 1.0f, 1.0f };
|
||||
glm::vec3 Offset = { 0.0f, 0.0f, 0.0f };
|
||||
bool IsTrigger = false;
|
||||
Ref<PhysicsMaterial> Material;
|
||||
Ref<PhysicsMaterialAsset> Material;
|
||||
|
||||
// The mesh that will be drawn in the editor to show the collision bounds
|
||||
Ref<Mesh> DebugMesh;
|
||||
@ -358,7 +439,7 @@ namespace Prism
|
||||
float Radius = 0.5f;
|
||||
float Height = 1.0f;
|
||||
bool IsTrigger = false;
|
||||
Ref<PhysicsMaterial> Material;
|
||||
Ref<PhysicsMaterialAsset> Material;
|
||||
|
||||
Ref<Mesh> DebugMesh;
|
||||
|
||||
@ -373,7 +454,7 @@ namespace Prism
|
||||
bool IsConvex = false;
|
||||
bool IsTrigger = false;
|
||||
bool OverrideMesh = false;
|
||||
Ref<PhysicsMaterial> Material;
|
||||
Ref<PhysicsMaterialAsset> Material;
|
||||
|
||||
MeshColliderComponent() = default;
|
||||
MeshColliderComponent(const MeshColliderComponent& other) = default;
|
||||
@ -431,7 +512,7 @@ namespace Prism
|
||||
bool ShowIcon = false;
|
||||
|
||||
bool DynamicSky = false;
|
||||
glm::vec3 TurbidityAzimuthInclination = { 2.0, 0.0, 0.0 };
|
||||
glm::vec3 TurbidityAzimuthInclination = { 2.0, 0.0, 1.0 };
|
||||
|
||||
SkyLightComponent(const Ref<Environment>& environment)
|
||||
: SceneEnvironment(environment)
|
||||
|
||||
@ -32,12 +32,7 @@ namespace Prism
|
||||
|
||||
static uint32_t s_SceneIDCounter = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Scene::Scene(const std::string& debugName, const bool isEditorScene)
|
||||
Scene::Scene(const std::string& debugName, const bool isEditorScene, const bool runtime)
|
||||
: m_SceneID(++s_SceneIDCounter), m_DebugName(debugName)
|
||||
{
|
||||
m_Registry.on_construct<TransformComponent>().connect<&Physics2D::OnTransformConstruct>();
|
||||
@ -56,10 +51,11 @@ namespace Prism
|
||||
Physics3D::CreateScene();
|
||||
}
|
||||
|
||||
Init();
|
||||
Init(runtime);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Scene::~Scene()
|
||||
{
|
||||
m_Registry.on_destroy<ScriptComponent>().disconnect();
|
||||
@ -68,20 +64,24 @@ namespace Prism
|
||||
s_ActiveScenes.erase(m_SceneID);
|
||||
}
|
||||
|
||||
void Scene::Init()
|
||||
void Scene::Init(const bool runtime)
|
||||
{
|
||||
const auto skyboxShader = Shader::Create("assets/shaders/Skybox.glsl");
|
||||
m_SkyboxMaterial = MaterialInstance::Create(Material::Create(skyboxShader));
|
||||
m_SkyboxMaterial->SetFlag(MaterialFlag::DepthTest, false);
|
||||
|
||||
m_CameraIcon = AssetsManager::GetAsset<Texture2D>("assets/editor/Camera.png");
|
||||
m_LightIcon = AssetsManager::GetAsset<Texture2D>("assets/editor/light.png");
|
||||
|
||||
if (!runtime)
|
||||
{
|
||||
m_CameraIcon = AssetsManager::GetAsset<Texture2D>("assets/editor/Camera.png");
|
||||
m_LightIcon = AssetsManager::GetAsset<Texture2D>("assets/editor/light.png");
|
||||
}
|
||||
}
|
||||
|
||||
void Scene::OnShutdown()
|
||||
{
|
||||
b2DestroyWorld(m_Registry.get<Box2DWorldComponent>(m_SceneEntity).World);
|
||||
Physics3D::DestroyScene();
|
||||
ScriptEngine::OnSceneDestruct(m_SceneID);
|
||||
}
|
||||
|
||||
void Scene::OnUpdate(TimeStep ts)
|
||||
@ -91,14 +91,14 @@ namespace Prism
|
||||
|
||||
const auto sceneView = m_Registry.view<Box2DWorldComponent>();
|
||||
const auto& box2DWorld = m_Registry.get<Box2DWorldComponent>(sceneView.front()).World;
|
||||
int32_t velocityIterations = 6;
|
||||
constexpr int32_t positionIterations = 2;
|
||||
// box2DWorld->Step(ts, velocityIterations, positionIterations);
|
||||
b2World_Step(box2DWorld, ts, positionIterations);
|
||||
|
||||
// Process Contact Envents box2d version 3.0^ should impl contact event after b2World_Step
|
||||
Physics2D::ProcessContactEvents(box2DWorld);
|
||||
|
||||
// Physics3D
|
||||
Physics3D::Simulate(ts);
|
||||
|
||||
{
|
||||
const auto view = m_Registry.view<RigidBody2DComponent>();
|
||||
for (const auto entity : view)
|
||||
@ -138,8 +138,6 @@ namespace Prism
|
||||
}
|
||||
|
||||
|
||||
Physics3D::Simulate(ts);
|
||||
|
||||
// Update all entities
|
||||
{
|
||||
const auto view = m_Registry.view<ScriptComponent>();
|
||||
@ -150,6 +148,7 @@ namespace Prism
|
||||
ScriptEngine::OnUpdateEntity(e, ts);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Scene::OnRenderRuntime(const TimeStep ts)
|
||||
@ -189,19 +188,35 @@ namespace Prism
|
||||
SceneRenderer::BeginScene(this, { static_cast<Camera>(camera), cameraViewMatrix }, false);
|
||||
{
|
||||
const auto group = m_Registry.group<MeshComponent>(entt::get<TransformComponent>);
|
||||
|
||||
// this maybe not to set
|
||||
// in Editor actually only one materialdesc will be changed
|
||||
Ref<PBRMaterialAsset> materialAsset;
|
||||
|
||||
for (const auto entity : group)
|
||||
{
|
||||
const auto& [transformComponent, meshComponent] = group.get<TransformComponent, MeshComponent>(entity);
|
||||
if (meshComponent.Mesh)
|
||||
{
|
||||
|
||||
for (auto i = 0; i < meshComponent.MaterialInstances.size(); i++)
|
||||
{
|
||||
if (meshComponent.MaterialDescs[i] && meshComponent.MaterialDescs[i]->IsDirty)
|
||||
{
|
||||
materialAsset = meshComponent.MaterialDescs[i];
|
||||
meshComponent.UpdateMaterials(i);
|
||||
}
|
||||
}
|
||||
|
||||
meshComponent.Mesh->OnUpdate(ts);
|
||||
|
||||
glm::mat4 transform = GetTransformRelativeToParent(Entity(entity, this));
|
||||
|
||||
// TODO: Should we render (logically)
|
||||
SceneRenderer::SubmitMesh(meshComponent, transform);
|
||||
SceneRenderer::SubmitMesh(meshComponent, transform, meshComponent.MaterialInstances);
|
||||
}
|
||||
}
|
||||
if (materialAsset) materialAsset->IsDirty = false;
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
@ -224,7 +239,9 @@ namespace Prism
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
SceneRenderer::FlushToScreen();
|
||||
SceneRenderer::EndScene();
|
||||
|
||||
}
|
||||
|
||||
void Scene::OnRenderEditor(const TimeStep ts, const EditorCamera& editorCamera)
|
||||
@ -270,21 +287,35 @@ namespace Prism
|
||||
|
||||
const auto group = m_Registry.group<MeshComponent>(entt::get<TransformComponent>);
|
||||
{
|
||||
|
||||
// in Editor actually only one materialdesc will be changed
|
||||
Ref<PBRMaterialAsset> materialAsset;
|
||||
|
||||
for (const auto [entity, meshComponent, transformComponent]: group.each())
|
||||
{
|
||||
Entity e = {entity, this};
|
||||
|
||||
if (meshComponent.Mesh)
|
||||
{
|
||||
|
||||
for (auto i = 0; i < meshComponent.MaterialInstances.size(); i++)
|
||||
{
|
||||
if (meshComponent.MaterialDescs[i] && meshComponent.MaterialDescs[i]->IsDirty)
|
||||
{
|
||||
materialAsset = meshComponent.MaterialDescs[i];
|
||||
meshComponent.UpdateMaterials(i);
|
||||
}
|
||||
}
|
||||
|
||||
meshComponent.Mesh->OnUpdate(ts);
|
||||
|
||||
glm::mat4 transform = GetTransformRelativeToParent(e);
|
||||
|
||||
// TODO: Should we render (logically)
|
||||
if (m_SelectedEntity == entity)
|
||||
SceneRenderer::SubmitSelectedMesh(meshComponent, transform);
|
||||
SceneRenderer::SubmitSelectedMesh(meshComponent, transform, meshComponent.MaterialInstances);
|
||||
else
|
||||
SceneRenderer::SubmitMesh(meshComponent, transform);
|
||||
SceneRenderer::SubmitMesh(meshComponent, transform, meshComponent.MaterialInstances);
|
||||
}
|
||||
|
||||
// Renderer Collider
|
||||
@ -302,6 +333,8 @@ namespace Prism
|
||||
SceneRenderer::SubmitColliderMesh(*collider, transform);
|
||||
}
|
||||
}
|
||||
|
||||
if (materialAsset) materialAsset->IsDirty = false;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -431,6 +464,12 @@ namespace Prism
|
||||
m_IsPlaying = false;
|
||||
}
|
||||
|
||||
void Scene::SetViewportSize(const glm::ivec2& viewportSize)
|
||||
{
|
||||
m_ViewportWidth = viewportSize.x;
|
||||
m_ViewportHeight = viewportSize.y;
|
||||
}
|
||||
|
||||
void Scene::SetViewportSize(const uint32_t width, const uint32_t height)
|
||||
{
|
||||
m_ViewportWidth = width;
|
||||
|
||||
@ -74,10 +74,10 @@ namespace Prism
|
||||
class PRISM_API Scene : public RefCounted
|
||||
{
|
||||
public:
|
||||
Scene(const std::string& debugName = "Scene", bool isEditorScene = false);
|
||||
Scene(const std::string& debugName = "Scene", bool isEditorScene = false, bool runtime = false);
|
||||
~Scene();
|
||||
|
||||
void Init();
|
||||
void Init(bool runtime);
|
||||
void OnShutdown();
|
||||
|
||||
void OnUpdate(TimeStep ts);
|
||||
@ -88,6 +88,7 @@ namespace Prism
|
||||
void OnRuntimeStart();
|
||||
void OnRuntimeStop();
|
||||
|
||||
void SetViewportSize(const glm::ivec2& viewportSize);
|
||||
void SetViewportSize(uint32_t width, uint32_t height);
|
||||
|
||||
const Ref<Environment>& GetEnvironment() const { return m_Environment; }
|
||||
@ -168,7 +169,7 @@ namespace Prism
|
||||
Ref<TextureCube> m_SkyboxTexture;
|
||||
Ref<MaterialInstance> m_SkyboxMaterial;
|
||||
|
||||
float m_SkyboxLod = 1.0f;
|
||||
float m_SkyboxLod = 0.0f;
|
||||
|
||||
|
||||
Ref<Texture2D> m_CameraIcon;
|
||||
|
||||
@ -13,142 +13,13 @@
|
||||
#include "Prism/Physics/PhysicsLayer.h"
|
||||
#include "Prism/Physics/PhysicsWrappers.h"
|
||||
#include "Prism/Renderer/Meshfactory.h"
|
||||
#include "../Asset/AssetsManager.h"
|
||||
#include "Prism/Asset/AssetsManager.h"
|
||||
|
||||
namespace YAML
|
||||
{
|
||||
|
||||
template<>
|
||||
struct convert<glm::vec2>
|
||||
{
|
||||
static Node encode(const glm::vec2& rhs)
|
||||
{
|
||||
Node node;
|
||||
node.push_back(rhs.x);
|
||||
node.push_back(rhs.y);
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool decode(const Node& node, glm::vec2& rhs)
|
||||
{
|
||||
if (!node.IsSequence() || node.size() != 2)
|
||||
return false;
|
||||
|
||||
rhs.x = node[0].as<float>();
|
||||
rhs.y = node[1].as<float>();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct convert<glm::vec3>
|
||||
{
|
||||
static Node encode(const glm::vec3& rhs)
|
||||
{
|
||||
Node node;
|
||||
node.push_back(rhs.x);
|
||||
node.push_back(rhs.y);
|
||||
node.push_back(rhs.z);
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool decode(const Node& node, glm::vec3& rhs)
|
||||
{
|
||||
if (!node.IsSequence() || node.size() != 3)
|
||||
return false;
|
||||
|
||||
rhs.x = node[0].as<float>();
|
||||
rhs.y = node[1].as<float>();
|
||||
rhs.z = node[2].as<float>();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct convert<glm::vec4>
|
||||
{
|
||||
static Node encode(const glm::vec4& rhs)
|
||||
{
|
||||
Node node;
|
||||
node.push_back(rhs.x);
|
||||
node.push_back(rhs.y);
|
||||
node.push_back(rhs.z);
|
||||
node.push_back(rhs.w);
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool decode(const Node& node, glm::vec4& rhs)
|
||||
{
|
||||
if (!node.IsSequence() || node.size() != 4)
|
||||
return false;
|
||||
|
||||
rhs.x = node[0].as<float>();
|
||||
rhs.y = node[1].as<float>();
|
||||
rhs.z = node[2].as<float>();
|
||||
rhs.w = node[3].as<float>();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct convert<glm::quat>
|
||||
{
|
||||
static Node encode(const glm::quat& rhs)
|
||||
{
|
||||
Node node;
|
||||
node.push_back(rhs.w);
|
||||
node.push_back(rhs.x);
|
||||
node.push_back(rhs.y);
|
||||
node.push_back(rhs.z);
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool decode(const Node& node, glm::quat& rhs)
|
||||
{
|
||||
if (!node.IsSequence() || node.size() != 4)
|
||||
return false;
|
||||
|
||||
rhs.w = node[0].as<float>();
|
||||
rhs.x = node[1].as<float>();
|
||||
rhs.y = node[2].as<float>();
|
||||
rhs.z = node[3].as<float>();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
#include "Prism/Utilities/SerializeUtils.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
|
||||
YAML::Emitter& operator<<(YAML::Emitter& out, const glm::vec2& v)
|
||||
{
|
||||
out << YAML::Flow;
|
||||
out << YAML::BeginSeq << v.x << v.y << YAML::EndSeq;
|
||||
return out;
|
||||
}
|
||||
|
||||
YAML::Emitter& operator<<(YAML::Emitter& out, const glm::vec3& v)
|
||||
{
|
||||
out << YAML::Flow;
|
||||
out << YAML::BeginSeq << v.x << v.y << v.z << YAML::EndSeq;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
YAML::Emitter& operator<<(YAML::Emitter& out, const glm::vec4& v)
|
||||
{
|
||||
out << YAML::Flow;
|
||||
out << YAML::BeginSeq << v.x << v.y << v.z << v.w << YAML::EndSeq;
|
||||
return out;
|
||||
}
|
||||
|
||||
YAML::Emitter& operator<<(YAML::Emitter& out, const glm::quat& v)
|
||||
{
|
||||
out << YAML::Flow;
|
||||
out << YAML::BeginSeq << v.w << v.x << v.y << v.z << YAML::EndSeq;
|
||||
return out;
|
||||
}
|
||||
|
||||
SceneSerializer::SceneSerializer(const Ref<Scene>& scene)
|
||||
: m_Scene(scene)
|
||||
{
|
||||
@ -163,7 +34,7 @@ namespace Prism
|
||||
|
||||
if (entity.HasComponent<RelationshipComponent>())
|
||||
{
|
||||
auto& relationshipComponent = entity.GetComponent<RelationshipComponent>();
|
||||
const auto& relationshipComponent = entity.GetComponent<RelationshipComponent>();
|
||||
out << YAML::Key << "Parent" << YAML::Value << relationshipComponent.ParentHandle;
|
||||
|
||||
out << YAML::Key << "Children";
|
||||
@ -258,11 +129,44 @@ namespace Prism
|
||||
out << YAML::Key << "MeshComponent";
|
||||
out << YAML::BeginMap; // MeshComponent
|
||||
|
||||
const auto mesh = entity.GetComponent<MeshComponent>().Mesh;
|
||||
if (mesh)
|
||||
const auto& meshComponent = entity.GetComponent<MeshComponent>();
|
||||
if (meshComponent.Mesh)
|
||||
{
|
||||
const auto& mesh = meshComponent.Mesh;
|
||||
out << YAML::Key << "AssetID" << YAML::Value << mesh->Handle;
|
||||
out << YAML::Key << "AssetPath" << YAML::Value << mesh->FilePath;
|
||||
|
||||
if (!meshComponent.MaterialDescs.empty())
|
||||
{
|
||||
|
||||
out << YAML::Key << "Materials";
|
||||
out << YAML::BeginMap;
|
||||
for (auto i = 0; i < meshComponent.MaterialDescs.size(); ++i)
|
||||
{
|
||||
{
|
||||
std::string slots = "Slot " + std::to_string(i);
|
||||
out << YAML::Key << slots;
|
||||
out << YAML::BeginMap;
|
||||
if (meshComponent.MaterialDescs[i])
|
||||
{
|
||||
out << YAML::Key << "AssetHandle" << YAML::Value << meshComponent.MaterialDescs[i]->Handle;
|
||||
out << YAML::Key << "AssetPath" << YAML::Value << meshComponent.MaterialDescs[i]->FilePath;
|
||||
}else
|
||||
{
|
||||
out << YAML::Key << "AssetHandle" << YAML::Value << 0;
|
||||
out << YAML::Key << "AssetPath" << YAML::Value << "";
|
||||
}
|
||||
out << YAML::EndMap;
|
||||
}
|
||||
}
|
||||
out << YAML::EndMap;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
out << YAML::Key << "AssetID" << YAML::Value << 0;
|
||||
out << YAML::Key << "AssetPath" << YAML::Value << "";
|
||||
}
|
||||
|
||||
out << YAML::EndMap; // MeshComponent
|
||||
}
|
||||
@ -287,7 +191,16 @@ namespace Prism
|
||||
out << YAML::BeginMap; // SkyLightComponent
|
||||
|
||||
const auto& skyLightComponent = entity.GetComponent<SkyLightComponent>();
|
||||
out << YAML::Key << "EnvironmentMap" << YAML::Value << skyLightComponent.SceneEnvironment->Handle;
|
||||
if (skyLightComponent.SceneEnvironment)
|
||||
{
|
||||
out << YAML::Key << "EnvironmentMap" << YAML::Value << skyLightComponent.SceneEnvironment->Handle;
|
||||
out << YAML::Key << "EnvironmentAssetPath" << YAML::Value << skyLightComponent.SceneEnvironment->FilePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
out << YAML::Key << "EnvironmentMap" << YAML::Value << 0;
|
||||
out << YAML::Key << "EnvironmentAssetPath" << YAML::Value << "";
|
||||
}
|
||||
out << YAML::Key << "Intensity" << YAML::Value << skyLightComponent.Intensity;
|
||||
out << YAML::Key << "Angle" << YAML::Value << skyLightComponent.Angle;
|
||||
|
||||
@ -518,9 +431,16 @@ namespace Prism
|
||||
out << YAML::Key << "IsTrigger" << YAML::Value << boxColliderComponent.IsTrigger;
|
||||
|
||||
if (boxColliderComponent.Material)
|
||||
{
|
||||
out << YAML::Key << "Material" << YAML::Value << boxColliderComponent.Material->Handle;
|
||||
out << YAML::Key << "MaterialPath" << YAML::Value << boxColliderComponent.Material->FilePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
out << YAML::Key << "Material" << YAML::Value << 0;
|
||||
out << YAML::Key << "MaterialPath" << YAML::Value << "";
|
||||
}
|
||||
|
||||
|
||||
out << YAML::EndMap; // BoxColliderComponent
|
||||
}
|
||||
@ -535,9 +455,16 @@ namespace Prism
|
||||
out << YAML::Key << "IsTrigger" << YAML::Value << sphereColliderComponent.IsTrigger;
|
||||
|
||||
if (sphereColliderComponent.Material)
|
||||
{
|
||||
out << YAML::Key << "Material" << YAML::Value << sphereColliderComponent.Material->Handle;
|
||||
out << YAML::Key << "MaterialPath" << YAML::Value << sphereColliderComponent.Material->FilePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
out << YAML::Key << "Material" << YAML::Value << 0;
|
||||
out << YAML::Key << "MaterialPath" << YAML::Value << "";
|
||||
}
|
||||
|
||||
|
||||
out << YAML::EndMap; // SphereColliderComponent
|
||||
}
|
||||
@ -552,10 +479,18 @@ namespace Prism
|
||||
out << YAML::Key << "Height" << YAML::Value << capsuleColliderComponent.Height;
|
||||
out << YAML::Key << "IsTrigger" << YAML::Value << capsuleColliderComponent.IsTrigger;
|
||||
|
||||
|
||||
if (capsuleColliderComponent.Material)
|
||||
{
|
||||
out << YAML::Key << "Material" << YAML::Value << capsuleColliderComponent.Material->Handle;
|
||||
out << YAML::Key << "MaterialPath" << YAML::Value << capsuleColliderComponent.Material->FilePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
out << YAML::Key << "Material" << YAML::Value << 0;
|
||||
out << YAML::Key << "MaterialPath" << YAML::Value << "";
|
||||
}
|
||||
|
||||
|
||||
out << YAML::EndMap; // CapsuleColliderComponent
|
||||
}
|
||||
@ -565,19 +500,27 @@ namespace Prism
|
||||
out << YAML::Key << "MeshColliderComponent";
|
||||
out << YAML::BeginMap; // MeshColliderComponent
|
||||
|
||||
auto meshColliderComponent = entity.GetComponent<MeshColliderComponent>();
|
||||
|
||||
if (meshColliderComponent.OverrideMesh)
|
||||
const auto& meshColliderComponent = entity.GetComponent<MeshColliderComponent>();
|
||||
if (meshColliderComponent.OverrideMesh && meshColliderComponent.CollisionMesh)
|
||||
{
|
||||
out << YAML::Key << "AssetID" << YAML::Value << meshColliderComponent.CollisionMesh->Handle;
|
||||
out << YAML::Key << "AssetPath" << YAML::Value << meshColliderComponent.CollisionMesh->FilePath;
|
||||
}
|
||||
|
||||
out << YAML::Key << "IsConvex" << YAML::Value << meshColliderComponent.IsConvex;
|
||||
out << YAML::Key << "IsTrigger" << YAML::Value << meshColliderComponent.IsTrigger;
|
||||
out << YAML::Key << "OverrideMesh" << YAML::Value << meshColliderComponent.OverrideMesh;
|
||||
|
||||
if (meshColliderComponent.Material)
|
||||
{
|
||||
out << YAML::Key << "Material" << YAML::Value << meshColliderComponent.Material->Handle;
|
||||
out << YAML::Key << "MaterialPath" << YAML::Value << meshColliderComponent.Material->FilePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
out << YAML::Key << "Material" << YAML::Value << 0;
|
||||
out << YAML::Key << "MaterialPath" << YAML::Value << "";
|
||||
}
|
||||
|
||||
out << YAML::EndMap; // MeshColliderComponent
|
||||
}
|
||||
@ -829,7 +772,7 @@ namespace Prism
|
||||
if (meshComponent["AssetPath"])
|
||||
{
|
||||
const std::string assetFilePath = meshComponent["AssetPath"].as<std::string>();
|
||||
assetID = AssetsManager::GetAssetHandleFromFilePath(filepath);
|
||||
assetID = AssetsManager::GetAssetHandleFromFilePath(assetFilePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -838,7 +781,46 @@ namespace Prism
|
||||
|
||||
if (AssetsManager::IsAssetHandleValid(assetID) && !deserializedEntity.HasComponent<MeshComponent>())
|
||||
{
|
||||
deserializedEntity.AddComponent<MeshComponent>(AssetsManager::GetAsset<Mesh>(assetID));
|
||||
auto& mc = deserializedEntity.AddComponent<MeshComponent>(AssetsManager::GetAsset<Mesh>(assetID));
|
||||
|
||||
if (meshComponent["Materials"])
|
||||
{
|
||||
auto materialsNode = meshComponent["Materials"];
|
||||
// 遍历 "Slot X" 键
|
||||
for (auto it = materialsNode.begin(); it != materialsNode.end(); ++it)
|
||||
{
|
||||
std::string slotKey = it->first.as<std::string>();
|
||||
if (slotKey.rfind("Slot ", 0) == 0) // 确保是 "Slot X"
|
||||
{
|
||||
int slotIndex = std::stoi(slotKey.substr(5));
|
||||
auto slotNode = it->second;
|
||||
|
||||
// 获取材质资产的 Handle
|
||||
UUID materialHandle = 0;
|
||||
if (slotNode["AssetPath"])
|
||||
{
|
||||
std::string matPath = slotNode["AssetPath"].as<std::string>();
|
||||
if (!matPath.empty())
|
||||
materialHandle = AssetsManager::GetAssetHandleFromFilePath(matPath);
|
||||
}
|
||||
else if (slotNode["AssetHandle"])
|
||||
{
|
||||
materialHandle = slotNode["AssetHandle"].as<uint64_t>();
|
||||
}
|
||||
|
||||
// 调整 MaterialDescs 大小(确保索引有效)
|
||||
if (slotIndex >= mc.MaterialDescs.size())
|
||||
mc.MaterialDescs.resize(slotIndex + 1);
|
||||
|
||||
// 加载材质资产并赋值
|
||||
if (materialHandle != 0 && AssetsManager::IsAssetHandleValid(materialHandle))
|
||||
mc.MaterialDescs[slotIndex] = AssetsManager::GetAsset<PBRMaterialAsset>(materialHandle);
|
||||
else
|
||||
mc.MaterialDescs[slotIndex] = nullptr;
|
||||
}
|
||||
}
|
||||
mc.UpdateMaterials(-1, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -858,8 +840,8 @@ namespace Prism
|
||||
AssetHandle assetHandle;
|
||||
if (skyLightComponent["EnvironmentAssetPath"])
|
||||
{
|
||||
const auto filePath = skyLightComponent["EnvironmentAssetPath"].as<std::string>();
|
||||
assetHandle = AssetsManager::GetAssetHandleFromFilePath(filepath);
|
||||
const auto assetFilePath = skyLightComponent["EnvironmentAssetPath"].as<std::string>();
|
||||
assetHandle = AssetsManager::GetAssetHandleFromFilePath(assetFilePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1054,10 +1036,18 @@ namespace Prism
|
||||
auto material = boxColliderComponent["Material"];
|
||||
if (material && AssetsManager::IsAssetHandleValid(material.as<uint64_t>()))
|
||||
{
|
||||
component.Material = AssetsManager::GetAsset<PhysicsMaterial>(material.as<uint64_t>());
|
||||
component.Material = AssetsManager::GetAsset<PhysicsMaterialAsset>(material.as<uint64_t>());
|
||||
}else
|
||||
{
|
||||
const auto materialPath = boxColliderComponent["MaterialPath"].as<std::string>();
|
||||
if (const auto assetId = AssetsManager::GetAssetHandleFromFilePath(materialPath); assetId != 0)
|
||||
{
|
||||
component.Material = AssetsManager::GetAsset<PhysicsMaterialAsset>(assetId);
|
||||
}
|
||||
}
|
||||
|
||||
component.DebugMesh = MeshFactory::CreateBox(component.Size);
|
||||
|
||||
component.DebugMesh = MeshFactory::CreateBox(component.Size * 2.0f);
|
||||
}
|
||||
|
||||
if (auto sphereColliderComponent = entity["SphereColliderComponent"])
|
||||
@ -1068,7 +1058,17 @@ namespace Prism
|
||||
|
||||
auto material = sphereColliderComponent["Material"];
|
||||
if (material && AssetsManager::IsAssetHandleValid(material.as<uint64_t>()))
|
||||
component.Material = AssetsManager::GetAsset<PhysicsMaterial>(material.as<uint64_t>());
|
||||
{
|
||||
component.Material = AssetsManager::GetAsset<PhysicsMaterialAsset>(material.as<uint64_t>());
|
||||
}else
|
||||
{
|
||||
const auto materialPath = sphereColliderComponent["MaterialPath"].as<std::string>();
|
||||
if (const auto assetId = AssetsManager::GetAssetHandleFromFilePath(materialPath); assetId != 0)
|
||||
{
|
||||
component.Material = AssetsManager::GetAsset<PhysicsMaterialAsset>(assetId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
component.DebugMesh = MeshFactory::CreateSphere(component.Radius);
|
||||
}
|
||||
@ -1082,7 +1082,16 @@ namespace Prism
|
||||
|
||||
auto material = capsuleColliderComponent["Material"];
|
||||
if (material && AssetsManager::IsAssetHandleValid(material.as<uint64_t>()))
|
||||
component.Material = AssetsManager::GetAsset<PhysicsMaterial>(material.as<uint64_t>());
|
||||
{
|
||||
component.Material = AssetsManager::GetAsset<PhysicsMaterialAsset>(material.as<uint64_t>());
|
||||
}else
|
||||
{
|
||||
const auto materialPath = capsuleColliderComponent["MaterialPath"].as<std::string>();
|
||||
if (const auto assetId = AssetsManager::GetAssetHandleFromFilePath(materialPath); assetId != 0)
|
||||
{
|
||||
component.Material = AssetsManager::GetAsset<PhysicsMaterialAsset>(assetId);
|
||||
}
|
||||
}
|
||||
|
||||
component.DebugMesh = MeshFactory::CreateCapsule(component.Radius, component.Height);
|
||||
}
|
||||
@ -1095,14 +1104,14 @@ namespace Prism
|
||||
if (overrideMesh)
|
||||
{
|
||||
UUID assetID;
|
||||
if (meshComponent["AssetPath"])
|
||||
if (meshColliderComponent["AssetPath"])
|
||||
{
|
||||
const auto assetFilePath = meshComponent["AssetPath"].as<std::string>();
|
||||
assetID = AssetsManager::GetAssetHandleFromFilePath(filepath);
|
||||
const auto assetFilePath = meshColliderComponent["AssetPath"].as<std::string>();
|
||||
assetID = AssetsManager::GetAssetHandleFromFilePath(assetFilePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
assetID = meshComponent["AssetID"].as<uint64_t>();
|
||||
assetID = meshColliderComponent["AssetID"].as<uint64_t>();
|
||||
}
|
||||
|
||||
if (AssetsManager::IsAssetHandleValid(assetID))
|
||||
@ -1116,16 +1125,33 @@ namespace Prism
|
||||
component.IsTrigger = meshColliderComponent["IsTrigger"] ? meshColliderComponent["IsTrigger"].as<bool>() : false;
|
||||
component.OverrideMesh = overrideMesh;
|
||||
|
||||
auto material = meshColliderComponent["Material"];
|
||||
if (material && AssetsManager::IsAssetHandleValid(material.as<uint64_t>()))
|
||||
if (meshColliderComponent["Material"])
|
||||
{
|
||||
component.Material = AssetsManager::GetAsset<PhysicsMaterial>(material.as<uint64_t>());
|
||||
auto material = meshColliderComponent["Material"];
|
||||
if (material && AssetsManager::IsAssetHandleValid(material.as<uint64_t>()))
|
||||
{
|
||||
component.Material = AssetsManager::GetAsset<PhysicsMaterialAsset>(material.as<uint64_t>());
|
||||
|
||||
if (component.IsConvex)
|
||||
PhysicsWrappers::CreateConvexMesh(component, deserializedEntity.Transform().Scale);
|
||||
else
|
||||
PhysicsWrappers::CreateTriangleMesh(component, deserializedEntity.Transform().Scale);
|
||||
if (component.IsConvex)
|
||||
PhysicsWrappers::CreateConvexMesh(component, deserializedEntity.Transform().Scale);
|
||||
else
|
||||
PhysicsWrappers::CreateTriangleMesh(component, deserializedEntity.Transform().Scale);
|
||||
}else
|
||||
{
|
||||
const auto materialPath = meshColliderComponent["MaterialPath"].as<std::string>();
|
||||
if (const auto assetId = AssetsManager::GetAssetHandleFromFilePath(materialPath); assetId != 0)
|
||||
{
|
||||
component.Material = AssetsManager::GetAsset<PhysicsMaterialAsset>(assetId);
|
||||
|
||||
if (component.IsConvex)
|
||||
PhysicsWrappers::CreateConvexMesh(component, deserializedEntity.Transform().Scale);
|
||||
else
|
||||
PhysicsWrappers::CreateTriangleMesh(component, deserializedEntity.Transform().Scale);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1139,7 +1165,7 @@ namespace Prism
|
||||
if (physicsMaterialComponent)
|
||||
{
|
||||
//auto& component = deserializedEntity.AddComponent<PhysicsMaterialComponent>();
|
||||
Ref<PhysicsMaterial> material = Ref<PhysicsMaterial>::Create();
|
||||
Ref<PhysicsMaterialAsset> material = Ref<PhysicsMaterialAsset>::Create();
|
||||
material->StaticFriction = physicsMaterialComponent["StaticFriction"].as<float>();
|
||||
material->DynamicFriction = physicsMaterialComponent["DynamicFriction"].as<float>();
|
||||
material->Bounciness = physicsMaterialComponent["Bounciness"].as<float>();
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
//
|
||||
|
||||
#include "ScriptEngine.h"
|
||||
#include <cstddef>
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
@ -35,6 +36,10 @@ namespace Prism
|
||||
MonoImage* s_AppAssemblyImage = nullptr;
|
||||
MonoImage* s_CoreAssemblyImage = nullptr;
|
||||
|
||||
|
||||
|
||||
std::vector<std::string> ScriptEngine::s_AvailableScripts;
|
||||
|
||||
#ifdef ENABLE_MONO_DEBUG
|
||||
static bool s_EnableMonoPDBDebug = true;
|
||||
#else
|
||||
@ -87,6 +92,7 @@ namespace Prism
|
||||
static std::unordered_map<std::string, EntityScriptClass> s_EntityClassMap;
|
||||
|
||||
|
||||
|
||||
MonoAssembly* LoadAssemblyFromFile(const char* filepath)
|
||||
{
|
||||
if (!filepath) {
|
||||
@ -390,6 +396,12 @@ namespace Prism
|
||||
|
||||
void ScriptEngine::Init(const std::string& assemblyPath)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
_putenv("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1");
|
||||
#else
|
||||
setenv("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", "1", 1);
|
||||
#endif
|
||||
|
||||
s_AssemblyPath = assemblyPath;
|
||||
|
||||
InitMono();
|
||||
@ -429,8 +441,8 @@ namespace Prism
|
||||
s_CoreAssembly = LoadAssembly("assets/scripts/Prism-ScriptCore.dll");
|
||||
s_CoreAssemblyImage = GetAssemblyImage(s_CoreAssembly);
|
||||
|
||||
auto appAssembly = LoadAssembly(path);
|
||||
auto appAssemblyImage = GetAssemblyImage(appAssembly);
|
||||
const auto appAssembly = LoadAssembly(path);
|
||||
const auto appAssemblyImage = GetAssemblyImage(appAssembly);
|
||||
ScriptEngineRegistry::RegisterAll();
|
||||
|
||||
if (cleanup)
|
||||
@ -441,6 +453,8 @@ namespace Prism
|
||||
|
||||
s_AppAssembly = appAssembly;
|
||||
s_AppAssemblyImage = appAssemblyImage;
|
||||
|
||||
RefreshAvailableScripts();
|
||||
}
|
||||
|
||||
void ScriptEngine::ReloadAssembly(const std::string& path)
|
||||
@ -845,6 +859,43 @@ namespace Prism
|
||||
return entityIDMap.at(entityID);
|
||||
}
|
||||
|
||||
void ScriptEngine::RefreshAvailableScripts()
|
||||
{
|
||||
if (!s_AppAssemblyImage) return;
|
||||
s_AvailableScripts.clear();
|
||||
|
||||
// 获取类型定义表
|
||||
const MonoTableInfo *tableInfo = mono_image_get_table_info(s_AppAssemblyImage, MONO_TABLE_TYPEDEF);
|
||||
int rows = mono_image_get_table_rows(s_AppAssemblyImage, MONO_TABLE_TYPEDEF);
|
||||
|
||||
for (int i = 0; i < rows; i++)
|
||||
{
|
||||
uint32_t cols[MONO_TYPEDEF_SIZE];
|
||||
mono_metadata_decode_row(tableInfo, i, cols, MONO_TYPEDEF_SIZE);
|
||||
|
||||
// 获取类名和命名空间
|
||||
const char* name = mono_metadata_string_heap(s_AppAssemblyImage, cols[MONO_TYPEDEF_NAME]);
|
||||
const char* nameSpace = mono_metadata_string_heap(s_AppAssemblyImage, cols[MONO_TYPEDEF_NAMESPACE]);
|
||||
|
||||
if (!name || strlen(name) == 0) continue;
|
||||
|
||||
// 构建全名
|
||||
std::string fullName;
|
||||
if (nameSpace && strlen(nameSpace) > 0)
|
||||
fullName = std::string(nameSpace) + "." + name;
|
||||
else
|
||||
fullName = name;
|
||||
|
||||
s_AvailableScripts.push_back(fullName);
|
||||
PM_CORE_DEBUG("Script Class: {}", fullName);
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<std::string>& ScriptEngine::GetAvailableScripts()
|
||||
{
|
||||
return s_AvailableScripts;
|
||||
}
|
||||
|
||||
void ScriptEngine::OnImGuiRender()
|
||||
{
|
||||
ImGui::Begin("Script Engine Debug");
|
||||
|
||||
@ -150,8 +150,15 @@ namespace Prism
|
||||
static EntityInstanceMap& GetEntityInstanceMap();
|
||||
static EntityInstanceData& GetEntityInstanceData(UUID sceneID, UUID entityID);
|
||||
|
||||
// GetAll Script Clas s
|
||||
static const std::vector<std::string>& GetAvailableScripts();
|
||||
static void RefreshAvailableScripts();
|
||||
|
||||
// Debug
|
||||
static void OnImGuiRender();
|
||||
|
||||
private:
|
||||
static std::vector<std::string> s_AvailableScripts;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -49,6 +49,8 @@ namespace Prism
|
||||
{
|
||||
InitComponentTypes();
|
||||
|
||||
mono_add_internal_call("Prism.Debug::Log_Native", (const void*)Prism::Script::Prism_Log_Native);
|
||||
|
||||
mono_add_internal_call("Prism.Noise::PerlinNoise_Native", (const void*)Prism::Script::Prism_Noise_PerlinNoise);
|
||||
|
||||
mono_add_internal_call("Prism.Physics::Raycast_Native", (const void*)Prism::Script::Prism_Physics_Raycast);
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
#include <mono/metadata/object.h>
|
||||
#include <mono/metadata/reflection.h>
|
||||
#include <mono/metadata/appdomain.h>
|
||||
#include <mono/utils/mono-publib.h>
|
||||
|
||||
#include "Prism/Core/Input.h"
|
||||
#include "Prism/Core/Math/Noise.h"
|
||||
@ -32,6 +33,31 @@ namespace Prism { namespace Script {
|
||||
SpriteRenderer = 4
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Debug ////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
static LogCallback s_LogCallback = nullptr;
|
||||
|
||||
void SetLogCallback(const LogCallback& callback)
|
||||
{
|
||||
s_LogCallback = callback;
|
||||
}
|
||||
|
||||
void Prism_Log_Native(MonoString* message)
|
||||
{
|
||||
if (message)
|
||||
{
|
||||
if (char* utf8 = mono_string_to_utf8(message))
|
||||
{
|
||||
PM_CLIENT_INFO("[c#]: {}", utf8);
|
||||
if (s_LogCallback) s_LogCallback(utf8);
|
||||
mono_free(utf8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Math ////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////
|
||||
@ -385,7 +411,8 @@ namespace Prism { namespace Script {
|
||||
|
||||
Entity entity = entityMap.at(entityID);
|
||||
|
||||
auto& transform = entity.GetComponent<TransformComponent>() = *inTransform;
|
||||
auto& transform = entity.GetComponent<TransformComponent>();
|
||||
transform = *inTransform;
|
||||
transform.Rotation = glm::radians(transform.Rotation);
|
||||
}
|
||||
|
||||
@ -454,7 +481,13 @@ namespace Prism { namespace Script {
|
||||
PM_CORE_ASSERT(entityMap.find(entityID) != entityMap.end(), "Invalid entity ID or entity doesn't exist in scene!");
|
||||
|
||||
Entity entity = entityMap.at(entityID);
|
||||
entity.GetComponent<TransformComponent>().Rotation = glm::radians(*inRotation);
|
||||
auto& transformComponent = entity.GetComponent<TransformComponent>();
|
||||
transformComponent.Rotation = glm::radians(*inRotation);
|
||||
|
||||
const auto rotationQuat = glm::quat(transformComponent.Rotation);
|
||||
transformComponent.Up = glm::normalize(glm::rotate(rotationQuat, glm::vec3(0.0f, 1.0f, 0.0f)));
|
||||
transformComponent.Right = glm::normalize(glm::rotate(rotationQuat, glm::vec3(1.0f, 0.0f, 0.0f)));
|
||||
transformComponent.Forward = glm::normalize(glm::rotate(rotationQuat, glm::vec3(0.0f, 0.0f, -1.0f)));
|
||||
}
|
||||
|
||||
void Prism_TransformComponent_GetScale(uint64_t entityID, glm::vec3* outScale)
|
||||
|
||||
@ -14,7 +14,11 @@ extern "C" {
|
||||
typedef struct _MonoArray MonoArray;
|
||||
}
|
||||
|
||||
namespace Prism { namespace Script {
|
||||
namespace Prism::Script
|
||||
{
|
||||
|
||||
using LogCallback = std::function<void(const char*)>;
|
||||
void SetLogCallback(const LogCallback& callback);
|
||||
|
||||
/*
|
||||
struct ScriptTransform
|
||||
@ -26,6 +30,9 @@ namespace Prism { namespace Script {
|
||||
};
|
||||
*/
|
||||
|
||||
// Debug
|
||||
void Prism_Log_Native(MonoString* message);
|
||||
|
||||
// Math
|
||||
float Prism_Noise_PerlinNoise(float x, float y);
|
||||
|
||||
@ -114,7 +121,7 @@ namespace Prism { namespace Script {
|
||||
|
||||
void* Prism_MeshComponent_GetMesh(uint64_t entityID);
|
||||
void Prism_MeshComponent_SetMesh(uint64_t entityID, const Ref<Mesh>* inMesh);
|
||||
} }
|
||||
}
|
||||
|
||||
|
||||
#endif //SCRIPTWRAPPERS_H
|
||||
|
||||
@ -38,6 +38,8 @@ namespace Prism
|
||||
static std::string OpenFileSelector(const std::string& filter = "");
|
||||
static std::string SaveFileSelector(const std::string& filter = "");
|
||||
|
||||
static void OpenInExplorer(const std::string& path);
|
||||
|
||||
static bool CreateFolder(const std::filesystem::path& filepath);
|
||||
static bool Exists(const std::string& filepath);
|
||||
static std::string Rename(const std::string& filepath, const std::string& newName);
|
||||
|
||||
145
Prism/src/Prism/Utilities/SerializeUtils.h
Normal file
145
Prism/src/Prism/Utilities/SerializeUtils.h
Normal file
@ -0,0 +1,145 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/25.
|
||||
//
|
||||
|
||||
#ifndef PRISM_SERIALIZEUTILS_H
|
||||
#define PRISM_SERIALIZEUTILS_H
|
||||
|
||||
#include <yaml-cpp/yaml.h>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
namespace YAML
|
||||
{
|
||||
template<>
|
||||
struct convert<glm::vec2>
|
||||
{
|
||||
static Node encode(const glm::vec2& rhs)
|
||||
{
|
||||
Node node;
|
||||
node.push_back(rhs.x);
|
||||
node.push_back(rhs.y);
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool decode(const Node& node, glm::vec2& rhs)
|
||||
{
|
||||
if (!node.IsSequence() || node.size() != 2)
|
||||
return false;
|
||||
|
||||
rhs.x = node[0].as<float>();
|
||||
rhs.y = node[1].as<float>();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct convert<glm::vec3>
|
||||
{
|
||||
static Node encode(const glm::vec3& rhs)
|
||||
{
|
||||
Node node;
|
||||
node.push_back(rhs.x);
|
||||
node.push_back(rhs.y);
|
||||
node.push_back(rhs.z);
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool decode(const Node& node, glm::vec3& rhs)
|
||||
{
|
||||
if (!node.IsSequence() || node.size() != 3)
|
||||
return false;
|
||||
|
||||
rhs.x = node[0].as<float>();
|
||||
rhs.y = node[1].as<float>();
|
||||
rhs.z = node[2].as<float>();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct convert<glm::vec4>
|
||||
{
|
||||
static Node encode(const glm::vec4& rhs)
|
||||
{
|
||||
Node node;
|
||||
node.push_back(rhs.x);
|
||||
node.push_back(rhs.y);
|
||||
node.push_back(rhs.z);
|
||||
node.push_back(rhs.w);
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool decode(const Node& node, glm::vec4& rhs)
|
||||
{
|
||||
if (!node.IsSequence() || node.size() != 4)
|
||||
return false;
|
||||
|
||||
rhs.x = node[0].as<float>();
|
||||
rhs.y = node[1].as<float>();
|
||||
rhs.z = node[2].as<float>();
|
||||
rhs.w = node[3].as<float>();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct convert<glm::quat>
|
||||
{
|
||||
static Node encode(const glm::quat& rhs)
|
||||
{
|
||||
Node node;
|
||||
node.push_back(rhs.w);
|
||||
node.push_back(rhs.x);
|
||||
node.push_back(rhs.y);
|
||||
node.push_back(rhs.z);
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool decode(const Node& node, glm::quat& rhs)
|
||||
{
|
||||
if (!node.IsSequence() || node.size() != 4)
|
||||
return false;
|
||||
|
||||
rhs.w = node[0].as<float>();
|
||||
rhs.x = node[1].as<float>();
|
||||
rhs.y = node[2].as<float>();
|
||||
rhs.z = node[3].as<float>();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
inline YAML::Emitter& operator<<(YAML::Emitter& out, const glm::vec2& v)
|
||||
{
|
||||
out << YAML::Flow;
|
||||
out << YAML::BeginSeq << v.x << v.y << YAML::EndSeq;
|
||||
return out;
|
||||
}
|
||||
|
||||
inline YAML::Emitter& operator<<(YAML::Emitter& out, const glm::vec3& v)
|
||||
{
|
||||
out << YAML::Flow;
|
||||
out << YAML::BeginSeq << v.x << v.y << v.z << YAML::EndSeq;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
inline YAML::Emitter& operator<<(YAML::Emitter& out, const glm::vec4& v)
|
||||
{
|
||||
out << YAML::Flow;
|
||||
out << YAML::BeginSeq << v.x << v.y << v.z << v.w << YAML::EndSeq;
|
||||
return out;
|
||||
}
|
||||
|
||||
inline YAML::Emitter& operator<<(YAML::Emitter& out, const glm::quat& v)
|
||||
{
|
||||
out << YAML::Flow;
|
||||
out << YAML::BeginSeq << v.w << v.x << v.y << v.z << YAML::EndSeq;
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif //PRISM_SERIALIZEUTILS_H
|
||||
@ -4,6 +4,8 @@
|
||||
|
||||
#include "StringUtils.h"
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
namespace Prism::Utils
|
||||
{
|
||||
|
||||
@ -17,10 +19,16 @@ namespace Prism::Utils
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string ReplaceFilePathName(const std::string& filepath, const std::string& newName)
|
||||
{
|
||||
const std::string extension = GetExtension(filepath, true);
|
||||
return std::filesystem::path(filepath).parent_path().string() + "/" + newName + extension;
|
||||
}
|
||||
|
||||
std::string GetExtension(const std::string& filename, const bool includeDot)
|
||||
{
|
||||
if (const std::vector<std::string> parts = SplitString(filename, '.'); parts.size() > 1)
|
||||
return parts[ includeDot ? parts.size() - 1 : parts.size()];
|
||||
return (includeDot ? "." : "") + parts[parts.size() - 1];
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
@ -9,8 +9,10 @@
|
||||
|
||||
namespace Prism::Utils
|
||||
{
|
||||
std::string ReplaceFilePathName(const std::string& filepath, const std::string& newName);
|
||||
|
||||
std::string GetFilename(const std::string& filepath);
|
||||
std::string GetExtension(const std::string& filename, bool includeDot = true);
|
||||
std::string GetExtension(const std::string& filename, bool includeDot = false);
|
||||
std::string RemoveExtension(const std::string& filename);
|
||||
std::string NormalizePath(std::string path);
|
||||
std::string StringToLower(const std::string& str);
|
||||
|
||||
11
PrismRuntime/CMakeLists.txt
Normal file
11
PrismRuntime/CMakeLists.txt
Normal file
@ -0,0 +1,11 @@
|
||||
project(PrismRuntime)
|
||||
|
||||
file(GLOB_RECURSE SRC_SOURCE ./PrismRuntime/**.cpp)
|
||||
|
||||
add_executable(${PROJECT_NAME} WIN32 ${SRC_SOURCE})
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE PRISM_GUI)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE Prism-Runtime)
|
||||
|
||||
|
||||
add_executable(${PROJECT_NAME}-Console ${SRC_SOURCE})
|
||||
target_link_libraries(${PROJECT_NAME}-Console PRIVATE Prism-Runtime)
|
||||
90
PrismRuntime/PrismRuntime/PrismRuntime.cpp
Normal file
90
PrismRuntime/PrismRuntime/PrismRuntime.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/23.
|
||||
//
|
||||
|
||||
#include "PrismRuntime.h"
|
||||
|
||||
#include "Prism/Core/Input.h"
|
||||
#include "Prism/Renderer/Renderer.h"
|
||||
#include "Prism/Renderer/SceneRenderer.h"
|
||||
#include "Prism/Scene/SceneSerializer.h"
|
||||
|
||||
|
||||
void PrismRuntime::OnAttach()
|
||||
{
|
||||
PM_CLIENT_INFO("App init");
|
||||
|
||||
AppInstance = &Prism::Application::Get();
|
||||
|
||||
sceneName.emplace_back("assets/scenes/FPS.scene");
|
||||
sceneName.emplace_back("assets/scenes/FPSdemo.scene");
|
||||
|
||||
LoadScene(sceneName[0]);
|
||||
}
|
||||
|
||||
void PrismRuntime::OnDetach()
|
||||
{
|
||||
PM_CLIENT_INFO("Scene Shutdown");
|
||||
m_CurrentScene->OnShutdown();
|
||||
}
|
||||
|
||||
void PrismRuntime::LoadScene(const std::string& scene)
|
||||
{
|
||||
if (m_CurrentScene)
|
||||
{
|
||||
PM_CLIENT_INFO("Scene Shutdown");
|
||||
m_CurrentScene->OnShutdown();
|
||||
}
|
||||
|
||||
const Prism::Ref<Prism::Scene> newScene = Prism::Ref<Prism::Scene>::Create("runtime Scene", false, true);
|
||||
Prism::SceneSerializer serializer(newScene);
|
||||
|
||||
PM_CLIENT_INFO("loading Scene: ", scene);
|
||||
serializer.Deserialize(scene);
|
||||
|
||||
m_CurrentScene = newScene;
|
||||
|
||||
const glm::ivec2 windowSize = AppInstance->GetWindow().GetSize();
|
||||
if (m_CurrentScene && windowSize.x > 0 && windowSize.y > 0)
|
||||
{
|
||||
Prism::SceneRenderer::SetViewportSize(windowSize.x, windowSize.y);
|
||||
m_CurrentScene->SetViewportSize(windowSize);
|
||||
}
|
||||
|
||||
m_CurrentScene->OnRuntimeStart();
|
||||
}
|
||||
|
||||
void PrismRuntime::OnUpdate(const Prism::TimeStep deltaTime)
|
||||
{
|
||||
m_CurrentScene->OnUpdate(deltaTime);
|
||||
m_CurrentScene->OnRenderRuntime(deltaTime);
|
||||
|
||||
const glm::vec2 windowSize = AppInstance->GetWindow().GetSize();
|
||||
if (m_CurrentScene && windowSize.x > 0 && windowSize.y > 0)
|
||||
{
|
||||
m_CurrentScene->SetViewportSize(windowSize);
|
||||
}
|
||||
|
||||
if (shouldChangeScene)
|
||||
{
|
||||
LoadScene(sceneName[nextScene]);
|
||||
shouldChangeScene = false;
|
||||
}
|
||||
}
|
||||
|
||||
void PrismRuntime::OnEvent(Prism::Event& e)
|
||||
{
|
||||
if (Prism::Input::IsKeyPressed(Prism::KeyCode::L) && nextScene == 0)
|
||||
{
|
||||
shouldChangeScene = true;
|
||||
nextScene++;
|
||||
} else if (Prism::Input::IsKeyPressed(Prism::KeyCode::K) && nextScene == 1)
|
||||
{
|
||||
shouldChangeScene = true;
|
||||
nextScene--;
|
||||
}
|
||||
}
|
||||
|
||||
void PrismRuntime::OnImGuiRender()
|
||||
{
|
||||
}
|
||||
38
PrismRuntime/PrismRuntime/PrismRuntime.h
Normal file
38
PrismRuntime/PrismRuntime/PrismRuntime.h
Normal file
@ -0,0 +1,38 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/23.
|
||||
//
|
||||
|
||||
#ifndef PRISM_PRISMRUNTIME_H
|
||||
#define PRISM_PRISMRUNTIME_H
|
||||
#include "Prism/Core/Application.h"
|
||||
#include "Prism/Core/Layer.h"
|
||||
#include "Prism/Scene/Scene.h"
|
||||
|
||||
|
||||
class PrismRuntime : public Prism::Layer
|
||||
{
|
||||
public:
|
||||
void OnAttach() override;
|
||||
void OnDetach() override;
|
||||
|
||||
void LoadScene(const std::string& scene);
|
||||
|
||||
void OnUpdate(Prism::TimeStep deltaTime) override;
|
||||
void OnEvent(Prism::Event& e) override;
|
||||
void OnImGuiRender() override;
|
||||
|
||||
|
||||
private:
|
||||
Prism::Ref<Prism::Scene> m_CurrentScene;
|
||||
|
||||
Prism::Application* AppInstance = nullptr;
|
||||
|
||||
bool shouldChangeScene = false;
|
||||
|
||||
// debug
|
||||
std::vector<std::string> sceneName;
|
||||
int nextScene = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif //PRISM_PRISMRUNTIME_H
|
||||
25
PrismRuntime/PrismRuntime/PrismRuntimeApp.cpp
Normal file
25
PrismRuntime/PrismRuntime/PrismRuntimeApp.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/23.
|
||||
//
|
||||
#include "Prism.h"
|
||||
#include "PrismRuntime.h"
|
||||
#include "Prism/Core/EntryPoint.h"
|
||||
|
||||
class PrismRuntimeApp : public Prism::Application
|
||||
{
|
||||
public:
|
||||
explicit PrismRuntimeApp(const Prism::ApplicationProps& props)
|
||||
: Application(props)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void OnInit() override
|
||||
{
|
||||
PushLayer(new PrismRuntime());
|
||||
}
|
||||
};
|
||||
|
||||
Prism::Application* Prism::CreateApplication(const CommandArgs args)
|
||||
{
|
||||
return new PrismRuntimeApp({"Game", 1920, 1080, args});
|
||||
}
|
||||
Reference in New Issue
Block a user