diff options
33 files changed, 770 insertions, 724 deletions
diff --git a/Assets/Shaders/ComputeTextureQuad.glsl b/Assets/Shaders/ComputeTextureQuad.glsl new file mode 100644 index 0000000..1b83f8a --- /dev/null +++ b/Assets/Shaders/ComputeTextureQuad.glsl @@ -0,0 +1,27 @@ +#type vertex + +#version 330 core +layout (location = 0) in vec2 a_Pos; +layout (location = 1) in vec2 a_TexCoord; + +out vec2 v_TexCoord; + +void main() +{ + gl_Position = vec4(a_Pos, 0.0, 1.0); + v_TexCoord = a_TexCoord; +} + +#type fragment + +#version 330 core + +in vec2 v_TexCoord; +out vec4 o_FragColor; + +uniform sampler2D u_ScreenTexture; + +void main() +{ + o_FragColor = texture(u_ScreenTexture, v_TexCoord); +} diff --git a/Assets/Shaders/Geodesic.glsl b/Assets/Shaders/Geodesic.glsl index c44b58d..7d3cc03 100644 --- a/Assets/Shaders/Geodesic.glsl +++ b/Assets/Shaders/Geodesic.glsl @@ -2,16 +2,15 @@ layout(local_size_x = 16, local_size_y = 16) in; layout(binding = 0, rgba8) writeonly uniform image2D outImage; - layout(std140, binding = 1) uniform Camera { - vec3 camPos; float _pad0; - vec3 camRight; float _pad1; - vec3 camUp; float _pad2; - vec3 camForward; float _pad3; + vec3 camPos; float _pad0; + vec3 camRight; float _pad1; + vec3 camUp; float _pad2; + vec3 camForward; float _pad3; float tanHalfFov; float aspect; - bool moving; + bool moving; int _pad4; } cam; @@ -25,65 +24,83 @@ layout(std140, binding = 2) uniform Disk layout(std140, binding = 3) uniform Objects { - int numObjects; - vec4 objPosRadius[16]; - vec4 objColor[16]; - float mass[16]; + int numObjects; + vec4 objPosRadius[16]; + vec4 objColor[16]; + float mass[16]; }; -const float SagA_rs = 1.269e10; -const float D_LAMBDA = 1e7; +const float SagA_rs = 1.269e10; +const float D_LAMBDA = 1e7; const double ESCAPE_R = 1e30; +const int MAX_STEPS_MOVING = 60000; +const int MAX_STEPS_STATIC = 30000; +const float EARLY_EXIT_DISTANCE = 5e11; + vec4 objectColor = vec4(0.0); vec3 hitCenter = vec3(0.0); float hitRadius = 0.0; struct Ray { - float x, y, z, radius, theta, phi; - float dRadius, dTheta, dPhi; - float energy, angularMomentum; + float x, y, z; + float r, theta, phi; + float dr, dtheta, dphi; + float E, L; }; -Ray InitRay(vec3 position, vec3 direction) +Ray InitRay(vec3 pos, vec3 dir) { Ray ray; - ray.x = position.x; - ray.y = position.y; - ray.z = position.z; - ray.radius = length(position); - ray.theta = acos(position.z / ray.radius); - ray.phi = atan(position.y, position.x); + ray.x = pos.x; + ray.y = pos.y; + ray.z = pos.z; + ray.r = length(pos); + ray.theta = acos(pos.z / ray.r); + ray.phi = atan(pos.y, pos.x); + + float dx = dir.x; + float dy = dir.y; + float dz = dir.z; + + ray.dr = sin(ray.theta)*cos(ray.phi)*dx + + sin(ray.theta)*sin(ray.phi)*dy + + cos(ray.theta)*dz; + + ray.dtheta = (cos(ray.theta)*cos(ray.phi)*dx + + cos(ray.theta)*sin(ray.phi)*dy - + sin(ray.theta)*dz) / ray.r; - float dx = direction.x, dy = direction.y, dz = direction.z; - ray.dRadius = sin(ray.theta) * cos(ray.phi) * dx + sin(ray.theta) * sin(ray.phi) * dy + cos(ray.theta) * dz; - ray.dTheta = (cos(ray.theta) * cos(ray.phi) * dx + cos(ray.theta) * sin(ray.phi) * dy - sin(ray.theta) * dz) / ray.radius; - ray.dPhi = (-sin(ray.phi) * dx + cos(ray.phi) * dy) / (ray.radius * sin(ray.theta)); + ray.dphi = (-sin(ray.phi)*dx + cos(ray.phi)*dy) / + (ray.r * sin(ray.theta)); - ray.angularMomentum = ray.radius * ray.radius * sin(ray.theta) * ray.dPhi; - float f = 1.0 - SagA_rs / ray.radius; - float dt_dL = sqrt((ray.dRadius * ray.dRadius) / f + ray.radius * ray.radius * (ray.dTheta * ray.dTheta + sin(ray.theta) * sin(ray.theta) * ray.dPhi * ray.dPhi)); - ray.energy = f * dt_dL; + ray.L = ray.r * ray.r * sin(ray.theta) * ray.dphi; + float f = 1.0 - SagA_rs / ray.r; + float dt_dL = sqrt((ray.dr*ray.dr)/f + + ray.r*ray.r*(ray.dtheta*ray.dtheta + + sin(ray.theta)*sin(ray.theta)* + ray.dphi*ray.dphi)); + ray.E = f * dt_dL; return ray; } -bool Intercept(Ray ray, float schwarzschildRadius) +bool Intercept(Ray ray, float rs) { - return ray.radius <= schwarzschildRadius; + return ray.r <= rs; } bool InterceptObject(Ray ray) { - vec3 position = vec3(ray.x, ray.y, ray.z); + vec3 P = vec3(ray.x, ray.y, ray.z); for (int i = 0; i < numObjects; ++i) { - vec3 center = objPosRadius[i].xyz; + vec3 center = objPosRadius[i].xyz; float radius = objPosRadius[i].w; - - if (distance(position, center) <= radius) + + if (distance(P, center) <= radius) { objectColor = objColor[i]; hitCenter = center; @@ -91,75 +108,94 @@ bool InterceptObject(Ray ray) return true; } } - + return false; } -void GeodesicRHS(Ray ray, out vec3 derivatives1, out vec3 derivatives2) +void GeodesicRHS(Ray ray, out vec3 d1, out vec3 d2) { - float radius = ray.radius, theta = ray.theta; - float dRadius = ray.dRadius, dTheta = ray.dTheta, dPhi = ray.dPhi; - float f = 1.0 - SagA_rs / radius; - float dt_dL = ray.energy / f; + float r = ray.r; + float theta = ray.theta; + float dr = ray.dr; + float dtheta = ray.dtheta; + float dphi = ray.dphi; + float f = 1.0 - SagA_rs / r; + float dt_dL = ray.E / f; - derivatives1 = vec3(dRadius, dTheta, dPhi); - derivatives2.x = -(SagA_rs / (2.0 * radius * radius)) * f * dt_dL * dt_dL - + (SagA_rs / (2.0 * radius * radius * f)) * dRadius * dRadius - + radius * (dTheta * dTheta + sin(theta) * sin(theta) * dPhi * dPhi); - derivatives2.y = -2.0 * dRadius * dTheta / radius + sin(theta) * cos(theta) * dPhi * dPhi; - derivatives2.z = -2.0 * dRadius * dPhi / radius - 2.0 * cos(theta) / sin(theta) * dTheta * dPhi; + d1 = vec3(dr, dtheta, dphi); + d2.x = - (SagA_rs / (2.0 * r*r)) * f * dt_dL * dt_dL + + (SagA_rs / (2.0 * r*r * f)) * dr * dr + + r * (dtheta*dtheta + sin(theta)*sin(theta)*dphi*dphi); + d2.y = -2.0*dr*dtheta/r + sin(theta)*cos(theta)*dphi*dphi; + d2.z = -2.0*dr*dphi/r - 2.0*cos(theta)/(sin(theta)) * dtheta * dphi; } -void RK4Step(inout Ray ray, float deltaLambda) +void RK4Step(inout Ray ray, float dL) { vec3 k1a, k1b; GeodesicRHS(ray, k1a, k1b); - ray.radius += deltaLambda * k1a.x; - ray.theta += deltaLambda * k1a.y; - ray.phi += deltaLambda * k1a.z; - ray.dRadius += deltaLambda * k1b.x; - ray.dTheta += deltaLambda * k1b.y; - ray.dPhi += deltaLambda * k1b.z; + ray.r += dL * k1a.x; + ray.theta += dL * k1a.y; + ray.phi += dL * k1a.z; + ray.dr += dL * k1b.x; + ray.dtheta += dL * k1b.y; + ray.dphi += dL * k1b.z; - ray.x = ray.radius * sin(ray.theta) * cos(ray.phi); - ray.y = ray.radius * sin(ray.theta) * sin(ray.phi); - ray.z = ray.radius * cos(ray.theta); + ray.x = ray.r * sin(ray.theta) * cos(ray.phi); + ray.y = ray.r * sin(ray.theta) * sin(ray.phi); + ray.z = ray.r * cos(ray.theta); } -bool CrossesEquatorialPlane(vec3 oldPosition, vec3 newPosition) +bool CrossesEquatorialPlane(vec3 oldPos, vec3 newPos) { - bool crossed = (oldPosition.y * newPosition.y < 0.0); - float radius = length(vec2(newPosition.x, newPosition.z)); - return crossed && (radius >= disk_r1 && radius <= disk_r2); + bool crossed = (oldPos.y * newPos.y < 0.0); + float r = length(vec2(newPos.x, newPos.z)); + return crossed && (r >= disk_r1 && r <= disk_r2); } void main() { - ivec2 pixel = ivec2(gl_GlobalInvocationID.xy); - int width = imageSize(outImage).x; - int height = imageSize(outImage).y; - - if (pixel.x >= width || pixel.y >= height) + ivec2 pix = ivec2(gl_GlobalInvocationID.xy); + int WIDTH = imageSize(outImage).x; + int HEIGHT = imageSize(outImage).y; + + if (pix.x >= WIDTH || + pix.y >= HEIGHT) return; - float u = (2.0 * (pixel.x + 0.5) / width - 1.0) * cam.aspect * cam.tanHalfFov; - float v = (1.0 - 2.0 * (pixel.y + 0.5) / height) * cam.tanHalfFov; - vec3 direction = normalize(u * cam.camRight - v * cam.camUp + cam.camForward); - Ray ray = InitRay(cam.camPos, direction); + float u = (2.0 * (pix.x + 0.5) / WIDTH - 1.0) * + cam.aspect * cam.tanHalfFov; + float v = (1.0 - 2.0 * (pix.y + 0.5) / HEIGHT) * + cam.tanHalfFov; + vec3 dir = normalize(u * cam.camRight - + v * cam.camUp + + cam.camForward); + Ray ray = InitRay(cam.camPos, dir); - vec4 color = vec4(0.0); - vec3 prevPosition = vec3(ray.x, ray.y, ray.z); - float lambda = 0.0; + vec4 color = vec4(0.0); + vec3 prevPos = vec3(ray.x, ray.y, ray.z); + float lambda = 0.0; bool hitBlackHole = false; - bool hitDisk = false; - bool hitObject = false; + bool hitDisk = false; + bool hitObject = false; - int steps = cam.moving ? 60000 : 60000; + int maxSteps = cam.moving ? MAX_STEPS_MOVING : MAX_STEPS_STATIC; + + float cameraDistance = length(cam.camPos); + if (cameraDistance > 1e12) + maxSteps = maxSteps / 4; + else if (cameraDistance > 5e11) + maxSteps = maxSteps / 2; - for (int i = 0; i < steps; ++i) + for (int i = 0; i < maxSteps; ++i) { + if (ray.r > EARLY_EXIT_DISTANCE) + break; + if (ray.r > ESCAPE_R) + break; + if (Intercept(ray, SagA_rs)) { hitBlackHole = true; @@ -169,9 +205,9 @@ void main() RK4Step(ray, D_LAMBDA); lambda += D_LAMBDA; - vec3 newPosition = vec3(ray.x, ray.y, ray.z); + vec3 newPos = vec3(ray.x, ray.y, ray.z); - if (CrossesEquatorialPlane(prevPosition, newPosition)) + if (CrossesEquatorialPlane(prevPos, newPos)) { hitDisk = true; break; @@ -183,33 +219,31 @@ void main() break; } - prevPosition = newPosition; - - if (ray.radius > ESCAPE_R) - break; + prevPos = newPos; } if (hitDisk) { - double radius = length(vec3(ray.x, ray.y, ray.z)) / disk_r2; - vec3 diskColor = vec3(1.0, radius, 0.2); - color = vec4(diskColor, radius); - } - else if (hitBlackHole) + double r = length(vec3(ray.x, ray.y, ray.z)) / disk_r2; + vec3 diskColor = vec3(1.0, r, 0.2); + color = vec4(diskColor, r); + + } else if (hitBlackHole) color = vec4(0.0, 0.0, 0.0, 1.0); else if (hitObject) { - vec3 position = vec3(ray.x, ray.y, ray.z); - vec3 normal = normalize(position - hitCenter); - vec3 viewDirection = normalize(cam.camPos - position); - float ambient = 0.1; - float diffuse = max(dot(normal, viewDirection), 0.0); - float intensity = ambient + (1.0 - ambient) * diffuse; - vec3 shaded = objectColor.rgb * intensity; + vec3 P = vec3(ray.x, ray.y, ray.z); + vec3 N = normalize(P - hitCenter); + vec3 V = normalize(cam.camPos - P); + + float ambient = 0.1; + float diff = max(dot(N, V), 0.0); + float intensity = ambient + (1.0 - ambient) * diff; + vec3 shaded = objectColor.rgb * intensity; + color = vec4(shaded, objectColor.a); - } - else + } else color = vec4(0.0); - imageStore(outImage, pixel, color); + imageStore(outImage, pix, color); }
\ No newline at end of file diff --git a/Assets/Shaders/Grid.glsl b/Assets/Shaders/Grid.glsl deleted file mode 100644 index 66096c4..0000000 --- a/Assets/Shaders/Grid.glsl +++ /dev/null @@ -1,19 +0,0 @@ -#type vertex -#version 330 core -layout (location = 0) in vec3 aPos; - -uniform mat4 viewProj; - -void main() -{ - gl_Position = viewProj * vec4(aPos, 1.0); -} - -#type fragment -#version 330 core -out vec4 FragColor; - -void main() -{ - FragColor = vec4(0.5, 0.5, 0.5, 0.3); -} diff --git a/Assets/Shaders/Quad.glsl b/Assets/Shaders/Quad.glsl deleted file mode 100644 index 57693a6..0000000 --- a/Assets/Shaders/Quad.glsl +++ /dev/null @@ -1,25 +0,0 @@ -#type vertex -#version 330 core -layout(location = 0) in vec2 a_Pos; -layout(location = 1) in vec2 a_TexCoord; - -out vec2 v_TexCoord; - -void main() -{ - gl_Position = vec4(a_Pos.xy, 0.0, 1.0); - v_TexCoord = a_TexCoord; -} - -#type fragment -#version 330 core -out vec4 FragColor; - -in vec2 v_TexCoord; - -uniform sampler2D screenTexture; - -void main() -{ - FragColor = texture(screenTexture, v_TexCoord); -} diff --git a/src/Core/Camera.cpp b/src/Core/Camera.cpp index 6f86124..eeb62a4 100644 --- a/src/Core/Camera.cpp +++ b/src/Core/Camera.cpp @@ -1,6 +1,7 @@ #include "Camera.h" #include <glm/gtc/quaternion.hpp> +#include <GLFW/glfw3.h> namespace Donut { @@ -50,8 +51,10 @@ namespace Donut else if (m_CameraMode == CameraMode::Orbital) { glm::vec3 position = GetOrbitalPosition(); - glm::vec3 worldUp(0.0f, 1.0f, 0.0f); - m_ViewMatrix = glm::lookAt(position, m_Target, worldUp); + glm::vec3 target = m_OrbitalTarget; + glm::vec3 up(0.0f, 1.0f, 0.0f); + + m_ViewMatrix = glm::lookAt(position, target, up); m_ViewProjectionMatrix = m_ProjectionMatrix * m_ViewMatrix; } } @@ -158,77 +161,65 @@ namespace Donut } } - // Orbital Camera Methods - void Camera::SetOrbitalMode(bool enabled) - { - m_CameraMode = enabled ? CameraMode::Orbital : CameraMode::FPS; - RecalculateViewMatrix(); - } - glm::vec3 Camera::GetOrbitalPosition() const { float clampedElevation = glm::clamp(m_Elevation, 0.01f, float(M_PI) - 0.01f); - return glm::vec3( - m_Radius * sin(clampedElevation) * cos(m_Azimuth), - m_Radius * cos(clampedElevation), - m_Radius * sin(clampedElevation) * sin(m_Azimuth) + return glm::vec3 + ( + m_OrbitalRadius * sin(clampedElevation) * cos(m_Azimuth), + m_OrbitalRadius * cos(clampedElevation), + m_OrbitalRadius * sin(clampedElevation) * sin(m_Azimuth) ); } + void Camera::UpdateOrbital() + { + m_OrbitalTarget = glm::vec3(0.0f, 0.0f, 0.0f); + if (m_Dragging || m_Panning) + m_Moving = true; + else + m_Moving = false; + RecalculateViewMatrix(); + } + void Camera::ProcessOrbitalMouseMove(double x, double y) { - if (m_Dragging && !m_Panning) + if (m_Dragging && !m_Panning) { - float dx = float(x - m_OrbitalLastX); - float dy = float(y - m_OrbitalLastY); + float dx = float(x - m_LastX_Orbital); + float dy = float(y - m_LastY_Orbital); - m_Azimuth += dx * m_OrbitSpeed; - m_Elevation -= dy * m_OrbitSpeed; + m_Azimuth += dx * m_OrbitalSpeed; + m_Elevation -= dy * m_OrbitalSpeed; m_Elevation = glm::clamp(m_Elevation, 0.01f, float(M_PI) - 0.01f); } - m_OrbitalLastX = x; - m_OrbitalLastY = y; - UpdateOrbitalState(); - RecalculateViewMatrix(); + m_LastX_Orbital = x; + m_LastY_Orbital = y; + UpdateOrbital(); } void Camera::ProcessOrbitalMouseButton(int button, int action, int mods) { - if (button == GLFW_MOUSE_BUTTON_LEFT) + if (button == GLFW_MOUSE_BUTTON_LEFT) { - if (action == GLFW_PRESS) + if (action == GLFW_PRESS) { m_Dragging = true; m_Panning = false; - } - else if (action == GLFW_RELEASE) + } + else if (action == GLFW_RELEASE) { m_Dragging = false; m_Panning = false; } } - UpdateOrbitalState(); } void Camera::ProcessOrbitalScroll(double xoffset, double yoffset) { - m_Radius -= yoffset * m_ZoomSpeed; - m_Radius = glm::clamp(m_Radius, m_MinRadius, m_MaxRadius); - UpdateOrbitalState(); - RecalculateViewMatrix(); - } - - void Camera::UpdateOrbitalState() - { - m_Target = glm::vec3(0.0f, 0.0f, 0.0f); - if (m_Dragging || m_Panning) - { - m_Moving = true; - } - else - { - m_Moving = false; - } + m_OrbitalRadius -= yoffset * m_ZoomSpeed; + m_OrbitalRadius = glm::clamp(m_OrbitalRadius, m_OrbitalMinRadius, m_OrbitalMaxRadius); + UpdateOrbital(); } } diff --git a/src/Core/Camera.h b/src/Core/Camera.h index 7fe3bd9..a049d06 100644 --- a/src/Core/Camera.h +++ b/src/Core/Camera.h @@ -2,7 +2,6 @@ #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> -#include <GLFW/glfw3.h> #define _USE_MATH_DEFINES #ifndef M_PI @@ -24,7 +23,6 @@ namespace Donut float nearPlane = 0.1f, float farPlane = 100.0f); ~Camera() = default; - // FPS Camera Methods void SetPosition(const glm::vec3& position) { m_Position = position; RecalculateViewMatrix(); } void SetRotation(const glm::vec3& rotation) { m_Rotation = rotation; RecalculateViewMatrix(); } @@ -55,21 +53,23 @@ namespace Donut void SetMovementSpeed(float speed) { m_MovementSpeed = speed; } float GetMovementSpeed() const { return m_MovementSpeed; } - // Orbital Camera Methods - void SetOrbitalMode(bool enabled); - bool IsOrbitalMode() const { return m_CameraMode == CameraMode::Orbital; } + void SetOrbitalTarget(const glm::vec3& target) { m_OrbitalTarget = target; } + const glm::vec3& GetOrbitalTarget() const { return m_OrbitalTarget; } - void SetTarget(const glm::vec3& target) { m_Target = target; } - const glm::vec3& GetTarget() const { return m_Target; } + void SetOrbitalRadius(double radius) { m_OrbitalRadius = radius; } + double GetOrbitalRadius() const { return m_OrbitalRadius; } - void SetRadius(double radius) { m_Radius = radius; } - double GetRadius() const { return m_Radius; } + void SetOrbitalLimits(double minRadius, double maxRadius) + { + m_OrbitalMinRadius = minRadius; + m_OrbitalMaxRadius = maxRadius; + } - void SetMinRadius(double minRadius) { m_MinRadius = minRadius; } - double GetMinRadius() const { return m_MinRadius; } + void SetOrbitalSpeed(float speed) { m_OrbitalSpeed = speed; } + float GetOrbitalSpeed() const { return m_OrbitalSpeed; } - void SetMaxRadius(double maxRadius) { m_MaxRadius = maxRadius; } - double GetMaxRadius() const { return m_MaxRadius; } + void SetZoomSpeed(double speed) { m_ZoomSpeed = speed; } + double GetZoomSpeed() const { return m_ZoomSpeed; } void SetAzimuth(float azimuth) { m_Azimuth = azimuth; } float GetAzimuth() const { return m_Azimuth; } @@ -77,35 +77,27 @@ namespace Donut void SetElevation(float elevation) { m_Elevation = elevation; } float GetElevation() const { return m_Elevation; } - void SetOrbitSpeed(float orbitSpeed) { m_OrbitSpeed = orbitSpeed; } - float GetOrbitSpeed() const { return m_OrbitSpeed; } - - void SetZoomSpeed(double zoomSpeed) { m_ZoomSpeed = zoomSpeed; } - double GetZoomSpeed() const { return m_ZoomSpeed; } - - // Orbital camera position calculation glm::vec3 GetOrbitalPosition() const; - - // Input handling for orbital camera + void UpdateOrbital(); void ProcessOrbitalMouseMove(double x, double y); void ProcessOrbitalMouseButton(int button, int action, int mods); void ProcessOrbitalScroll(double xoffset, double yoffset); - // State management - bool IsDragging() const { return m_Dragging; } - bool IsPanning() const { return m_Panning; } - bool IsMoving() const { return m_Moving; } + void SetCameraMode(CameraMode mode) { m_CameraMode = mode; } + CameraMode GetCameraMode() const { return m_CameraMode; } + + bool IsDragging() const { return m_Dragging; } + bool IsPanning() const { return m_Panning; } + bool IsMoving() const { return m_Moving; } + double GetLastX() const { return m_LastX; } + double GetLastY() const { return m_LastY; } private: void RecalculateViewMatrix(); void RecalculateProjectionMatrix(); - void UpdateOrbitalState(); - private: - // Camera mode CameraMode m_CameraMode = CameraMode::FPS; - - // FPS Camera members + glm::mat4 m_ProjectionMatrix; glm::mat4 m_ViewMatrix; glm::mat4 m_ViewProjectionMatrix; @@ -123,20 +115,19 @@ namespace Donut bool m_FirstMouse = true; float m_LastX = 0.0f; float m_LastY = 0.0f; - - // Orbital Camera members - glm::vec3 m_Target = glm::vec3(0.0f, 0.0f, 0.0f); - double m_Radius = 6.34194e10; - double m_MinRadius = 1e10; - double m_MaxRadius = 1e12; - float m_Azimuth = 0.0f; - float m_Elevation = static_cast<float>(M_PI) / 2.0f; - float m_OrbitSpeed = 0.01f; - double m_ZoomSpeed = 25e9f; - bool m_Dragging = false; - bool m_Panning = false; - bool m_Moving = false; - double m_OrbitalLastX = 0.0; - double m_OrbitalLastY = 0.0; + + glm::vec3 m_OrbitalTarget = glm::vec3(0.0f, 0.0f, 0.0f); + double m_OrbitalRadius = 6.34194e10; + double m_OrbitalMinRadius = 1e10; + double m_OrbitalMaxRadius = 1e12; + float m_Azimuth = 0.0f; + float m_Elevation = static_cast<float>(M_PI) / 2.0f; + float m_OrbitalSpeed = 0.01f; + double m_ZoomSpeed = 25e9f; + bool m_Dragging = false; + bool m_Panning = false; + bool m_Moving = false; + double m_LastX_Orbital = 0.0; + double m_LastY_Orbital = 0.0; }; } 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 }; } } diff --git a/src/Engine/Engine.h b/src/Engine/Engine.h index 2368bb8..a004717 100644 --- a/src/Engine/Engine.h +++ b/src/Engine/Engine.h @@ -2,10 +2,6 @@ #include <vector> #include <iostream> -#include <GLFW/glfw3.h> -#include <glm/glm.hpp> -#include <glm/gtc/matrix_transform.hpp> -#include <glm/gtc/type_ptr.hpp> #include <fstream> #include <sstream> #include <chrono> @@ -15,16 +11,27 @@ #include "Core/Camera.h" #include "Rendering/Renderer.h" #include "Rendering/Shader.h" -#include "Rendering/Texture.h" #include "Rendering/VertexArray.h" +#include "Rendering/Texture.h" #include "Rendering/UniformBuffer.h" +#include "Rendering/TextureManager.h" + +#include <GLFW/glfw3.h> +#include <glm/glm.hpp> +#include <glm/gtc/matrix_transform.hpp> +#include <glm/gtc/type_ptr.hpp> + +#define _USE_MATH_DEFINES +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif namespace Donut { const double c = 299792458.0; const double G = 6.67430e-11; - struct BlackHole + struct BlackHole { glm::vec3 m_Position; double m_Mass; @@ -32,13 +39,12 @@ namespace Donut double m_Rs; BlackHole(glm::vec3 pos, float mass) - : m_Position(pos), - m_Mass(mass) + : m_Position(pos), m_Mass(mass) { m_Rs = 2.0 * G * m_Mass / (c * c); } - bool Intercept(float px, float py, float pz) const + bool Intercept(float px, float py, float pz) const { double dx = double(px) - double(m_Position.x); double dy = double(py) - double(m_Position.y); @@ -48,11 +54,11 @@ namespace Donut } }; - struct ObjectData + struct ObjectData { glm::vec4 m_PosRadius; glm::vec4 m_Color; - float m_Mass; + float m_Mass; glm::vec3 m_Velocity = glm::vec3(0.0f, 0.0f, 0.0f); }; @@ -62,8 +68,6 @@ namespace Donut Engine(); ~Engine() = default; - void GenerateGrid(const std::vector<ObjectData>& objects); - void DrawGrid(const glm::mat4& viewProj); void DrawFullScreenQuad(); void DispatchCompute(const Camera& cam); void UploadCameraUBO(const Camera& cam); @@ -73,46 +77,47 @@ namespace Donut void UpdatePhysics(float deltaTime); void UpdateWindowDimensions(); - Camera& GetCamera() { return m_Camera; } - const Camera& GetCamera() const { return m_Camera; } - - const std::vector<ObjectData>& GetObjects() const { return m_Objects; } - std::vector<ObjectData>& GetObjects() { return m_Objects; } - - bool GetGravity() const { return m_Gravity; } - void SetGravity(bool gravity) { m_Gravity = gravity; } - - int GetWidth() const { return m_Width; } - int GetHeight() const { return m_Height; } - int GetComputeWidth() const { return m_ComputeWidth; } - int GetComputeHeight() const { return m_ComputeHeight; } + int GetWidth() const { return m_Width; } + int GetHeight() const { return m_Height; } + + std::vector<ObjectData>& GetObjects() { return m_Objects; } + BlackHole& GetSagA() { return m_SagA; } + Camera& GetCamera() { return m_Camera; } + bool& GetGravity() { return m_Gravity; } + void UpdatePerformance(float deltaTime); + void SetTargetFPS(int fps) { m_TargetFPS = fps; } + int GetTargetFPS() const { return m_TargetFPS; } + float GetCurrentFPS() const { return m_CurrentFPS; } + void SetComputeHeight(int height) { m_ComputeHeight = height; } + int GetComputeHeight() const { return m_ComputeHeight; } + int GetComputeWidth() const { return (m_Width * m_ComputeHeight) / m_Height; } + void UpdateComputeDimensions(); private: - std::string CreateBasicVertexShader(); - std::string CreateBasicFragmentShader(); - std::string LoadComputeShader(const std::string& path); + Ref<Shader> CreateComputeProgram(const char* path); + std::pair<Ref<VertexArray>, Ref<Texture2D>> QuadVAO(); private: - Ref<Shader> m_GridShader; - Ref<Shader> m_QuadShader; - Ref<Shader> m_ComputeShader; - Ref<Texture2D> m_Texture; Ref<VertexArray> m_QuadVAO; - Ref<VertexArray> m_GridVAO; + Ref<Texture2D> m_Texture; + Ref<Shader> m_ShaderProgram; + Ref<Shader> m_ComputeProgram; Ref<UniformBuffer> m_CameraUBO; Ref<UniformBuffer> m_DiskUBO; Ref<UniformBuffer> m_ObjectsUBO; - - int m_GridIndexCount = 0; + int m_Width; int m_Height; - int m_ComputeWidth; - int m_ComputeHeight; - float m_WidthScale = 100000000000.0f; - float m_HeightScale = 75000000000.0f; + float m_Width_f = 100*10e10f; + float m_Height_f = 75*10e10f; + + int m_TargetFPS = 60; + float m_CurrentFPS = 60.0f; + float m_LastFrameTime = 0.0f; + int m_ComputeHeight = 320; std::vector<ObjectData> m_Objects; BlackHole m_SagA; Camera m_Camera; bool m_Gravity = false; }; -} +}; diff --git a/src/Engine/Object.cpp b/src/Engine/Object.cpp deleted file mode 100644 index 8e042fd..0000000 --- a/src/Engine/Object.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "Object.h" - -namespace Donut -{ - Ray::Ray(glm::vec3 o, glm::vec3 d) - : m_Origin(o), - m_Direction(glm::normalize(d)) { } - - Material::Material(glm::vec3 c, float s, float e) - : m_Color(c), - m_Specular(s), - m_Emission(e) { } - - Object::Object(glm::vec3 c, float r, Material m) - : m_Centre(c), - m_Radius(r), - m_Material(m) { } - - bool Object::Intersect(Ray &ray, float &t) - { - glm::vec3 oc = ray.m_Origin - m_Centre; - float a = glm::dot(ray.m_Direction, ray.m_Direction); - float b = 2.0f * glm::dot(oc, ray.m_Direction); - float c = glm::dot(oc, oc) - m_Radius * m_Radius; - double discriminant = b*b - 4*a*c; - - if(discriminant < 0) - return false; - - float intercept = (-b - sqrt(discriminant)) / (2.0f*a); - if(intercept < 0) - { - intercept = (-b + sqrt(discriminant)) / (2.0f*a); - if(intercept<0) - return false; - } - - t = intercept; - return true; - } - - glm::vec3 Object::GetNormal(glm::vec3 &point) const - { - return glm::normalize(point - m_Centre); - } -} diff --git a/src/Engine/Object.h b/src/Engine/Object.h index 0ae3430..ea672db 100644 --- a/src/Engine/Object.h +++ b/src/Engine/Object.h @@ -10,7 +10,9 @@ namespace Donut glm::vec3 m_Direction; glm::vec3 m_Origin; - Ray(glm::vec3 o, glm::vec3 d); + Ray(glm::vec3 o, glm::vec3 d) + : m_Origin(o), + m_Direction(glm::normalize(d)) { } }; class Material @@ -20,7 +22,10 @@ namespace Donut float m_Specular; float m_Emission; - Material(glm::vec3 c, float s, float e); + Material(glm::vec3 c, float s, float e) + : m_Color(c), + m_Specular(s), + m_Emission(e) { } }; class Object @@ -30,9 +35,37 @@ namespace Donut float m_Radius; Material m_Material; - Object(glm::vec3 c, float r, Material m); + Object(glm::vec3 c, float r, Material m) + : m_Centre(c), + m_Radius(r), + m_Material(m) { } - bool Intersect(Ray &ray, float &t); - glm::vec3 GetNormal(glm::vec3 &point) const; + bool Intersect(Ray &ray, float &t) + { + glm::vec3 oc = ray.m_Origin - m_Centre; + float a = glm::dot(ray.m_Direction, ray.m_Direction); + float b = 2.0f * glm::dot(oc, ray.m_Direction); + float c = glm::dot(oc, oc) - m_Radius * m_Radius; + double discriminant = b*b - 4*a*c; + + if(discriminant < 0) + return false; + + float intercept = (-b - sqrt(discriminant)) / (2.0f*a); + if(intercept < 0) + { + intercept = (-b + sqrt(discriminant)) / (2.0f*a); + if(intercept<0) + return false; + } + + t = intercept; + return true; + } + + glm::vec3 GetNormal(glm::vec3 &point) const + { + return glm::normalize(point - m_Centre); + } }; }; diff --git a/src/Engine/Scene.cpp b/src/Engine/Scene.cpp deleted file mode 100644 index f92dc68..0000000 --- a/src/Engine/Scene.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "Scene.h" - -namespace Donut -{ - Scene::Scene() - : m_LightPos(5.0f, 5.0f, 5.0f) { } - - glm::vec3 Scene::Trace(Ray &ray) - { - float closest = std::numeric_limits<float>::infinity(); - const Object* hitObj = nullptr; - - for(auto& obj : objs) - { - float t; - - if(obj.Intersect(ray, t)) - if(t < closest) - { - closest = t; - hitObj = &obj; - } - } - - if(hitObj) - { - glm::vec3 hitPoint = ray.m_Origin + ray.m_Direction * closest; - glm::vec3 normal = hitObj->GetNormal(hitPoint); - glm::vec3 lightDir = glm::normalize(m_LightPos - hitPoint); - - float diff = std::max(glm::dot(normal, lightDir), 0.0f); - - Ray shadowRay(hitPoint + normal * 0.001f, lightDir); - bool inShadow = false; - - for(auto& obj : objs) - { - float t; - - if(obj.Intersect(shadowRay, t)) - { - inShadow = true; - break; - } - } - - glm::vec3 color = hitObj->m_Material.m_Color; - float ambient = 0.1f; - - if (inShadow) - return color * ambient; - return color * (ambient + diff * 0.9f); - } - - return glm::vec3(0.0f, 0.0f, 0.1f); - } -} diff --git a/src/Engine/Scene.h b/src/Engine/Scene.h index fa80302..f85fc13 100644 --- a/src/Engine/Scene.h +++ b/src/Engine/Scene.h @@ -2,7 +2,6 @@ #include <vector> #include <limits> -#include <glm/glm.hpp> #include "Object.h" @@ -14,7 +13,57 @@ namespace Donut std::vector<Object> objs; glm::vec3 m_LightPos; - Scene(); - glm::vec3 Trace(Ray &ray); + Scene() + : m_LightPos(5.0f, 5.0f, 5.0f) { } + + glm::vec3 Trace(Ray &ray) + { + float closest = std::numeric_limits<float>::infinity(); + const Object* hitObj = nullptr; + + for(auto& obj : objs) + { + float t; + + if(obj.Intersect(ray, t)) + if(t < closest) + { + closest = t; + hitObj = &obj; + } + } + + if(hitObj) + { + glm::vec3 hitPoint = ray.m_Origin + ray.m_Direction * closest; + glm::vec3 normal = hitObj->GetNormal(hitPoint); + glm::vec3 lightDir = glm::normalize(m_LightPos - hitPoint); + + float diff = std::max(glm::dot(normal, lightDir), 0.0f); + + Ray shadowRay(hitPoint + normal * 0.001f, lightDir); + bool inShadow = false; + + for(auto& obj : objs) + { + float t; + + if(obj.Intersect(shadowRay, t)) + { + inShadow = true; + break; + } + } + + glm::vec3 color = hitObj->m_Material.m_Color; + float ambient = 0.1f; + + if (inShadow) + return color * ambient; + return color * (ambient + diff * 0.9f); + } + + return glm::vec3(0.0f, 0.0f, 0.1f); + } }; };
\ No newline at end of file diff --git a/src/Platform/OpenGL/OpenGLRendererAPI.cpp b/src/Platform/OpenGL/OpenGLRendererAPI.cpp index d181203..cd54f82 100644 --- a/src/Platform/OpenGL/OpenGLRendererAPI.cpp +++ b/src/Platform/OpenGL/OpenGLRendererAPI.cpp @@ -83,4 +83,27 @@ namespace Donut glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, nullptr); glBindTexture(GL_TEXTURE_2D, 0); } + + void OpenGLRendererAPI::DrawArrays(uint32_t vertexCount, uint32_t first) + { + glDrawArrays(GL_TRIANGLES, first, vertexCount); + } + + void OpenGLRendererAPI::DrawLines(const Ref<VertexArray>& vertexArray, uint32_t indexCount) + { + uint32_t count = indexCount ? indexCount : vertexArray->GetIndexBuffer()->GetCount(); + glDrawElements(GL_LINES, count, GL_UNSIGNED_INT, nullptr); + } + + void OpenGLRendererAPI::BindTexture(uint32_t textureID, uint32_t slot) + { + glActiveTexture(GL_TEXTURE0 + slot); + glBindTexture(GL_TEXTURE_2D, textureID); + } + + void OpenGLRendererAPI::BindImageTexture(uint32_t textureID, uint32_t slot, bool readOnly) + { + glBindImageTexture(slot, textureID, 0, GL_FALSE, 0, + readOnly ? GL_READ_ONLY : GL_WRITE_ONLY, GL_RGBA8); + } }; diff --git a/src/Platform/OpenGL/OpenGLRendererAPI.h b/src/Platform/OpenGL/OpenGLRendererAPI.h index f6b9fb4..0576db8 100644 --- a/src/Platform/OpenGL/OpenGLRendererAPI.h +++ b/src/Platform/OpenGL/OpenGLRendererAPI.h @@ -26,5 +26,15 @@ namespace Donut virtual void DrawIndexed(const Ref<VertexArray>& vertexArray, uint32_t indexCount = 0) override; + + virtual void DrawArrays(uint32_t vertexCount, + uint32_t first = 0) override; + virtual void DrawLines(const Ref<VertexArray>& vertexArray, + uint32_t indexCount = 0) override; + virtual void BindTexture(uint32_t textureID, + uint32_t slot = 0) override; + virtual void BindImageTexture(uint32_t textureID, + uint32_t slot = 0, + bool readOnly = false) override; }; }; diff --git a/src/Platform/OpenGL/OpenGLUniformBuffer.h b/src/Platform/OpenGL/OpenGLUniformBuffer.h index 6e7fac1..fd96f37 100644 --- a/src/Platform/OpenGL/OpenGLUniformBuffer.h +++ b/src/Platform/OpenGL/OpenGLUniformBuffer.h @@ -12,11 +12,10 @@ namespace Donut virtual ~OpenGLUniformBuffer(); virtual void SetData(const void* data, uint32_t size, uint32_t offset = 0) override; - virtual void Bind(uint32_t binding) override; - + virtual void Bind(uint32_t binding) override; private: uint32_t m_RendererID = 0; - uint32_t m_Size = 0; - uint32_t m_Binding = 0; + uint32_t m_Size = 0; + uint32_t m_Binding = 0; }; }; diff --git a/src/Platform/Vulkan/VulkanRendererAPI.cpp b/src/Platform/Vulkan/VulkanRendererAPI.cpp index 6f0e73e..0dc9f0e 100644 --- a/src/Platform/Vulkan/VulkanRendererAPI.cpp +++ b/src/Platform/Vulkan/VulkanRendererAPI.cpp @@ -2,53 +2,73 @@ namespace Donut { - void VulkanRendererAPI::Init() - { - // TODO(Hachem): Implement Vulkan renderer API initialization - } + void VulkanRendererAPI::Init() + { + // TODO(Hachem): Implement Vulkan renderer API initialization + } - void VulkanRendererAPI::SetViewport(uint32_t x, uint32_t y, uint32_t width, uint32_t height) - { - // TODO(Hachem): Implement Vulkan viewport setting - } + void VulkanRendererAPI::SetViewport(uint32_t x, uint32_t y, uint32_t width, uint32_t height) + { + // TODO(Hachem): Implement Vulkan viewport setting + } - void VulkanRendererAPI::SetClearColor(const glm::vec4& color) - { - // TODO(Hachem): Implement Vulkan clear color setting - } + void VulkanRendererAPI::SetClearColor(const glm::vec4& color) + { + // TODO(Hachem): Implement Vulkan clear color setting + } - void VulkanRendererAPI::Clear() - { - // TODO(Hachem): Implement Vulkan clear - } + void VulkanRendererAPI::Clear() + { + // TODO(Hachem): Implement Vulkan clear + } - void VulkanRendererAPI::EnableDepthTest() - { - // TODO(Hachem): Implement Vulkan depth test enabling - } + void VulkanRendererAPI::EnableDepthTest() + { + // TODO(Hachem): Implement Vulkan depth test enabling + } - void VulkanRendererAPI::DisableDepthTest() - { - // TODO(Hachem): Implement Vulkan depth test disabling - } + void VulkanRendererAPI::DisableDepthTest() + { + // TODO(Hachem): Implement Vulkan depth test disabling + } - void VulkanRendererAPI::SetFaceCulling(bool enabled) - { - // TODO(Hachem): Implement Vulkan face culling setting - } + void VulkanRendererAPI::SetFaceCulling(bool enabled) + { + // TODO(Hachem): Implement Vulkan face culling setting + } - void VulkanRendererAPI::EnableBlending() - { - // TODO(Hachem): Implement Vulkan blending enabling - } + void VulkanRendererAPI::EnableBlending() + { + // TODO(Hachem): Implement Vulkan blending enabling + } - void VulkanRendererAPI::DisableBlending() - { - // TODO(Hachem): Implement Vulkan blending disabling - } + void VulkanRendererAPI::DisableBlending() + { + // TODO(Hachem): Implement Vulkan blending disabling + } - void VulkanRendererAPI::DrawIndexed(const Ref<VertexArray>& vertexArray, uint32_t indexCount) - { - // TODO(Hachem): Implement Vulkan indexed drawing - } + void VulkanRendererAPI::DrawIndexed(const Ref<VertexArray>& vertexArray, uint32_t indexCount) + { + // TODO(Hachem): Implement Vulkan indexed drawing + } + + void VulkanRendererAPI::DrawArrays(uint32_t vertexCount, uint32_t first) + { + // TODO(Hachem): Implement Vulkan array drawing + } + + void VulkanRendererAPI::DrawLines(const Ref<VertexArray>& vertexArray, uint32_t indexCount) + { + // TODO(Hachem): Implement Vulkan line drawing + } + + void VulkanRendererAPI::BindTexture(uint32_t textureID, uint32_t slot) + { + // TODO(Hachem): Implement Vulkan texture binding + } + + void VulkanRendererAPI::BindImageTexture(uint32_t textureID, uint32_t slot, bool readOnly) + { + // TODO(Hachem): Implement Vulkan image texture binding + } }; diff --git a/src/Platform/Vulkan/VulkanRendererAPI.h b/src/Platform/Vulkan/VulkanRendererAPI.h index 8ba3942..dba7fe6 100644 --- a/src/Platform/Vulkan/VulkanRendererAPI.h +++ b/src/Platform/Vulkan/VulkanRendererAPI.h @@ -5,22 +5,32 @@ namespace Donut { - class VulkanRendererAPI - : public RendererAPI - { - public: - virtual void Init() override; - virtual void SetViewport(uint32_t x, uint32_t y, - uint32_t width, uint32_t height) override; - virtual void SetClearColor(const glm::vec4& color) override; - virtual void Clear() override; - virtual void EnableDepthTest() override; - virtual void DisableDepthTest() override; - virtual void SetFaceCulling(bool enabled) override; - virtual void EnableBlending() override; - virtual void DisableBlending() override; + class VulkanRendererAPI + : public RendererAPI + { + public: + virtual void Init() override; + virtual void SetViewport(uint32_t x, uint32_t y, + uint32_t width, uint32_t height) override; + virtual void SetClearColor(const glm::vec4& color) override; + virtual void Clear() override; + virtual void EnableDepthTest() override; + virtual void DisableDepthTest() override; + virtual void SetFaceCulling(bool enabled) override; + virtual void EnableBlending() override; + virtual void DisableBlending() override; - virtual void DrawIndexed(const Ref<VertexArray>& vertexArray, - uint32_t indexCount = 0) override; - }; + virtual void DrawIndexed(const Ref<VertexArray>& vertexArray, + uint32_t indexCount = 0) override; + + virtual void DrawArrays(uint32_t vertexCount, + uint32_t first = 0) override; + virtual void DrawLines(const Ref<VertexArray>& vertexArray, + uint32_t indexCount = 0) override; + virtual void BindTexture(uint32_t textureID, + uint32_t slot = 0) override; + virtual void BindImageTexture(uint32_t textureID, + uint32_t slot = 0, + bool readOnly = false) override; + }; }; diff --git a/src/Platform/Vulkan/VulkanUniformBuffer.h b/src/Platform/Vulkan/VulkanUniformBuffer.h index a2e9ce2..bbf152d 100644 --- a/src/Platform/Vulkan/VulkanUniformBuffer.h +++ b/src/Platform/Vulkan/VulkanUniformBuffer.h @@ -11,10 +11,9 @@ namespace Donut virtual ~VulkanUniformBuffer(); virtual void SetData(const void* data, uint32_t size, uint32_t offset = 0) override; - virtual void Bind(uint32_t binding) override; - + virtual void Bind(uint32_t binding) override; private: - uint32_t m_Size = 0; - uint32_t m_Binding = 0; + uint32_t m_Size; + uint32_t m_Binding; }; }; diff --git a/src/Rendering/IndexBuffer.cpp b/src/Rendering/IndexBuffer.cpp index dc900ed..185684b 100644 --- a/src/Rendering/IndexBuffer.cpp +++ b/src/Rendering/IndexBuffer.cpp @@ -6,14 +6,14 @@ namespace Donut { - Ref<IndexBuffer> IndexBuffer::Create(const uint32_t* indices, uint32_t count) + IndexBuffer* IndexBuffer::Create(const uint32_t* indices, uint32_t count) { switch (Renderer::GetAPI()) { case RendererAPI::API::OpenGL: - return CreateRef<OpenGLIndexBuffer>(indices, count); + return new OpenGLIndexBuffer(indices, count); case RendererAPI::API::Vulkan: - return CreateRef<VulkanIndexBuffer>((uint32_t*)indices, count); + return new VulkanIndexBuffer((uint32_t*)indices, count); default: return nullptr; } diff --git a/src/Rendering/IndexBuffer.h b/src/Rendering/IndexBuffer.h index bb1b3a1..a58cc6c 100644 --- a/src/Rendering/IndexBuffer.h +++ b/src/Rendering/IndexBuffer.h @@ -1,6 +1,5 @@ #pragma once -#include "Core/Memory.h" #include <cstdint> namespace Donut @@ -14,6 +13,6 @@ namespace Donut virtual void Unbind() const = 0; virtual uint32_t GetCount() const = 0; - static Ref<IndexBuffer> Create(const uint32_t* indices, uint32_t count); + static IndexBuffer* Create(const uint32_t* indices, uint32_t count); }; }; diff --git a/src/Rendering/Renderer.cpp b/src/Rendering/Renderer.cpp index c1001d8..c0684cb 100644 --- a/src/Rendering/Renderer.cpp +++ b/src/Rendering/Renderer.cpp @@ -7,14 +7,14 @@ namespace Donut { - Ref<RendererAPI> RendererAPI::Create() + Scope<RendererAPI> RendererAPI::Create() { switch (s_API) { case API::OpenGL: - return CreateRef<OpenGLRendererAPI>(); + return CreateScope<OpenGLRendererAPI>(); case API::Vulkan: - return CreateRef<VulkanRendererAPI>(); + return CreateScope<VulkanRendererAPI>(); default: return nullptr; } @@ -50,7 +50,7 @@ namespace Donut RenderCommand::DrawIndexed(vertexArray); } - Ref<RendererAPI> RenderCommand::s_RendererAPI = RendererAPI::Create(); + Scope<RendererAPI> RenderCommand::s_RendererAPI = RendererAPI::Create(); void Renderer::SetClearColor(const glm::vec4& color) { diff --git a/src/Rendering/Renderer.h b/src/Rendering/Renderer.h index b2a44a4..d6c4154 100644 --- a/src/Rendering/Renderer.h +++ b/src/Rendering/Renderer.h @@ -20,23 +20,31 @@ namespace Donut public: virtual ~RendererAPI() = default; - virtual void Init() = 0; + virtual void Init() = 0; virtual void SetViewport(uint32_t x, uint32_t y, - uint32_t width, uint32_t height) = 0; - virtual void SetClearColor(const glm::vec4& color) = 0; - virtual void Clear() = 0; - virtual void EnableDepthTest() = 0; - virtual void DisableDepthTest() = 0; - virtual void SetFaceCulling(bool enabled) = 0; - virtual void EnableBlending() = 0; - virtual void DisableBlending() = 0; + uint32_t width, uint32_t height) = 0; + virtual void SetClearColor(const glm::vec4& color) = 0; + virtual void Clear() = 0; + virtual void EnableDepthTest() = 0; + virtual void DisableDepthTest() = 0; + virtual void SetFaceCulling(bool enabled) = 0; + virtual void EnableBlending() = 0; + virtual void DisableBlending() = 0; virtual void DrawIndexed(const Ref<VertexArray>& vertexArray, - uint32_t indexCount = 0) = 0; + uint32_t indexCount = 0) = 0; + + virtual void DrawArrays(uint32_t vertexCount, uint32_t first = 0) = 0; + virtual void DrawLines(const Ref<VertexArray>& vertexArray, + uint32_t indexCount = 0) = 0; + virtual void BindTexture(uint32_t textureID, uint32_t slot = 0) = 0; + virtual void BindImageTexture(uint32_t textureID, + uint32_t slot = 0, + bool readOnly = false) = 0; inline static API GetAPI() { return s_API; } inline static void SetAPI(API api) { s_API = api; } - static Ref<RendererAPI> Create(); + static Scope<RendererAPI> Create(); private: static API s_API; }; @@ -94,8 +102,28 @@ namespace Donut s_RendererAPI->DrawIndexed(vertexArray, indexCount); } + inline static void DrawArrays(uint32_t vertexCount, uint32_t first = 0) + { + s_RendererAPI->DrawArrays(vertexCount, first); + } + + inline static void DrawLines(const Ref<VertexArray>& vertexArray, uint32_t indexCount = 0) + { + s_RendererAPI->DrawLines(vertexArray, indexCount); + } + + inline static void BindTexture(uint32_t textureID, uint32_t slot = 0) + { + s_RendererAPI->BindTexture(textureID, slot); + } + + inline static void BindImageTexture(uint32_t textureID, uint32_t slot = 0, bool readOnly = false) + { + s_RendererAPI->BindImageTexture(textureID, slot, readOnly); + } + private: - static Ref<RendererAPI> s_RendererAPI; + static Scope<RendererAPI> s_RendererAPI; }; class Renderer diff --git a/src/Rendering/Shader.cpp b/src/Rendering/Shader.cpp index 2198663..8266e00 100644 --- a/src/Rendering/Shader.cpp +++ b/src/Rendering/Shader.cpp @@ -6,40 +6,40 @@ namespace Donut { - Ref<Shader> Shader::Create(const std::string& filepath) + Shader* Shader::Create(const std::string& filepath) { switch (Renderer::GetAPI()) { case RendererAPI::API::OpenGL: - return CreateRef<OpenGLShader>(filepath); + return new OpenGLShader(filepath); case RendererAPI::API::Vulkan: - return CreateRef<VulkanShader>(filepath); + return new VulkanShader(filepath); default: return nullptr; } } - Ref<Shader> Shader::Create(const std::string& name, const std::string& vertexSrc, const std::string& fragmentSrc) + Shader* Shader::Create(const std::string& name, const std::string& vertexSrc, const std::string& fragmentSrc) { switch (Renderer::GetAPI()) { case RendererAPI::API::OpenGL: - return CreateRef<OpenGLShader>(name, vertexSrc, fragmentSrc); + return new OpenGLShader(name, vertexSrc, fragmentSrc); case RendererAPI::API::Vulkan: - return CreateRef<VulkanShader>(name, vertexSrc, fragmentSrc); + return new VulkanShader(name, vertexSrc, fragmentSrc); default: return nullptr; } } - Ref<Shader> Shader::CreateCompute(const std::string& name, const std::string& computeSrc) + Shader* Shader::CreateCompute(const std::string& name, const std::string& computeSrc) { switch (Renderer::GetAPI()) { case RendererAPI::API::OpenGL: - return CreateRef<OpenGLShader>(name, computeSrc); + return new OpenGLShader(name, computeSrc); case RendererAPI::API::Vulkan: - return CreateRef<VulkanShader>(name, computeSrc); + return new VulkanShader(name, computeSrc); default: return nullptr; } @@ -58,14 +58,14 @@ namespace Donut Ref<Shader> ShaderLibrary::Load(const std::string& filepath) { - auto shader = Shader::Create(filepath); + auto shader = Ref<Shader>(Shader::Create(filepath)); Add(shader); return shader; } Ref<Shader> ShaderLibrary::Load(const std::string& name, const std::string& filepath) { - auto shader = Shader::Create(filepath); + auto shader = Ref<Shader>(Shader::Create(filepath)); Add(name, shader); return shader; } diff --git a/src/Rendering/Shader.h b/src/Rendering/Shader.h index 9cfecd9..e2d8d2a 100644 --- a/src/Rendering/Shader.h +++ b/src/Rendering/Shader.h @@ -35,9 +35,9 @@ namespace Donut virtual const std::string& GetName() const = 0; - static Ref<Shader> Create(const std::string& filepath); - static Ref<Shader> Create(const std::string& name, const std::string& vertexSrc, const std::string& fragmentSrc); - static Ref<Shader> CreateCompute(const std::string& name, const std::string& computeSrc); + static Shader* Create(const std::string& filepath); + static Shader* Create(const std::string& name, const std::string& vertexSrc, const std::string& fragmentSrc); + static Shader* CreateCompute(const std::string& name, const std::string& computeSrc); }; class ShaderLibrary diff --git a/src/Rendering/TextureManager.cpp b/src/Rendering/TextureManager.cpp new file mode 100644 index 0000000..9110558 --- /dev/null +++ b/src/Rendering/TextureManager.cpp @@ -0,0 +1,34 @@ +#include "TextureManager.h" +#include "Platform/OpenGL/OpenGLTexture.h" +#include "Platform/OpenGL/OpenGLRendererAPI.h" +#include <glad/glad.h> + +namespace Donut +{ + Ref<Texture2D> TextureManager::CreateTexture(uint32_t width, uint32_t height) + { + return CreateRef<OpenGLTexture2D>(width, height); + } + + void TextureManager::BindTexture(uint32_t textureID, uint32_t slot) + { + RenderCommand::BindTexture(textureID, slot); + } + + void TextureManager::BindImageTexture(uint32_t textureID, uint32_t slot, bool readOnly) + { + RenderCommand::BindImageTexture(textureID, slot, readOnly); + } + + void TextureManager::SetTextureData(uint32_t textureID, void* data, uint32_t width, uint32_t height) + { + glBindTexture(GL_TEXTURE_2D, textureID); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data); + } + + void TextureManager::ResizeTexture(uint32_t textureID, uint32_t width, uint32_t height) + { + glBindTexture(GL_TEXTURE_2D, textureID); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + } +}; diff --git a/src/Rendering/TextureManager.h b/src/Rendering/TextureManager.h new file mode 100644 index 0000000..0ab6c5f --- /dev/null +++ b/src/Rendering/TextureManager.h @@ -0,0 +1,19 @@ +#pragma once + +#include "Core/Memory.h" +#include "Rendering/Texture.h" +#include <cstdint> + +namespace Donut +{ + class TextureManager + { + public: + static Ref<Texture2D> CreateTexture(uint32_t width, uint32_t height); + + static void BindTexture(uint32_t textureID, uint32_t slot = 0); + static void BindImageTexture(uint32_t textureID, uint32_t slot = 0, bool readOnly = false); + static void SetTextureData(uint32_t textureID, void* data, uint32_t width, uint32_t height); + static void ResizeTexture(uint32_t textureID, uint32_t width, uint32_t height); + }; +}; diff --git a/src/Rendering/VertexArray.cpp b/src/Rendering/VertexArray.cpp index bca1f4a..366675f 100644 --- a/src/Rendering/VertexArray.cpp +++ b/src/Rendering/VertexArray.cpp @@ -17,14 +17,14 @@ namespace Donut } } - Ref<VertexArray> VertexArray::Create() + VertexArray* VertexArray::Create() { switch (Renderer::GetAPI()) { case RendererAPI::API::OpenGL: - return CreateRef<OpenGLVertexArray>(); + return new OpenGLVertexArray(); case RendererAPI::API::Vulkan: - return CreateRef<VulkanVertexArray>(); + return new VulkanVertexArray(); default: return nullptr; } diff --git a/src/Rendering/VertexArray.h b/src/Rendering/VertexArray.h index aa857e4..10fff89 100644 --- a/src/Rendering/VertexArray.h +++ b/src/Rendering/VertexArray.h @@ -23,6 +23,6 @@ namespace Donut virtual const std::vector<Ref<VertexBuffer>>& GetVertexBuffers() const = 0; virtual const Ref<IndexBuffer>& GetIndexBuffer() const = 0; - static Ref<VertexArray> Create(); + static VertexArray* Create(); }; }; diff --git a/src/Rendering/VertexBuffer.cpp b/src/Rendering/VertexBuffer.cpp index dd59546..a7e2504 100644 --- a/src/Rendering/VertexBuffer.cpp +++ b/src/Rendering/VertexBuffer.cpp @@ -6,14 +6,14 @@ namespace Donut { - Ref<VertexBuffer> VertexBuffer::Create(const void* data, uint32_t size) + VertexBuffer* VertexBuffer::Create(const void* data, uint32_t size) { switch (Renderer::GetAPI()) { case RendererAPI::API::OpenGL: - return CreateRef<OpenGLVertexBuffer>(data, size); + return new OpenGLVertexBuffer(data, size); case RendererAPI::API::Vulkan: - return CreateRef<VulkanVertexBuffer>((float*)data, size); + return new VulkanVertexBuffer((float*)data, size); default: return nullptr; } diff --git a/src/Rendering/VertexBuffer.h b/src/Rendering/VertexBuffer.h index db85755..35b9a84 100644 --- a/src/Rendering/VertexBuffer.h +++ b/src/Rendering/VertexBuffer.h @@ -1,7 +1,5 @@ #pragma once -#include "Core/Memory.h" - #include <cstdint> #include <vector> @@ -24,7 +22,7 @@ namespace Donut ~VertexBufferLayout() = default; template<typename T> - void Push(uint32_t count) + void Push(uint32_t count) { static_assert(false); } @@ -70,6 +68,6 @@ namespace Donut virtual const VertexBufferLayout& GetLayout() const = 0; virtual void SetLayout(const VertexBufferLayout& layout) = 0; - static Ref<VertexBuffer> Create(const void* data, uint32_t size); + static VertexBuffer* Create(const void* data, uint32_t size); }; }; diff --git a/src/States/ConfigState.cpp b/src/States/ConfigState.cpp index 316038e..8fd59db 100644 --- a/src/States/ConfigState.cpp +++ b/src/States/ConfigState.cpp @@ -22,7 +22,7 @@ namespace Donut void ConfigState::OnRender() { - Renderer::SetClearColor({ 0.1f, 0.1f, 0.2f, 1.0f }); + Renderer::SetClearColor({ 0.1f, 0.1f, 0.1f, 1.0f }); Renderer::Clear(); } diff --git a/src/States/SimulationState.cpp b/src/States/SimulationState.cpp index 4663e99..98640e0 100644 --- a/src/States/SimulationState.cpp +++ b/src/States/SimulationState.cpp @@ -22,11 +22,11 @@ namespace Donut void SimulationState::OnUpdate(float deltaTime) { - + m_Engine.UpdatePerformance(deltaTime); m_Engine.UpdateWindowDimensions(); m_Engine.UpdatePhysics(deltaTime); - - if (m_Engine.GetCamera().IsDragging()) + + if (m_Engine.GetCamera().IsDragging()) { GLFWwindow* window = static_cast<GLFWwindow*>(Application::Get().GetWindow().GetNativeWindow()); double xpos, ypos; @@ -37,34 +37,28 @@ namespace Donut void SimulationState::OnRender() { - if (!m_Initialized) return; - RenderCommand::SetClearColor(glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)); RenderCommand::Clear(); - - m_Engine.GenerateGrid(m_Engine.GetObjects()); - - glm::mat4 view = glm::lookAt(m_Engine.GetCamera().GetOrbitalPosition(), m_Engine.GetCamera().GetTarget(), glm::vec3(0,1,0)); - glm::mat4 proj = glm::perspective(glm::radians(60.0f), float(m_Engine.GetWidth())/m_Engine.GetHeight(), 1e9f, 1e14f); - glm::mat4 viewProj = proj * view; - - m_Engine.DrawGrid(viewProj); - RenderCommand::SetViewport(0, 0, m_Engine.GetWidth(), m_Engine.GetHeight()); + m_Engine.DispatchCompute(m_Engine.GetCamera()); m_Engine.DrawFullScreenQuad(); } void SimulationState::OnEvent(Event& event) { - if (!m_Initialized) return; - if (event.GetEventType() == EventType::MouseButtonPressed) { MouseButtonPressedEvent& e = (MouseButtonPressedEvent&)event; int button = e.GetMouseButton(); - m_Engine.GetCamera().ProcessOrbitalMouseButton(button, GLFW_PRESS, 0); + GLFWwindow* window = static_cast<GLFWwindow*>(Application::Get().GetWindow().GetNativeWindow()); + Camera& camera = m_Engine.GetCamera(); + double lastX = camera.GetLastX(); + double lastY = camera.GetLastY(); + glfwGetCursorPos(window, &lastX, &lastY); + + camera.ProcessOrbitalMouseButton(button, GLFW_PRESS, 0); } else if (event.GetEventType() == EventType::MouseButtonReleased) { @@ -84,7 +78,7 @@ namespace Donut KeyPressedEvent& e = (KeyPressedEvent&)event; if (e.GetKeyCode() == GLFW_KEY_G) { - m_Engine.SetGravity(!m_Engine.GetGravity()); + m_Engine.GetGravity() = !m_Engine.GetGravity(); DONUT_INFO("Gravity turned {}", m_Engine.GetGravity() ? "ON" : "OFF"); } } @@ -109,6 +103,27 @@ namespace Donut ImGui::Separator(); + ImGui::Text("Performance:"); + ImGui::Text("Engine FPS: %.1f", m_Engine.GetCurrentFPS()); + ImGui::Text("Target FPS: %d", m_Engine.GetTargetFPS()); + + int targetFPS = m_Engine.GetTargetFPS(); + if (ImGui::SliderInt("Target FPS", &targetFPS, 30, 120)) + { + m_Engine.SetTargetFPS(targetFPS); + } + + int computeHeight = m_Engine.GetComputeHeight(); + if (ImGui::SliderInt("Compute Height", &computeHeight, 64, 2048)) + { + m_Engine.SetComputeHeight(computeHeight); + m_Engine.UpdateComputeDimensions(); + } + + ImGui::Text("Compute Width: %d (auto-calculated)", m_Engine.GetComputeWidth()); + + ImGui::Separator(); + ImGui::Text("Controls:"); ImGui::Text("Left Mouse: Orbit camera"); ImGui::Text("Scroll: Zoom in/out"); @@ -118,16 +133,15 @@ namespace Donut ImGui::Separator(); ImGui::Text("Physics:"); - bool gravity = m_Engine.GetGravity(); - if (ImGui::Checkbox("Gravity Enabled", &gravity)) - m_Engine.SetGravity(gravity); + bool& gravity = m_Engine.GetGravity(); + ImGui::Checkbox("Gravity Enabled", &gravity); ImGui::Text("Camera:"); ImGui::Text("Position: (%.2e, %.2e, %.2e)", m_Engine.GetCamera().GetOrbitalPosition().x, m_Engine.GetCamera().GetOrbitalPosition().y, m_Engine.GetCamera().GetOrbitalPosition().z); - ImGui::Text("Radius: %.2e", m_Engine.GetCamera().GetRadius()); + ImGui::Text("Radius: %.2e", m_Engine.GetCamera().GetOrbitalRadius()); ImGui::Text("Azimuth: %.2f", m_Engine.GetCamera().GetAzimuth()); ImGui::Text("Elevation: %.2f", m_Engine.GetCamera().GetElevation()); diff --git a/src/States/SimulationState.h b/src/States/SimulationState.h index ba1c242..2db4738 100644 --- a/src/States/SimulationState.h +++ b/src/States/SimulationState.h @@ -23,6 +23,6 @@ namespace Donut private: Engine m_Engine; - bool m_Initialized = false; + bool m_Initialized = false; }; }; |
