From 216e9a684a50cd3e7c2a465e7e0f9db7457aed05 Mon Sep 17 00:00:00 2001 From: TheRedShip Date: Tue, 24 Dec 2024 01:44:53 +0100 Subject: [PATCH] + | Multiple sphere sent to GPU working --- includes/RT.hpp | 6 ++-- includes/RT/Object.hpp | 33 ++++++++++++------ includes/RT/Scene.hpp | 24 +++++++++++-- includes/RT/Shader.hpp | 3 +- includes/RT/objects/Sphere.hpp | 11 +++--- shaders/compute.glsl | 61 +++++++++++++++++++++++++--------- srcs/RT.cpp | 36 +++++++++++++++----- srcs/class/Object.cpp | 12 ------- srcs/class/Scene.cpp | 35 ++++++++++++++++++- srcs/class/Shader.cpp | 7 ++-- 10 files changed, 166 insertions(+), 62 deletions(-) delete mode 100644 srcs/class/Object.cpp diff --git a/includes/RT.hpp b/includes/RT.hpp index c1016e9..19b56fe 100644 --- a/includes/RT.hpp +++ b/includes/RT.hpp @@ -16,7 +16,6 @@ # define WIDTH 1920 # define HEIGHT 1080 - # include "glm/glm.hpp" # include "glm/gtc/matrix_transform.hpp" # include "glm/gtc/type_ptr.hpp" @@ -24,14 +23,17 @@ # include "glad/gl.h" # include "GLFW/glfw3.h" - # include +# include struct Vertex { glm::vec2 position; glm::vec2 texCoord; }; +# include "Object.hpp" +# include "objects/Sphere.hpp" + # include "Camera.hpp" # include "Window.hpp" # include "Shader.hpp" diff --git a/includes/RT/Object.hpp b/includes/RT/Object.hpp index 204d9c4..1bb5ad4 100644 --- a/includes/RT/Object.hpp +++ b/includes/RT/Object.hpp @@ -13,20 +13,33 @@ #ifndef RT_OBJECT__HPP # define RT_OBJECT__HPP -#include "RT.hpp" +# include "RT.hpp" + +typedef struct s_Material +{ + glm::vec3 color; + float roughness; + float specular; +} Material; class Object { - public: - glm::vec3 position; - glm::vec3 color; - - Object(const glm::vec3& pos, const glm::vec3& col) : position(pos), color(col) {} - virtual ~Object() = default; - - // virtual bool hit(const glm::vec3& rayOrigin, const glm::vec3& rayDir, float& t, glm::vec3& hitNormal) const = 0; + protected: + glm::vec3 _position; + Material _material; - + public: + Object(const glm::vec3& position, const Material& material) : _position(position), _material(material) {} + virtual ~Object() = default; + + const glm::vec3& getPosition() const { return (_position); } + const Material& getMaterial() const { return (_material); } + + enum class Type { + SPHERE, + }; + + virtual Type getType() const = 0; }; #endif \ No newline at end of file diff --git a/includes/RT/Scene.hpp b/includes/RT/Scene.hpp index 59462d1..bdeaea9 100644 --- a/includes/RT/Scene.hpp +++ b/includes/RT/Scene.hpp @@ -15,6 +15,19 @@ # include "RT.hpp" +struct GPUObject +{ + glm::vec3 position; + int padding_1; + glm::vec3 color; + int padding_2; + float roughness; + float specular; + float radius; + int type; +}; + +class Sphere; class Camera; class Scene @@ -23,11 +36,16 @@ class Scene Scene(); ~Scene(); - Camera *getCamera(void) const; - // Object *getObjects(void) const; + Camera *getCamera(void) const; + void addObject(std::unique_ptr object); + + void updateGPUData(); + const std::vector& getGPUData() const; private: - // Object *_objects; + std::vector> _objects; + std::vector _gpuObjects; + Camera *_camera; }; diff --git a/includes/RT/Shader.hpp b/includes/RT/Shader.hpp index dc8759c..73d8609 100644 --- a/includes/RT/Shader.hpp +++ b/includes/RT/Shader.hpp @@ -21,7 +21,6 @@ class Shader Shader(std::string vertexPath, std::string fragmentPath, std::string computePath); ~Shader(void); - // void compile(const char *vertexSource, const char *fragmentSource); void attach(void); void setupVertexBuffer(const Vertex* vertices, size_t size); void drawTriangles(size_t size); @@ -29,7 +28,7 @@ class Shader // void setBool(const std::string &name, bool value) const; - // void setInt(const std::string &name, int value) const; + void set_int(const std::string &name, int value) const; // void setFloat(const std::string &name, float value) const; void set_vec2(const std::string &name, const glm::vec2 &value) const; void set_vec3(const std::string &name, const glm::vec3 &value) const; diff --git a/includes/RT/objects/Sphere.hpp b/includes/RT/objects/Sphere.hpp index f48e8ff..b248392 100644 --- a/includes/RT/objects/Sphere.hpp +++ b/includes/RT/objects/Sphere.hpp @@ -18,13 +18,14 @@ class Sphere : public Object { public: - float radius; - glm::vec3 position; + Sphere(const glm::vec3& position, float radius, const Material& material) + : Object(position, material), _radius(radius) {} + + float getRadius() const { return (_radius); } + Type getType() const override { return Type::SPHERE; } - private: - - + float _radius; }; #endif \ No newline at end of file diff --git a/shaders/compute.glsl b/shaders/compute.glsl index b624d33..8eaa67c 100644 --- a/shaders/compute.glsl +++ b/shaders/compute.glsl @@ -6,14 +6,30 @@ layout(local_size_x = 16, local_size_y = 16) in; // Output image layout(binding = 0, rgba32f) uniform image2D outputImage; -// Uniforms for camera and scene -uniform vec2 u_resolution; -uniform vec3 u_cameraPosition; -uniform mat4 u_viewMatrix; +struct GPUObject { + vec3 position; // 12 + 4 + float padding_1; // 4 + vec3 color; // 12 + 4 + float padding_2; // 4 + float roughness; // 4 + float specular; // 4 + float radius; // 4 + int type; // 4 +}; + +layout(std430, binding = 1) buffer ObjectBuffer +{ + GPUObject objects[]; +}; + +uniform int u_objectsNum; +uniform vec2 u_resolution; +uniform vec3 u_cameraPosition; +uniform mat4 u_viewMatrix; + vec3 lightPos = vec3(5.0, 5.0, 5.0); vec3 lightColor = vec3(1.0, 1.0, 1.0); -// Scene definition vec3 sphereCenter = vec3(0.0, 0.0, -5.0); float sphereRadius = 1.0; vec3 objectColor = vec3(0.4, 0.7, 0.9); @@ -23,7 +39,8 @@ struct Ray { vec3 direction; }; -bool intersectSphere(Ray ray, vec3 center, float radius, out float t) { +bool intersectSphere(Ray ray, vec3 center, float radius, out float t) +{ vec3 oc = ray.origin - center; float a = dot(ray.direction, ray.direction); float b = 2.0 * dot(oc, ray.direction); @@ -32,10 +49,13 @@ bool intersectSphere(Ray ray, vec3 center, float radius, out float t) { if (discriminant < 0.0) { return false; - } else { - t = (-b - sqrt(discriminant)) / (2.0 * a); + } + float t1 = (-b - sqrt(discriminant)) / (2.0 * a); + if (t1 > 0.001) { + t = t1; return true; } + return false; } vec3 computeLighting(vec3 point, vec3 normal, vec3 viewDir) { @@ -46,7 +66,6 @@ vec3 computeLighting(vec3 point, vec3 normal, vec3 viewDir) { } void main() { - // Compute pixel coordinates ivec2 pixelCoords = ivec2(gl_GlobalInvocationID.xy); if (pixelCoords.x >= int(u_resolution.x) || pixelCoords.y >= int(u_resolution.y)) { return; @@ -64,14 +83,24 @@ void main() { rayDirection = normalize(rayDirection); Ray ray = Ray(u_cameraPosition, rayDirection); - float t; + vec4 color = vec4(0.0, 0.0, 0.0, 1.0); - if (intersectSphere(ray, sphereCenter, sphereRadius, t)) { - vec3 hitPoint = ray.origin + t * ray.direction; - vec3 normal = normalize(hitPoint - sphereCenter); - vec3 viewDir = normalize(-ray.direction); - vec3 lighting = computeLighting(hitPoint, normal, viewDir); - color = vec4(lighting, 1.0); + float closest_t = 1e30; + for (int i = 0; i < u_objectsNum; i++) + { + float t; + if (intersectSphere(ray, objects[i].position, objects[i].radius, t)) + { + if (t < closest_t) + { + closest_t = t; + + vec3 hitPoint = ray.origin + t * ray.direction; + vec3 normal = normalize(hitPoint - objects[i].position); + + color = vec4(objects[i].color * normal.y, 1.0); + } + } } // Write to the output image diff --git a/srcs/RT.cpp b/srcs/RT.cpp index c49ed7a..4d65757 100644 --- a/srcs/RT.cpp +++ b/srcs/RT.cpp @@ -12,21 +12,33 @@ #include "RT.hpp" - - int main(void) { - Window window(WIDTH, HEIGHT, "RT_GPU", 0); + Window window(WIDTH, HEIGHT, "RT_GPU", 1); Shader shader("shaders/vertex.vert", "shaders/frag.frag", "shaders/compute.glsl"); - Vertex vertices[3] = { - {{-1.0f, -1.0f}, {0.0f, 0.0f}}, - {{3.0f, -1.0f}, {2.0f, 0.0f}}, - {{-1.0f, 3.0f}, {0.0f, 2.0f}} - }; + Material redMaterial = {glm::vec3(1.0f, 0.2f, 0.2f), 1.0, 1.0}; + float radius = 30.0f; + for (int i = 0; i < 150; i++) { + float angle = (2.0f * M_PI * i) / 150.0f; + + float x = radius * cos(angle); + float z = radius * sin(angle); + + float y = 2.0f * sin(angle * 3.0f); + + glm::vec3 position(x, y, z); + float sphereSize = 0.8f + 0.4f * sin(angle * 2.0f); + + window.getScene()->addObject(std::make_unique(position, sphereSize, redMaterial)); + } + + GLuint objectSSBO; + glGenBuffers(1, &objectSSBO); shader.attach(); + Vertex vertices[3] = {{{-1.0f, -1.0f}, {0.0f, 0.0f}},{{3.0f, -1.0f}, {2.0f, 0.0f}},{{-1.0f, 3.0f}, {0.0f, 2.0f}}}; size_t size = sizeof(vertices) / sizeof(Vertex) / 3; shader.setupVertexBuffer(vertices, size); @@ -35,6 +47,14 @@ int main(void) { glUseProgram(shader.getProgramCompute()); + const std::vector &gpu_data = window.getScene()->getGPUData(); + + // Update SSBO with latest object data + glBindBuffer(GL_SHADER_STORAGE_BUFFER, objectSSBO); + glBufferData(GL_SHADER_STORAGE_BUFFER, gpu_data.size() * sizeof(GPUObject), gpu_data.data(), GL_DYNAMIC_DRAW); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, objectSSBO); + + shader.set_int("u_objectsNum", gpu_data.size()); shader.set_vec2("u_resolution", glm::vec2(WIDTH, HEIGHT)); shader.set_vec3("u_cameraPosition", window.getScene()->getCamera()->get_position()); shader.set_mat4("u_viewMatrix", window.getScene()->getCamera()->get_view_matrix()); diff --git a/srcs/class/Object.cpp b/srcs/class/Object.cpp deleted file mode 100644 index f75f2d2..0000000 --- a/srcs/class/Object.cpp +++ /dev/null @@ -1,12 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* Object.cpp :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: ycontre +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2024/12/23 18:44:00 by ycontre #+# #+# */ -/* Updated: 2024/12/23 18:44:01 by ycontre ### ########.fr */ -/* */ -/* ************************************************************************** */ - diff --git a/srcs/class/Scene.cpp b/srcs/class/Scene.cpp index fd632ff..0a0a2b4 100644 --- a/srcs/class/Scene.cpp +++ b/srcs/class/Scene.cpp @@ -19,10 +19,43 @@ Scene::Scene() Scene::~Scene() { - delete _camera; + delete (_camera); } Camera *Scene::getCamera(void) const { return (_camera); +} + +void Scene::addObject(std::unique_ptr object) +{ + _objects.push_back(std::move(object)); + + this->updateGPUData(); +} + +void Scene::updateGPUData() +{ + _gpuObjects.clear(); + for (const auto& obj : _objects) + { + GPUObject gpuObj; + gpuObj.position = obj->getPosition(); + gpuObj.color = obj->getMaterial().color; + gpuObj.roughness = obj->getMaterial().roughness; + gpuObj.specular = obj->getMaterial().specular; + gpuObj.type = static_cast(obj->getType()); + + if (obj->getType() == Object::Type::SPHERE) { + auto sphere = static_cast(obj.get()); + gpuObj.radius = sphere->getRadius(); + } + + _gpuObjects.push_back(gpuObj); + } +} + +const std::vector& Scene::getGPUData() const +{ + return (_gpuObjects); } \ No newline at end of file diff --git a/srcs/class/Shader.cpp b/srcs/class/Shader.cpp index e0074fe..f883950 100644 --- a/srcs/class/Shader.cpp +++ b/srcs/class/Shader.cpp @@ -142,17 +142,18 @@ void Shader::drawTriangles(size_t size) glDrawArrays(GL_TRIANGLES, 0, size * 3); } - +void Shader::set_int(const std::string &name, int value) const +{ + glUniform1i(glGetUniformLocation(_program_compute, name.c_str()), value); +} void Shader::set_vec2(const std::string &name, const glm::vec2 &value) const { glUniform2fv(glGetUniformLocation(_program_compute, name.c_str()), 1, glm::value_ptr(value)); } - void Shader::set_vec3(const std::string &name, const glm::vec3 &value) const { glUniform3fv(glGetUniformLocation(_program_compute, name.c_str()), 1, glm::value_ptr(value)); } - void Shader::set_mat4(const std::string &name, const glm::mat4 &value) const { glUniformMatrix4fv(glGetUniformLocation(_program_compute, name.c_str()), 1, GL_FALSE, glm::value_ptr(value));