diff options
Diffstat (limited to 'src/engine')
| -rw-r--r-- | src/engine/engine.cpp | 317 | ||||
| -rw-r--r-- | src/engine/engine.h | 87 | ||||
| -rw-r--r-- | src/engine/object.cpp | 46 | ||||
| -rw-r--r-- | src/engine/object.h | 43 | ||||
| -rw-r--r-- | src/engine/scene.cpp | 57 | ||||
| -rw-r--r-- | src/engine/scene.h | 55 |
6 files changed, 249 insertions, 356 deletions
diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 29fa65a..c2a84a8 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/vertex_buffer.h" #include "rendering/index_buffer.h" namespace Donut { - Engine::Engine() - : m_sag_a(glm::vec3(0.0f, 0.0f, 0.0f), - static_cast<float>(8.54e36)) + Engine::Engine() + : m_sag_a(glm::vec3(0.0f, 0.0f, 0.0f), 8.54e36f) { GLFWwindow* window = static_cast<GLFWwindow*>(Application::get().get_window().get_native_window()); glfwGetFramebufferSize(window, &m_width, &m_height); - m_compute_height = 420; - m_compute_width = (m_width * 420) / m_height; - m_camera.set_orbital_mode(true); - m_camera.set_radius(6.34194e10); - m_camera.set_min_radius(1e10); - m_camera.set_max_radius(1e12); - m_camera.set_orbit_speed(0.01f); + m_camera.set_camera_mode(CameraMode::Orbital); + m_camera.set_orbital_radius(6.34194e10); + m_camera.set_orbital_limits(1e10, 1e12); + m_camera.set_orbital_speed(0.01f); m_camera.set_zoom_speed(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_sag_a.m_rs), glm::vec4(0,0,0,1), static_cast<float>(m_sag_a.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_sag_a.m_rs), glm::vec4(0, 0, 0, 1), static_cast<float>(m_sag_a.m_mass) } }; - m_quad_shader = Shader::create("assets/shaders/quad.glsl"); - m_grid_shader = Shader::create("assets/shaders/grid.glsl"); - m_compute_shader = Shader::create_compute("Geodesic", load_compute_shader("assets/shaders/geodesic.glsl")); + m_shader_program = Ref<Shader>(Shader::create("assets/shaders/compute_texture_quad.glsl")); + m_compute_program = create_compute_program("assets/shaders/geodesic.glsl"); m_camera_ubo = UniformBuffer::create(128, 1); - m_disk_ubo = UniformBuffer::create(sizeof(float) * 4, 2); + m_disk_ubo = UniformBuffer::create(sizeof(float) * 4, 2); uint32_t obj_ubo_size = sizeof(int) + 3 * sizeof(float) + 16 * (sizeof(glm::vec4) + sizeof(glm::vec4)) + 16 * sizeof(float); m_objects_ubo = UniformBuffer::create(obj_ubo_size, 3); - float quad_vertices[] = - { - -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_quad_vao = VertexArray::create(); - - auto vertex_buffer = VertexBuffer::create(quad_vertices, static_cast<uint32_t>(sizeof(quad_vertices))); - VertexBufferLayout layout; - layout.push<float>(2); - layout.push<float>(2); - vertex_buffer->set_layout(layout); - m_quad_vao->add_vertex_buffer(vertex_buffer); - - m_texture = Texture2D::create(m_width, m_height); + auto result = quad_vao(); + m_quad_vao = result.first; + m_texture = result.second; } - void Engine::generate_grid(const std::vector<ObjectData>& objects) + void Engine::update_window_dimensions() { - const int grid_size = 25; - const float spacing = 1e10f; - - std::vector<glm::vec3> vertices; - std::vector<uint32_t> indices; - - for (int z = 0; z <= grid_size; ++z) - { - for (int x = 0; x <= grid_size; ++x) - { - float world_x = (x - grid_size / 2) * spacing; - float world_z = (z - grid_size / 2) * spacing; - float y = 0.0f; - - for (const auto& obj : objects) - { - glm::vec3 obj_pos = glm::vec3(obj.m_pos_radius); - double mass = obj.m_mass; - double radius = obj.m_pos_radius.w; - - double r_s = 2.0 * G * mass / (c * c); - double dx = world_x - obj_pos.x; - double dz = world_z - obj_pos.z; - double dist = sqrt(dx * dx + dz * dz); - - if (dist > r_s) - { - double delta_y = 2.0 * sqrt(r_s * (dist - r_s)); - y += static_cast<float>(delta_y) - 3e10f; - } - else - { - y += 2.0f * static_cast<float>(sqrt(r_s * r_s)) - 3e10f; - } - } - - vertices.emplace_back(world_x, y, world_z); - } - } - - for (int z = 0; z < grid_size; ++z) - { - for (int x = 0; x < grid_size; ++x) - { - int i = z * (grid_size + 1) + x; - indices.push_back(i); - indices.push_back(i + 1); - indices.push_back(i); - indices.push_back(i + grid_size + 1); - } - } - - if (!m_grid_vao) - { - m_grid_vao = Ref<VertexArray>(VertexArray::create()); - - auto vertex_buffer = Ref<VertexBuffer>(VertexBuffer::create(vertices.data(), static_cast<uint32_t>(vertices.size() * sizeof(glm::vec3)))); - VertexBufferLayout layout; - layout.push<float>(3); - vertex_buffer->set_layout(layout); - m_grid_vao->add_vertex_buffer(vertex_buffer); - - auto index_buffer = Ref<IndexBuffer>(IndexBuffer::create(indices.data(), static_cast<uint32_t>(indices.size()))); - m_grid_vao->set_index_buffer(index_buffer); - } - else - { - auto vertex_buffer = m_grid_vao->get_vertex_buffers()[0]; - vertex_buffer->set_data(vertices.data(), static_cast<uint32_t>(vertices.size() * sizeof(glm::vec3))); - } - - m_grid_index_count = static_cast<int>(indices.size()); + GLFWwindow* window = static_cast<GLFWwindow*>(Application::get().get_window().get_native_window()); + int old_width = m_width; + int old_height = m_height; + int old_compute_height = m_compute_height; + + glfwGetFramebufferSize(window, &m_width, &m_height); + + if (old_width != m_width || + old_height != m_height || + old_compute_height != m_compute_height) + update_compute_dimensions(); } - void Engine::draw_grid(const glm::mat4& view_proj) + void Engine::update_performance(float delta_time) { - if (!m_grid_shader || !m_grid_vao) - return; - - m_grid_shader->bind(); - m_grid_shader->set_mat4("viewProj", view_proj); - - RenderCommand::disable_depth_test(); - RenderCommand::enable_blending(); - - m_grid_vao->bind(); - glDrawElements(GL_LINES, m_grid_index_count, GL_UNSIGNED_INT, nullptr); - - RenderCommand::enable_depth_test(); + if (delta_time > 0.0f) + m_current_fps = 1.0f / delta_time; } - void Engine::update_window_dimensions() + void Engine::update_compute_dimensions() { - GLFWwindow* window = static_cast<GLFWwindow*>(Application::get().get_window().get_native_window()); - int old_width = m_width; - int old_height = m_height; - glfwGetFramebufferSize(window, &m_width, &m_height); - m_compute_height = 420; - m_compute_width = (m_width * 420) / m_height; - - if (old_width != m_width || old_height != m_height) - m_texture = Texture2D::create(m_width, m_height); + m_texture = Texture2D::create(get_compute_width(), m_compute_height); } - void Engine::draw_full_screen_quad() + void Engine::draw_full_screen_quad() { RenderCommand::set_viewport(0, 0, m_width, m_height); - m_quad_shader->bind(); - std::cout << "Texture ID: " << m_texture->get_renderer_id() << ", Size: " << m_texture->get_width() << "x" << m_texture->get_height() << std::endl; + m_shader_program->bind(); + m_quad_vao->bind(); + m_texture->bind(0); - m_quad_shader->set_int("screenTexture", 0); - std::cout << "Set screenTexture uniform to slot 0\n"; + m_shader_program->set_int("u_ScreenTexture", 0); RenderCommand::disable_depth_test(); - RenderCommand::draw_indexed(m_quad_vao, 6); + RenderCommand::draw_arrays(6); RenderCommand::enable_depth_test(); } - void Engine::dispatch_compute(const Camera& cam) + void Engine::dispatch_compute(const Camera& cam) { - int cw = m_compute_width; + int cw = get_compute_width(); int ch = m_compute_height; - if (m_texture->get_width() != cw || m_texture->get_height() != ch) - m_texture = Texture2D::create(cw, ch); + m_texture->set_data(nullptr, cw * ch * 4); - m_compute_shader->bind(); + m_compute_program->bind(); upload_camera_ubo(cam); upload_disk_ubo(); upload_objects_ubo(m_objects); - m_texture->bind_as_image(0, false); - uint32_t groups_x = (uint32_t)std::ceil(cw / 16.0f); - uint32_t groups_y = (uint32_t)std::ceil(ch / 16.0f); - m_compute_shader->dispatch(groups_x, groups_y, 1); - m_compute_shader->memory_barrier(IMAGE_ACCESS_BARRIER_BIT); - - glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); - glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); + uint32_t groups_x = static_cast<uint32_t>(std::ceil(cw / 16.0f)); + uint32_t groups_y = static_cast<uint32_t>(std::ceil(ch / 16.0f)); + m_compute_program->dispatch(groups_x, groups_y, 1); + m_compute_program->memory_barrier(IMAGE_ACCESS_BARRIER_BIT); } - void Engine::upload_camera_ubo(const Camera& cam) + void Engine::upload_camera_ubo(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 tan_half_fov; float aspect; - bool moving; - int _pad4; + bool moving; + int _pad4; } data; - glm::vec3 fwd = glm::normalize(cam.get_target() - cam.get_orbital_position()); - glm::vec3 up = glm::vec3(0, 1, 0); + glm::vec3 fwd = glm::normalize(cam.get_orbital_target() - cam.get_orbital_position()); + 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.get_orbital_position(); - data.right = right; - data.up = up; - data.forward = fwd; + data.pos = cam.get_orbital_position(); + data.right = right; + data.up = up; + data.forward = fwd; data.tan_half_fov = 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.is_dragging() || cam.is_panning(); + data.aspect = static_cast<float>(get_compute_width()) / static_cast<float>(m_compute_height); + data.moving = cam.is_dragging() || cam.is_panning(); m_camera_ubo->set_data(&data, sizeof(UBOData)); + m_camera_ubo->bind(1); } - void Engine::upload_objects_ubo(const std::vector<ObjectData>& objs) + void Engine::upload_objects_ubo(const std::vector<ObjectData>& objs) { - struct UBOData + struct UBOData { int num_objects; float _pad0, _pad1, _pad2; @@ -257,7 +150,7 @@ namespace Donut size_t count = std::min(objs.size(), size_t(16)); data.num_objects = static_cast<int>(count); - for (size_t i = 0; i < count; ++i) + for (size_t i = 0; i < count; ++i) { data.pos_radius[i] = objs[i].m_pos_radius; data.color[i] = objs[i].m_color; @@ -265,9 +158,10 @@ namespace Donut } m_objects_ubo->set_data(&data, sizeof(data)); + m_objects_ubo->bind(3); } - void Engine::upload_disk_ubo() + void Engine::upload_disk_ubo() { float r1 = static_cast<float>(m_sag_a.m_rs * 2.2); float r2 = static_cast<float>(m_sag_a.m_rs * 5.2); @@ -276,28 +170,28 @@ namespace Donut float disk_data[4] = { r1, r2, num, thickness }; m_disk_ubo->set_data(disk_data, sizeof(disk_data)); + m_disk_ubo->bind(2); } - void Engine::update_physics(float delta_time) + void Engine::update_physics(float delta_time) { - 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_pos_radius.x - obj.m_pos_radius.x; float dy = obj2.m_pos_radius.y - obj.m_pos_radius.y; float dz = obj2.m_pos_radius.z - obj.m_pos_radius.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,49 @@ namespace Donut void Engine::render_scene() { - glm::mat4 view = glm::lookAt(m_camera.get_orbital_position(), m_camera.get_target(), glm::vec3(0,1,0)); - glm::mat4 proj = glm::perspective(glm::radians(60.0f), float(m_width)/m_height, 1e9f, 1e14f); - glm::mat4 view_proj = proj * view; - - generate_grid(m_objects); - draw_grid(view_proj); - - RenderCommand::set_viewport(0, 0, m_width, m_height); - dispatch_compute(m_camera); - draw_full_screen_quad(); + RenderCommand::clear(); + m_shader_program->bind(); + m_quad_vao->bind(); + m_texture->bind(0); + RenderCommand::draw_arrays(6); } - std::string Engine::load_compute_shader(const std::string& path) + Ref<Shader> Engine::create_compute_program(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 src_str = ss.str(); + return Ref<Shader>(Shader::create_compute("ComputeShader", src_str)); + } + + std::pair<Ref<VertexArray>, Ref<Texture2D>> Engine::quad_vao() + { + float quad_vertices[] = + { + -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 vertex_buffer = Ref<VertexBuffer>(VertexBuffer::create(quad_vertices, static_cast<uint32_t>(sizeof(quad_vertices)))); + VertexBufferLayout layout; + layout.push<float>(2); + layout.push<float>(2); + vertex_buffer->set_layout(layout); + + auto vertex_array = Ref<VertexArray>(VertexArray::create()); + vertex_array->add_vertex_buffer(vertex_buffer); + auto texture = Texture2D::create(get_compute_width(), m_compute_height); + + return { vertex_array, texture }; } } diff --git a/src/engine/engine.h b/src/engine/engine.h index 6f90efb..39791c1 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/vertex_array.h" +#include "rendering/texture.h" #include "rendering/uniform_buffer.h" +#include "rendering/texture_manager.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_pos_radius; 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 generate_grid(const std::vector<ObjectData>& objects); - void draw_grid(const glm::mat4& view_proj); void draw_full_screen_quad(); void dispatch_compute(const Camera& cam); void upload_camera_ubo(const Camera& cam); @@ -73,46 +77,47 @@ namespace Donut void update_physics(float delta_time); void update_window_dimensions(); - Camera& get_camera() { return m_camera; } - const Camera& get_camera() const { return m_camera; } - - const std::vector<ObjectData>& get_objects() const { return m_objects; } - std::vector<ObjectData>& get_objects() { return m_objects; } - - bool get_gravity() const { return m_gravity; } - void set_gravity(bool gravity) { m_gravity = gravity; } - - int get_width() const { return m_width; } - int get_height() const { return m_height; } - int get_compute_width() const { return m_compute_width; } - int get_compute_height() const { return m_compute_height; } + int get_width() const { return m_width; } + int get_height() const { return m_height; } + + std::vector<ObjectData>& get_objects() { return m_objects; } + BlackHole& get_sag_a() { return m_sag_a; } + Camera& get_camera() { return m_camera; } + bool& get_gravity() { return m_gravity; } + void update_performance(float delta_time); + void set_target_fps(int fps) { m_target_fps = fps; } + int get_target_fps() const { return m_target_fps; } + float get_current_fps() const { return m_current_fps; } + void set_compute_height(int height) { m_compute_height = height; } + int get_compute_height() const { return m_compute_height; } + int get_compute_width() const { return (m_width * m_compute_height) / m_height; } + void update_compute_dimensions(); private: - std::string create_basic_vertex_shader(); - std::string create_basic_fragment_shader(); - std::string load_compute_shader(const std::string& path); + Ref<Shader> create_compute_program(const char* path); + std::pair<Ref<VertexArray>, Ref<Texture2D>> quad_vao(); private: - Ref<Shader> m_grid_shader; - Ref<Shader> m_quad_shader; - Ref<Shader> m_compute_shader; - Ref<Texture2D> m_texture; Ref<VertexArray> m_quad_vao; - Ref<VertexArray> m_grid_vao; + Ref<Texture2D> m_texture; + Ref<Shader> m_shader_program; + Ref<Shader> m_compute_program; Ref<UniformBuffer> m_camera_ubo; Ref<UniformBuffer> m_disk_ubo; Ref<UniformBuffer> m_objects_ubo; - - int m_grid_index_count = 0; + int m_width; int m_height; - int m_compute_width; - int m_compute_height; - float m_width_scale = 100000000000.0f; - float m_height_scale = 75000000000.0f; + float m_width_f = 100*10e10f; + float m_height_f = 75*10e10f; + + int m_target_fps = 60; + float m_current_fps = 60.0f; + float m_last_frame_time = 0.0f; + int m_compute_height = 320; std::vector<ObjectData> m_objects; BlackHole m_sag_a; Camera m_camera; bool m_gravity = false; }; -} +}; diff --git a/src/engine/object.cpp b/src/engine/object.cpp deleted file mode 100644 index 2e76b16..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::get_normal(glm::vec3 &point) const - { - return glm::normalize(point - m_centre); - } -} diff --git a/src/engine/object.h b/src/engine/object.h index 5f5d86f..c45815b 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 get_normal(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 get_normal(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 bfac1aa..0000000 --- a/src/engine/scene.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "scene.h" - -namespace Donut -{ - Scene::Scene() - : m_light_pos(5.0f, 5.0f, 5.0f) { } - - glm::vec3 Scene::trace(Ray &ray) - { - float closest = std::numeric_limits<float>::infinity(); - const Object* hit_obj = nullptr; - - for(auto& obj : objs) - { - float t; - - if(obj.intersect(ray, t)) - if(t < closest) - { - closest = t; - hit_obj = &obj; - } - } - - if(hit_obj) - { - glm::vec3 hit_point = ray.m_origin + ray.m_direction * closest; - glm::vec3 normal = hit_obj->get_normal(hit_point); - glm::vec3 light_dir = glm::normalize(m_light_pos - hit_point); - - float diff = std::max(glm::dot(normal, light_dir), 0.0f); - - Ray shadow_ray(hit_point + normal * 0.001f, light_dir); - bool in_shadow = false; - - for(auto& obj : objs) - { - float t; - - if(obj.intersect(shadow_ray, t)) - { - in_shadow = true; - break; - } - } - - glm::vec3 color = hit_obj->m_material.m_color; - float ambient = 0.1f; - - if (in_shadow) - 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 abe582e..2ac9cd8 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_light_pos; - Scene(); - glm::vec3 trace(Ray &ray); + Scene() + : m_light_pos(5.0f, 5.0f, 5.0f) { } + + glm::vec3 trace(Ray &ray) + { + float closest = std::numeric_limits<float>::infinity(); + const Object* hit_obj = nullptr; + + for(auto& obj : objs) + { + float t; + + if(obj.intersect(ray, t)) + if(t < closest) + { + closest = t; + hit_obj = &obj; + } + } + + if(hit_obj) + { + glm::vec3 hit_point = ray.m_origin + ray.m_direction * closest; + glm::vec3 normal = hit_obj->get_normal(hit_point); + glm::vec3 light_dir = glm::normalize(m_light_pos - hit_point); + + float diff = std::max(glm::dot(normal, light_dir), 0.0f); + + Ray shadow_ray(hit_point + normal * 0.001f, light_dir); + bool in_shadow = false; + + for(auto& obj : objs) + { + float t; + + if(obj.intersect(shadow_ray, t)) + { + in_shadow = true; + break; + } + } + + glm::vec3 color = hit_obj->m_material.m_color; + float ambient = 0.1f; + + if (in_shadow) + return color * ambient; + return color * (ambient + diff * 0.9f); + } + + return glm::vec3(0.0f, 0.0f, 0.1f); + } }; }; |
