diff options
| author | hachem <im@hachem.wtf> | 2025-08-15 03:18:29 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2025-08-15 03:18:29 +0200 |
| commit | 4172869e54093eee6e1595ebe0fa55c9fe98aef7 (patch) | |
| tree | 2004c518688e6db529e437fe3f0120ad0fcc1dd9 /src/Engine/Engine.cpp | |
| parent | bc2d88c799cb3913a5defe4ea9ddea9c56814349 (diff) | |
[help]: Complete first geodesic 3d raytracing
Diffstat (limited to 'src/Engine/Engine.cpp')
| -rw-r--r-- | src/Engine/Engine.cpp | 318 |
1 files changed, 114 insertions, 204 deletions
diff --git a/src/Engine/Engine.cpp b/src/Engine/Engine.cpp index 614e8e5..ac0e891 100644 --- a/src/Engine/Engine.cpp +++ b/src/Engine/Engine.cpp @@ -1,251 +1,144 @@ -#include "Engine.h" -#include <GLFW/glfw3.h> -#include <glad/glad.h> #include <iostream> #include <fstream> #include <sstream> -#include <limits> + +#include <GLFW/glfw3.h> + +#include "Engine.h" #include "Rendering/VertexBuffer.h" #include "Rendering/IndexBuffer.h" namespace Donut { - Engine::Engine() - : m_SagA(glm::vec3(0.0f, 0.0f, 0.0f), - static_cast<float>(8.54e36)) + Engine::Engine() + : m_SagA(glm::vec3(0.0f, 0.0f, 0.0f), 8.54e36f) { GLFWwindow* window = static_cast<GLFWwindow*>(Application::Get().GetWindow().GetNativeWindow()); glfwGetFramebufferSize(window, &m_Width, &m_Height); - m_ComputeHeight = 420; - m_ComputeWidth = (m_Width * 420) / m_Height; - m_Camera.SetOrbitalMode(true); - m_Camera.SetRadius(6.34194e10); - m_Camera.SetMinRadius(1e10); - m_Camera.SetMaxRadius(1e12); - m_Camera.SetOrbitSpeed(0.01f); + m_Camera.SetCameraMode(CameraMode::Orbital); + m_Camera.SetOrbitalRadius(6.34194e10); + m_Camera.SetOrbitalLimits(1e10, 1e12); + m_Camera.SetOrbitalSpeed(0.01f); m_Camera.SetZoomSpeed(25e9f); m_Objects = { - { glm::vec4(4e11f, 0.0f, 0.0f, 4e10f), glm::vec4(1,1,0,1), static_cast<float>(1.98892e30) }, - { glm::vec4(0.0f, 0.0f, 4e11f, 4e10f), glm::vec4(1,0,0,1), static_cast<float>(1.98892e30) }, - { glm::vec4(0.0f, 0.0f, 0.0f, m_SagA.m_Rs), glm::vec4(0,0,0,1), static_cast<float>(m_SagA.m_Mass) } + { glm::vec4(4e11f, 0.00f, 0.00f, 4e10f), glm::vec4(1, 1, 0, 1), static_cast<float>(1.98892e30) }, + { glm::vec4(0.00f, 0.00f, 4e11f, 4e10f), glm::vec4(1, 0, 0, 1), static_cast<float>(1.98892e30) }, + { glm::vec4(0.00f, 0.00f, 0.00f, m_SagA.m_Rs), glm::vec4(0, 0, 0, 1), static_cast<float>(m_SagA.m_Mass) } }; - m_QuadShader = Shader::Create("Assets/Shaders/Quad.glsl"); - m_GridShader = Shader::Create("Assets/Shaders/Grid.glsl"); - m_ComputeShader = Shader::CreateCompute("Geodesic", LoadComputeShader("Assets/Shaders/Geodesic.glsl")); + m_ShaderProgram = Ref<Shader>(Shader::Create("Assets/Shaders/ComputeTextureQuad.glsl")); + m_ComputeProgram = CreateComputeProgram("Assets/Shaders/Geodesic.glsl"); m_CameraUBO = UniformBuffer::Create(128, 1); - m_DiskUBO = UniformBuffer::Create(sizeof(float) * 4, 2); + m_DiskUBO = UniformBuffer::Create(sizeof(float) * 4, 2); uint32_t objUBOSize = sizeof(int) + 3 * sizeof(float) + 16 * (sizeof(glm::vec4) + sizeof(glm::vec4)) + 16 * sizeof(float); m_ObjectsUBO = UniformBuffer::Create(objUBOSize, 3); - float quadVertices[] = - { - -1.0f, 1.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 0.0f, 0.0f, - 1.0f, -1.0f, 1.0f, 0.0f, - - -1.0f, 1.0f, 0.0f, 1.0f, - 1.0f, -1.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 1.0f, 1.0f - }; - - m_QuadVAO = VertexArray::Create(); - - auto vertexBuffer = VertexBuffer::Create(quadVertices, static_cast<uint32_t>(sizeof(quadVertices))); - VertexBufferLayout layout; - layout.Push<float>(2); - layout.Push<float>(2); - vertexBuffer->SetLayout(layout); - m_QuadVAO->AddVertexBuffer(vertexBuffer); - - m_Texture = Texture2D::Create(m_Width, m_Height); + auto result = QuadVAO(); + m_QuadVAO = result.first; + m_Texture = result.second; } - void Engine::GenerateGrid(const std::vector<ObjectData>& objects) + void Engine::UpdateWindowDimensions() { - const int gridSize = 25; - const float spacing = 1e10f; - - std::vector<glm::vec3> vertices; - std::vector<uint32_t> indices; - - for (int z = 0; z <= gridSize; ++z) - { - for (int x = 0; x <= gridSize; ++x) - { - float worldX = (x - gridSize / 2) * spacing; - float worldZ = (z - gridSize / 2) * spacing; - float y = 0.0f; - - for (const auto& obj : objects) - { - glm::vec3 objPos = glm::vec3(obj.m_PosRadius); - double mass = obj.m_Mass; - double radius = obj.m_PosRadius.w; - - double r_s = 2.0 * G * mass / (c * c); - double dx = worldX - objPos.x; - double dz = worldZ - objPos.z; - double dist = sqrt(dx * dx + dz * dz); - - if (dist > r_s) - { - double deltaY = 2.0 * sqrt(r_s * (dist - r_s)); - y += static_cast<float>(deltaY) - 3e10f; - } - else - { - y += 2.0f * static_cast<float>(sqrt(r_s * r_s)) - 3e10f; - } - } - - vertices.emplace_back(worldX, y, worldZ); - } - } - - for (int z = 0; z < gridSize; ++z) - { - for (int x = 0; x < gridSize; ++x) - { - int i = z * (gridSize + 1) + x; - indices.push_back(i); - indices.push_back(i + 1); - indices.push_back(i); - indices.push_back(i + gridSize + 1); - } - } - - if (!m_GridVAO) - { - m_GridVAO = Ref<VertexArray>(VertexArray::Create()); - - auto vertexBuffer = Ref<VertexBuffer>(VertexBuffer::Create(vertices.data(), static_cast<uint32_t>(vertices.size() * sizeof(glm::vec3)))); - VertexBufferLayout layout; - layout.Push<float>(3); - vertexBuffer->SetLayout(layout); - m_GridVAO->AddVertexBuffer(vertexBuffer); - - auto indexBuffer = Ref<IndexBuffer>(IndexBuffer::Create(indices.data(), static_cast<uint32_t>(indices.size()))); - m_GridVAO->SetIndexBuffer(indexBuffer); - } - else - { - auto vertexBuffer = m_GridVAO->GetVertexBuffers()[0]; - vertexBuffer->SetData(vertices.data(), static_cast<uint32_t>(vertices.size() * sizeof(glm::vec3))); - } - - m_GridIndexCount = static_cast<int>(indices.size()); + GLFWwindow* window = static_cast<GLFWwindow*>(Application::Get().GetWindow().GetNativeWindow()); + int oldWidth = m_Width; + int oldHeight = m_Height; + int oldComputeHeight = m_ComputeHeight; + + glfwGetFramebufferSize(window, &m_Width, &m_Height); + + if (oldWidth != m_Width || + oldHeight != m_Height || + oldComputeHeight != m_ComputeHeight) + UpdateComputeDimensions(); } - void Engine::DrawGrid(const glm::mat4& viewProj) + void Engine::UpdatePerformance(float deltaTime) { - if (!m_GridShader || !m_GridVAO) - return; - - m_GridShader->Bind(); - m_GridShader->SetMat4("viewProj", viewProj); - - RenderCommand::DisableDepthTest(); - RenderCommand::EnableBlending(); - - m_GridVAO->Bind(); - glDrawElements(GL_LINES, m_GridIndexCount, GL_UNSIGNED_INT, nullptr); - - RenderCommand::EnableDepthTest(); + if (deltaTime > 0.0f) + m_CurrentFPS = 1.0f / deltaTime; } - void Engine::UpdateWindowDimensions() + void Engine::UpdateComputeDimensions() { - GLFWwindow* window = static_cast<GLFWwindow*>(Application::Get().GetWindow().GetNativeWindow()); - int oldWidth = m_Width; - int oldHeight = m_Height; - glfwGetFramebufferSize(window, &m_Width, &m_Height); - m_ComputeHeight = 420; - m_ComputeWidth = (m_Width * 420) / m_Height; - - if (oldWidth != m_Width || oldHeight != m_Height) - m_Texture = Texture2D::Create(m_Width, m_Height); + m_Texture = Texture2D::Create(GetComputeWidth(), m_ComputeHeight); } - void Engine::DrawFullScreenQuad() + void Engine::DrawFullScreenQuad() { RenderCommand::SetViewport(0, 0, m_Width, m_Height); - m_QuadShader->Bind(); - std::cout << "Texture ID: " << m_Texture->GetRendererID() << ", Size: " << m_Texture->GetWidth() << "x" << m_Texture->GetHeight() << std::endl; + m_ShaderProgram->Bind(); + m_QuadVAO->Bind(); + m_Texture->Bind(0); - m_QuadShader->SetInt("screenTexture", 0); - std::cout << "Set screenTexture uniform to slot 0\n"; + m_ShaderProgram->SetInt("u_ScreenTexture", 0); RenderCommand::DisableDepthTest(); - RenderCommand::DrawIndexed(m_QuadVAO, 6); + RenderCommand::DrawArrays(6); RenderCommand::EnableDepthTest(); } - void Engine::DispatchCompute(const Camera& cam) + void Engine::DispatchCompute(const Camera& cam) { - int cw = m_ComputeWidth; + int cw = GetComputeWidth(); int ch = m_ComputeHeight; - if (m_Texture->GetWidth() != cw || m_Texture->GetHeight() != ch) - m_Texture = Texture2D::Create(cw, ch); + m_Texture->SetData(nullptr, cw * ch * 4); - m_ComputeShader->Bind(); + m_ComputeProgram->Bind(); UploadCameraUBO(cam); UploadDiskUBO(); UploadObjectsUBO(m_Objects); - m_Texture->BindAsImage(0, false); - uint32_t groupsX = (uint32_t)std::ceil(cw / 16.0f); - uint32_t groupsY = (uint32_t)std::ceil(ch / 16.0f); - m_ComputeShader->Dispatch(groupsX, groupsY, 1); - m_ComputeShader->MemoryBarrier(IMAGE_ACCESS_BARRIER_BIT); - - glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); - glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); + uint32_t groupsX = static_cast<uint32_t>(std::ceil(cw / 16.0f)); + uint32_t groupsY = static_cast<uint32_t>(std::ceil(ch / 16.0f)); + m_ComputeProgram->Dispatch(groupsX, groupsY, 1); + m_ComputeProgram->MemoryBarrier(IMAGE_ACCESS_BARRIER_BIT); } - void Engine::UploadCameraUBO(const Camera& cam) + void Engine::UploadCameraUBO(const Camera& cam) { - struct UBOData + struct UBOData { - glm::vec3 pos; float _pad0; - glm::vec3 right; float _pad1; - glm::vec3 up; float _pad2; + glm::vec3 pos; float _pad0; + glm::vec3 right; float _pad1; + glm::vec3 up; float _pad2; glm::vec3 forward; float _pad3; float tanHalfFov; float aspect; - bool moving; - int _pad4; + bool moving; + int _pad4; } data; - glm::vec3 fwd = glm::normalize(cam.GetTarget() - cam.GetOrbitalPosition()); - glm::vec3 up = glm::vec3(0, 1, 0); + glm::vec3 fwd = glm::normalize(cam.GetOrbitalTarget() - cam.GetOrbitalPosition()); + glm::vec3 up = glm::vec3(0, 1, 0); glm::vec3 right = glm::normalize(glm::cross(fwd, up)); up = glm::cross(right, fwd); - data.pos = cam.GetOrbitalPosition(); - data.right = right; - data.up = up; - data.forward = fwd; + data.pos = cam.GetOrbitalPosition(); + data.right = right; + data.up = up; + data.forward = fwd; data.tanHalfFov = static_cast<float>(tan(glm::radians(60.0f * 0.5f))); - data.aspect = static_cast<float>(m_Width) / static_cast<float>(m_Height); - data.moving = cam.IsDragging() || cam.IsPanning(); + data.aspect = static_cast<float>(GetComputeWidth()) / static_cast<float>(m_ComputeHeight); + data.moving = cam.IsDragging() || cam.IsPanning(); m_CameraUBO->SetData(&data, sizeof(UBOData)); + m_CameraUBO->Bind(1); } - void Engine::UploadObjectsUBO(const std::vector<ObjectData>& objs) + void Engine::UploadObjectsUBO(const std::vector<ObjectData>& objs) { - struct UBOData + struct UBOData { int numObjects; float _pad0, _pad1, _pad2; @@ -257,7 +150,7 @@ namespace Donut size_t count = std::min(objs.size(), size_t(16)); data.numObjects = static_cast<int>(count); - for (size_t i = 0; i < count; ++i) + for (size_t i = 0; i < count; ++i) { data.posRadius[i] = objs[i].m_PosRadius; data.color[i] = objs[i].m_Color; @@ -265,9 +158,10 @@ namespace Donut } m_ObjectsUBO->SetData(&data, sizeof(data)); + m_ObjectsUBO->Bind(3); } - void Engine::UploadDiskUBO() + void Engine::UploadDiskUBO() { float r1 = static_cast<float>(m_SagA.m_Rs * 2.2); float r2 = static_cast<float>(m_SagA.m_Rs * 5.2); @@ -276,28 +170,28 @@ namespace Donut float diskData[4] = { r1, r2, num, thickness }; m_DiskUBO->SetData(diskData, sizeof(diskData)); + m_DiskUBO->Bind(2); } - void Engine::UpdatePhysics(float deltaTime) + void Engine::UpdatePhysics(float deltaTime) { - for (auto& obj : m_Objects) + for (auto& obj : m_Objects) { - for (auto& obj2 : m_Objects) + for (auto& obj2 : m_Objects) { if (&obj == &obj2) continue; float dx = obj2.m_PosRadius.x - obj.m_PosRadius.x; float dy = obj2.m_PosRadius.y - obj.m_PosRadius.y; float dz = obj2.m_PosRadius.z - obj.m_PosRadius.z; float distance = sqrt(dx * dx + dy * dy + dz * dz); - - if (distance > 0) + if (distance > 0) { std::vector<double> direction = {dx / distance, dy / distance, dz / distance}; double Gforce = (G * obj.m_Mass * obj2.m_Mass) / (distance * distance); double acc1 = Gforce / obj.m_Mass; std::vector<double> acc = {direction[0] * acc1, direction[1] * acc1, direction[2] * acc1}; - - if (m_Gravity) + + if (m_Gravity) { obj.m_Velocity.x += static_cast<float>(acc[0]); obj.m_Velocity.y += static_cast<float>(acc[1]); @@ -314,34 +208,50 @@ namespace Donut void Engine::RenderScene() { - glm::mat4 view = glm::lookAt(m_Camera.GetOrbitalPosition(), m_Camera.GetTarget(), glm::vec3(0,1,0)); - glm::mat4 proj = glm::perspective(glm::radians(60.0f), float(m_Width)/m_Height, 1e9f, 1e14f); - glm::mat4 viewProj = proj * view; - - GenerateGrid(m_Objects); - DrawGrid(viewProj); - - RenderCommand::SetViewport(0, 0, m_Width, m_Height); - DispatchCompute(m_Camera); - DrawFullScreenQuad(); + RenderCommand::Clear(); + m_ShaderProgram->Bind(); + m_QuadVAO->Bind(); + m_Texture->Bind(0); + RenderCommand::DrawArrays(6); } - std::string Engine::LoadComputeShader(const std::string& path) + Ref<Shader> Engine::CreateComputeProgram(const char* path) { std::ifstream in(path); - if(!in.is_open()) + if(!in.is_open()) { std::cerr << "Failed to open compute shader: " << path << "\n"; - return ""; + return nullptr; } - std::stringstream ss; ss << in.rdbuf(); - std::string result = ss.str(); - if (result.empty()) - std::cerr << "Warning: Compute shader file is empty: " << path << "\n"; - else - std::cout << "Successfully loaded compute shader: " << path << " (size: " << result.size() << " bytes)\n"; - return result; + std::string srcStr = ss.str(); + return Ref<Shader>(Shader::CreateCompute("ComputeShader", srcStr)); + } + + std::pair<Ref<VertexArray>, Ref<Texture2D>> Engine::QuadVAO() + { + float quadVertices[] = + { + // Positions // TexCoords + -1.0f, 1.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, + -1.0f, 1.0f, 0.0f, 1.0f, + 1.0f, -1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 1.0f + }; + + auto vertexBuffer = Ref<VertexBuffer>(VertexBuffer::Create(quadVertices, static_cast<uint32_t>(sizeof(quadVertices)))); + VertexBufferLayout layout; + layout.Push<float>(2); // Position (x, y) + layout.Push<float>(2); // TexCoord (u, v) + vertexBuffer->SetLayout(layout); + + auto vertexArray = Ref<VertexArray>(VertexArray::Create()); + vertexArray->AddVertexBuffer(vertexBuffer); + auto texture = Texture2D::Create(GetComputeWidth(), m_ComputeHeight); + + return { vertexArray, texture }; } } |
