aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Assets/Shaders/ComputeTextureQuad.glsl27
-rw-r--r--Assets/Shaders/Geodesic.glsl232
-rw-r--r--Assets/Shaders/Grid.glsl19
-rw-r--r--Assets/Shaders/Quad.glsl25
-rw-r--r--src/Core/Camera.cpp79
-rw-r--r--src/Core/Camera.h83
-rw-r--r--src/Engine/Engine.cpp318
-rw-r--r--src/Engine/Engine.h87
-rw-r--r--src/Engine/Object.cpp46
-rw-r--r--src/Engine/Object.h43
-rw-r--r--src/Engine/Scene.cpp57
-rw-r--r--src/Engine/Scene.h55
-rw-r--r--src/Platform/OpenGL/OpenGLRendererAPI.cpp23
-rw-r--r--src/Platform/OpenGL/OpenGLRendererAPI.h10
-rw-r--r--src/Platform/OpenGL/OpenGLUniformBuffer.h7
-rw-r--r--src/Platform/Vulkan/VulkanRendererAPI.cpp100
-rw-r--r--src/Platform/Vulkan/VulkanRendererAPI.h44
-rw-r--r--src/Platform/Vulkan/VulkanUniformBuffer.h7
-rw-r--r--src/Rendering/IndexBuffer.cpp6
-rw-r--r--src/Rendering/IndexBuffer.h3
-rw-r--r--src/Rendering/Renderer.cpp8
-rw-r--r--src/Rendering/Renderer.h52
-rw-r--r--src/Rendering/Shader.cpp22
-rw-r--r--src/Rendering/Shader.h6
-rw-r--r--src/Rendering/TextureManager.cpp34
-rw-r--r--src/Rendering/TextureManager.h19
-rw-r--r--src/Rendering/VertexArray.cpp6
-rw-r--r--src/Rendering/VertexArray.h2
-rw-r--r--src/Rendering/VertexBuffer.cpp6
-rw-r--r--src/Rendering/VertexBuffer.h6
-rw-r--r--src/States/ConfigState.cpp2
-rw-r--r--src/States/SimulationState.cpp58
-rw-r--r--src/States/SimulationState.h2
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;
};
};