From ea3dd738f811c6a0f0495f7b57dcf7673359affb Mon Sep 17 00:00:00 2001 From: TheRedShip Date: Fri, 27 Dec 2024 11:11:01 +0100 Subject: [PATCH] + | Real material shared system + parsing --- includes/RT/Object.hpp | 7 +++--- includes/RT/Scene.hpp | 12 ++++++---- includes/RT/SceneParser.hpp | 9 ++++--- includes/RT/objects/Sphere.hpp | 42 ++++++++------------------------- scenes/test.rt | 7 +++++- shaders/compute.glsl | 5 ++-- srcs/RT.cpp | 6 ++--- srcs/class/Scene.cpp | 37 +++++++++++++++++++++++------ srcs/class/SceneParser.cpp | 43 ++++++++++++++++++++++++++++------ 9 files changed, 105 insertions(+), 63 deletions(-) diff --git a/includes/RT/Object.hpp b/includes/RT/Object.hpp index 4a734f9..07f7e75 100644 --- a/includes/RT/Object.hpp +++ b/includes/RT/Object.hpp @@ -18,6 +18,7 @@ typedef struct s_Material { glm::vec3 color; + float emission; float roughness; float specular; } Material; @@ -26,14 +27,14 @@ class Object { protected: glm::vec3 _position; - const Material *_material; + int _mat_index; public: - Object(const glm::vec3& position, const Material *material) : _position(position), _material(material) {} + Object(const glm::vec3& position, const int mat_index) : _position(position), _mat_index(mat_index) {} virtual ~Object() = default; + int getMaterialIndex() const {return (_mat_index); } const glm::vec3 &getPosition() const { return (_position); } - const Material *getMaterial() const { return (_material); } enum class Type { SPHERE, diff --git a/includes/RT/Scene.hpp b/includes/RT/Scene.hpp index a88f77a..b86ccc5 100644 --- a/includes/RT/Scene.hpp +++ b/includes/RT/Scene.hpp @@ -17,10 +17,9 @@ struct GPUObject { - glm::vec3 position; - int padding_1; - glm::vec3 color; - int padding_2; + alignas(16) glm::vec3 position; + alignas(16) glm::vec3 color; + float emission; float roughness; float specular; float radius; @@ -39,16 +38,21 @@ class Scene bool parseScene(char *name); void addObject(Object *object); + void addMaterial(Material *material); void updateGPUData(); const std::vector &getGPUData() const; Camera *getCamera(void) const; + + Material *getMaterial(int material_index); private: std::vector _objects; std::vector _gpu_objects; + std::vector _materials; + Camera *_camera; }; diff --git a/includes/RT/SceneParser.hpp b/includes/RT/SceneParser.hpp index 2e3eded..792c698 100644 --- a/includes/RT/SceneParser.hpp +++ b/includes/RT/SceneParser.hpp @@ -10,8 +10,8 @@ /* */ /* ************************************************************************** */ -#ifndef RT_SceneParser__HPP -# define RT_SceneParser__HPP +#ifndef RT_SCENEPARSER__HPP +# define RT_SCENEPARSER__HPP # include "RT.hpp" @@ -23,7 +23,10 @@ class SceneParser bool parseLine(const std::string &line); private: - Scene *_scene; + void parseMaterial(std::stringstream &line); + + + Scene *_scene; std::map> object_parsers; }; diff --git a/includes/RT/objects/Sphere.hpp b/includes/RT/objects/Sphere.hpp index b4f2fcb..d9f77b8 100644 --- a/includes/RT/objects/Sphere.hpp +++ b/includes/RT/objects/Sphere.hpp @@ -17,58 +17,36 @@ class Sphere : public Object { - public: - struct ParseError : public std::runtime_error + Sphere(std::stringstream &line) : Object(glm::vec3(0.0f), -1) { - ParseError(const std::string& msg) : std::runtime_error("Sphere parse error: " + msg) {} - }; - - Sphere(std::stringstream &line) : Object(glm::vec3(0.0f), nullptr) - { - _mat = new Material; - try { - float x, y, z, radius; - float r, g, b, rough, spec; + float x, y, z, radius; + int mat_index; if (!(line >> x >> y >> z >> radius)) - throw std::invalid_argument("Missing position or radius values"); + throw std::runtime_error("Missing position or radius values"); if (radius <= 0.0f) - throw std::invalid_argument("Radius must be positive"); + throw std::runtime_error("Radius must be positive"); - if (!(line >> r >> g >> b >> rough >> spec)) - throw std::invalid_argument("Missing material properties"); - - if (r < 0.0f || r > 255.0f || g < 0.0f || g > 255.0f || b < 0.0f || b > 255.0f) - throw std::invalid_argument("Color values must be between 0 and 255"); - - if (rough < 0.0f || rough > 1.0f) - throw std::invalid_argument("Roughness must be between 0 and 1"); - - if (spec < 0.0f || spec > 1.0f) - throw std::invalid_argument("Specular must be between 0 and 1"); + if (!(line >> mat_index)) + throw std::runtime_error("Missing material properties"); _position = glm::vec3(x, y, z); _radius = radius; - _mat->color = glm::vec3(r / 255.0f, g / 255.0f, b / 255.0f); - _mat->roughness = rough; - _mat->specular = spec; - - _material = _mat; + _mat_index = mat_index; } catch (const std::exception& e) { throw; } } - Sphere(const glm::vec3& position, float radius, const Material *material) - : Object(position, material), _radius(radius) {} + Sphere(const glm::vec3& position, float radius, const int mat_index) + : Object(position, mat_index), _radius(radius) {} float getRadius() const { return (_radius); } Type getType() const override { return Type::SPHERE; } private: - Material *_mat; float _radius; }; diff --git a/scenes/test.rt b/scenes/test.rt index cfd25b8..7d79136 100644 --- a/scenes/test.rt +++ b/scenes/test.rt @@ -1,4 +1,9 @@ -sp 0 -1 -6 2.0 255 255 255 0.0 0.0 +MAT 255 255 255 0.0 1.0 2.0 +MAT 255 0 0 0.0 1.0 2.0 + +sp 0 -1 -6 1.0 0 +sp 2 -1 -6 1.0 1 +sp -2 -1 -6 1.0 1 R 1.0 -2.0 10 diff --git a/shaders/compute.glsl b/shaders/compute.glsl index 8eaa67c..c42ecdb 100644 --- a/shaders/compute.glsl +++ b/shaders/compute.glsl @@ -8,13 +8,12 @@ layout(binding = 0, rgba32f) uniform image2D outputImage; struct GPUObject { vec3 position; // 12 + 4 - float padding_1; // 4 vec3 color; // 12 + 4 - float padding_2; // 4 + float emission; // 4 float roughness; // 4 float specular; // 4 float radius; // 4 - int type; // 4 + int type; // 4 + 12 }; layout(std430, binding = 1) buffer ObjectBuffer diff --git a/srcs/RT.cpp b/srcs/RT.cpp index 51eba2a..7b8d542 100644 --- a/srcs/RT.cpp +++ b/srcs/RT.cpp @@ -22,8 +22,8 @@ int main(int argc, char **argv) Window window(&scene, WIDTH, HEIGHT, "RT_GPU", 1); Shader shader("shaders/vertex.vert", "shaders/frag.frag", "shaders/compute.glsl"); - - // Material redMaterial = {glm::vec3(1.0f, 0.2f, 0.2f), 1.0, 1.0}; + // Material redMaterial = {glm::vec3(1.0f, 0.2f, 0.2f), 1.0, 1.0, 0.0}; + // scene.addMaterial(&redMaterial); // for (int i = 0; i < 150; i++) // { @@ -33,7 +33,7 @@ int main(int argc, char **argv) // float y = 2.0f * sin(angle * 3.0f); // glm::vec3 position(x, y, z); // float sphereSize = 0.8f + 0.4f * sin(angle * 2.0f); - // scene.addObject(new Sphere(position, sphereSize, &redMaterial)); + // scene.addObject(new Sphere(position, sphereSize, 0)); // } GLuint objectSSBO; diff --git a/srcs/class/Scene.cpp b/srcs/class/Scene.cpp index b4a7610..bd003c6 100644 --- a/srcs/class/Scene.cpp +++ b/srcs/class/Scene.cpp @@ -56,17 +56,26 @@ void Scene::addObject(Object *object) this->updateGPUData(); } +void Scene::addMaterial(Material *material) +{ + _materials.push_back(material); +} + void Scene::updateGPUData() { + GPUObject gpu_obj; + Material *mat; _gpu_objects.clear(); for (const auto& obj : _objects) { - GPUObject gpu_obj; + mat = getMaterial(obj->getMaterialIndex()); + gpu_obj.position = obj->getPosition(); - gpu_obj.color = obj->getMaterial()->color; - gpu_obj.roughness = obj->getMaterial()->roughness; - gpu_obj.specular = obj->getMaterial()->specular; + gpu_obj.color = mat->color; + gpu_obj.emission = mat->emission; + gpu_obj.roughness = mat->roughness; + gpu_obj.specular = mat->specular; gpu_obj.type = static_cast(obj->getType()); if (obj->getType() == Object::Type::SPHERE) @@ -74,19 +83,33 @@ void Scene::updateGPUData() auto sphere = static_cast(obj); gpu_obj.radius = sphere->getRadius(); } - - std::cout << gpu_obj.position.x << " " << gpu_obj.position.y << " " << gpu_obj.position.z << " " << gpu_obj.radius << " " << gpu_obj.roughness << " " << gpu_obj.specular << std::endl; - + _gpu_objects.push_back(gpu_obj); } } const std::vector& Scene::getGPUData() const { + for (const auto& obj : _gpu_objects) + { + std::cout << "objType: " << obj.type << std::endl; + std::cout << "position: " << obj.position.x << " " << obj.position.y << " " << obj.position.z << std::endl; + std::cout << "color: " << obj.color.x << " " << obj.color.y << " " << obj.color.z << std::endl; + std::cout << "mat: " << obj.emission << " " << obj.roughness << " " << obj.specular << std::endl; + std::cout << "Size of GPUObject: " << sizeof(GPUObject) << " bytes" << std::endl; + } + return (_gpu_objects); } Camera *Scene::getCamera(void) const { return (_camera); +} + +Material *Scene::getMaterial(int material_index) +{ + if (material_index < 0 || material_index >= (int)_materials.size()) + throw std::runtime_error("Incorrect material index"); + return (_materials[material_index]); } \ No newline at end of file diff --git a/srcs/class/SceneParser.cpp b/srcs/class/SceneParser.cpp index fe047a0..3217fb7 100644 --- a/srcs/class/SceneParser.cpp +++ b/srcs/class/SceneParser.cpp @@ -21,6 +21,27 @@ SceneParser::SceneParser(Scene *scene) : _scene(scene) }; } +void SceneParser::parseMaterial(std::stringstream &line) +{ + float r,g,b; + float emission; + float roughness; + float specular; + Material *mat; + + if (!(line >> r >> g >> b >> emission >> roughness >> specular)) + throw std::runtime_error("Material: Missing material properties"); + + mat = new Material; + + mat->color = glm::vec3(r / 255.0f, g / 255.0f, b / 255.0f); + mat->emission = emission; + mat->roughness = roughness; + mat->specular = specular; + + _scene->addMaterial(mat); +} + bool SceneParser::parseLine(const std::string &line) { if (line.empty() || line[0] == '#') @@ -31,17 +52,25 @@ bool SceneParser::parseLine(const std::string &line) ss >> identifier; - auto it = object_parsers.find(identifier); - if (it != object_parsers.end()) + try { - try { + auto it = object_parsers.find(identifier); + if (it != object_parsers.end()) + { Object *obj = it->second(ss); + (void) _scene->getMaterial(obj->getMaterialIndex()); //verify material + _scene->addObject(obj); - } catch (const std::exception& e) { - std::cerr << "Error parsing sphere: " << e.what() << std::endl; - return false; } + + if (identifier == "MAT") + this->parseMaterial(ss); + } + catch (const std::exception& e) + { + std::cerr << e.what() << std::endl; + return (false); } return (true); -} \ No newline at end of file +}