diff --git a/includes/RT.hpp b/includes/RT.hpp index 0383535..9bca437 100644 --- a/includes/RT.hpp +++ b/includes/RT.hpp @@ -41,6 +41,7 @@ struct Vertex { # include "objects/Quad.hpp" # include "objects/Triangle.hpp" # include "objects/Cube.hpp" +# include "objects/Portal.hpp" # include "Camera.hpp" # include "Window.hpp" diff --git a/includes/RT/Object.hpp b/includes/RT/Object.hpp index d10172c..29f9b3d 100644 --- a/includes/RT/Object.hpp +++ b/includes/RT/Object.hpp @@ -42,7 +42,8 @@ class Object PLANE, QUAD, TRIANGLE, - CUBE + CUBE, + PORTAL }; virtual Type getType() const = 0; diff --git a/includes/RT/objects/Portal.hpp b/includes/RT/objects/Portal.hpp new file mode 100644 index 0000000..1354c13 --- /dev/null +++ b/includes/RT/objects/Portal.hpp @@ -0,0 +1,70 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* Portal.hpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ycontre +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/12/23 19:12:51 by ycontre #+# #+# */ +/* Updated: 2024/12/23 19:47:09 by ycontre ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef RT_PORTAL__HPP +# define RT_PORTAL__HPP + +# include "RT.hpp" + +class Portal : public Object +{ + public: + Portal(std::stringstream &line) : Object(glm::vec3(0.0f), -1) + { + try { + float x, y, z; + float x1, y1, z1; + float x2, y2, z2; + int linked_portal; + int mat_index; + + if (!(line >> x >> y >> z)) + throw std::runtime_error("Missing position"); + + if (!(line >> x1 >> y1 >> z1)) + throw std::runtime_error("Missing Portal's first edge "); + + if (!(line >> x2 >> y2 >> z2)) + throw std::runtime_error("Missing Portal's second edge"); + + if (!(line >> linked_portal)) + throw std::runtime_error("Missing Portal's linked index"); + + if (!(line >> mat_index)) + throw std::runtime_error("Missing material properties"); + + _position = glm::vec3(x, y, z); + _edge1 = glm::vec3(x1, y1, z1); + _edge2 = glm::vec3(x2, y2, z2); + + _linked_portal = linked_portal; + + _mat_index = mat_index; + } + catch (const std::exception &e) { throw; } + } + Portal(const glm::vec3 &position, const glm::vec3 &edge1, const glm::vec3 &edge2, const int linked_portal, const int mat_index) + : Object(position, mat_index), _edge1(edge1), _edge2(edge2), _linked_portal(linked_portal) {} + + glm::vec3 getEdge1() const { return (_edge1); } + glm::vec3 getEdge2() const { return (_edge2); } + int getLinkedPortalIndex() const { return (_linked_portal); } + Type getType() const override { return Type::PORTAL; } + + private: + glm::vec3 _edge1; + glm::vec3 _edge2; + + int _linked_portal; +}; + +#endif \ No newline at end of file diff --git a/scenes/colored_light.rt b/scenes/colored_light.rt index 3d4e45b..64558a2 100644 --- a/scenes/colored_light.rt +++ b/scenes/colored_light.rt @@ -4,7 +4,7 @@ MAT 255 010 010 5 0.0 1.0 MAT 010 255 010 5 0.0 1.0 MAT 010 010 255 5 0.0 1.0 -MAT 255 255 255 0 1.7 1.0 1 +MAT 255 255 255 0 1.7 1.0 DIE MAT 255 255 255 0 0.0 1.0 diff --git a/scenes/stairs.rt b/scenes/stairs.rt index 12e9f94..0379514 100644 --- a/scenes/stairs.rt +++ b/scenes/stairs.rt @@ -1,6 +1,6 @@ CAM -7 10 6 -MAT 255 255 255 4.0 0.0 0.0 //white light +MAT 255 255 255 2.0 0.0 0.0 //white light sp -10 100 10 50 0 qu -2.5 15 -9 7 0 0 0 0 7 0 @@ -66,7 +66,7 @@ MAT 244 95 28 0.0 0.5 1.0 cu -9 1.23 -6 3 3 3 29 MAT 200 20 20 0.0 1.0 0.05 -MAT 255 255 255 0.0 1.8 0.0 1 +MAT 255 255 255 0.0 1.8 0.0 DIE MAT 255 255 255 0.0 1.0 1.0 sp 0 5 -4 3 30 diff --git a/scenes/test.rt b/scenes/test.rt index b4545f2..66441c2 100644 --- a/scenes/test.rt +++ b/scenes/test.rt @@ -6,14 +6,13 @@ MAT 255 255 255 0.0 1.0 1.0 //mirror MAT 255 255 255 2.0 0.0 0.0 //sun MAT 255 100 100 0.0 0.0 0.0 //red +MAT 100 100 255 0.0 0.0 0.0 //blue pl 0 0 0 0 1 0 0 -# cu 0 0.5 1 1 1 1 3 +cu 1 0.5 3 1 1 1 3 +cu 1 0.5 -3 1 1 1 4 -# tr -5 0 2 -5 2 2 0 2 2 2 -# tr -5 0 2 0 0 2 0 2 2 2 +po 3 0 0 2 0 0 0 2 0 4 0 +po -3 0 0 2 0 0 0 2 0 3 0 -qu -5 0 0 2 0 0 0 2 0 2 //light problem -# qu -4 0 0 0 0 2 0 2 0 0 //blocking - -# sp 0 30 0 30 2 \ No newline at end of file +sp 0 30 0 30 2 \ No newline at end of file diff --git a/shaders/compute.glsl b/shaders/compute.glsl index ba2dc56..79806b3 100644 --- a/shaders/compute.glsl +++ b/shaders/compute.glsl @@ -11,7 +11,7 @@ struct GPUObject { vec3 vertex1; // 12 + 4 vec3 vertex2; // 12 + 4 - + float radius; // 4 int mat_index; // 4 @@ -62,26 +62,54 @@ struct hitInfo #include "shaders/intersect.glsl" #include "shaders/scatter.glsl" +Ray portalRay(Ray ray, hitInfo hit) +{ + GPUObject portal_1; + GPUObject portal_2; + vec3 relative; + + portal_1 = objects[hit.obj_index]; + portal_2 = objects[int(portal_1.radius)]; // saving memory radius = portal_index + + vec3 portal_2_normal = normalize(cross(portal_2.vertex1, portal_2.vertex2)); + portal_2_normal *= sign(dot(ray.direction, portal_2_normal)); + + relative = portal_2.position - portal_1.position; + + ray.origin = hit.position + relative + portal_2_normal * 0.01; + ray.direction = normalize(ray.direction + portal_2_normal * 0.01); + + return (ray); +} + hitInfo traceRay(Ray ray) { hitInfo hit; - hit.t = 1e30; - hit.obj_index = -1; - for (int i = 0; i < u_objectsNum; i++) + for (int p = 0; p < 2; p++) //portals { - GPUObject obj = objects[i]; - - hitInfo temp_hit; - if (intersect(ray, obj, temp_hit) && temp_hit.t > 0.0f && temp_hit.t < hit.t) + hit.t = 1e30; + hit.obj_index = -1; + + for (int i = 0; i < u_objectsNum; i++) { - hit.t = temp_hit.t; - hit.obj_index = i; - hit.position = temp_hit.position; - hit.normal = temp_hit.normal; + GPUObject obj = objects[i]; + + hitInfo temp_hit; + if (intersect(ray, obj, temp_hit) && temp_hit.t > 0.0f && temp_hit.t < hit.t) + { + hit.t = temp_hit.t; + hit.obj_index = i; + hit.position = temp_hit.position; + hit.normal = temp_hit.normal; + } } + if (hit.obj_index == -1 || objects[hit.obj_index].type != 5) + break ; + ray = portalRay(ray, hit); } + return (hit); } @@ -105,10 +133,10 @@ vec3 pathtrace(Ray ray, inout uint rng_state) GPUMaterial mat = materials[obj.mat_index]; // RR - // float p = max(color.r, max(color.g, color.b)); - // if (randomValue(rng_state) > p && i > 1) - // break; - // color /= p; + float p = max(color.r, max(color.g, color.b)); + if (randomValue(rng_state) > p && i > 1) + break; + color /= p; // color *= mat.color; diff --git a/shaders/intersect.glsl b/shaders/intersect.glsl index 1f219f4..8ab324c 100644 --- a/shaders/intersect.glsl +++ b/shaders/intersect.glsl @@ -153,7 +153,7 @@ bool intersect(Ray ray, GPUObject obj, out hitInfo hit) return (intersectSphere(ray, obj, hit)); if (obj.type == 1) return (intersectPlane(ray, obj, hit)); - if (obj.type == 2) + if (obj.type == 2 || obj.type == 5) return (intersectQuad(ray, obj, hit)); if (obj.type == 3) return (intersectTriangle(ray, obj, hit)); diff --git a/shaders/random.glsl b/shaders/random.glsl index fd8556a..bc420a5 100644 --- a/shaders/random.glsl +++ b/shaders/random.glsl @@ -1,3 +1,5 @@ +#define M_PI 3.14159265359 + float randomValue(inout uint rng_state) { rng_state = rng_state * 747796405u + 2891336453u; @@ -8,7 +10,7 @@ float randomValue(inout uint rng_state) float randomValueNormalDistribution(inout uint rng_state) { - float theta = 2.0 * 3.14159265359 * randomValue(rng_state); + float theta = 2.0 * M_PI * randomValue(rng_state); float rho = sqrt(-2.0 * log(randomValue(rng_state))); return (rho * cos(theta)); } @@ -27,7 +29,6 @@ vec3 randomHemisphereDirection(vec3 normal, inout uint rng_state) return (direction * sign(dot(normal, direction))); } -#define M_PI 3.1415926535897932384626433832795 // vec3 randomHemisphereDirection(vec3 normal, inout uint rng_state) // { diff --git a/srcs/class/Scene.cpp b/srcs/class/Scene.cpp index 0a5452d..569e15b 100644 --- a/srcs/class/Scene.cpp +++ b/srcs/class/Scene.cpp @@ -106,6 +106,13 @@ void Scene::updateGPUData() gpu_obj.vertex1 = cube->getSize(); gpu_obj.type = static_cast(cube->getType()); } + else if (obj->getType() == Object::Type::PORTAL) + { + auto portal = static_cast(obj); + gpu_obj.vertex1 = portal->getEdge1(); + gpu_obj.vertex2 = portal->getEdge2(); + gpu_obj.radius = portal->getLinkedPortalIndex(); + } _gpu_objects.push_back(gpu_obj); } diff --git a/srcs/class/SceneParser.cpp b/srcs/class/SceneParser.cpp index ba432a6..8bd11a2 100644 --- a/srcs/class/SceneParser.cpp +++ b/srcs/class/SceneParser.cpp @@ -43,6 +43,12 @@ SceneParser::SceneParser(Scene *scene) : _scene(scene) try { return (new Cube(ss)); } catch (const std::exception &e) { throw; } }; + + object_parsers["po"] = [](std::stringstream &ss) -> Object * + { + try { return (new Portal(ss)); } + catch (const std::exception &e) { throw; } + }; } void SceneParser::parseMaterial(std::stringstream &line) @@ -51,7 +57,7 @@ void SceneParser::parseMaterial(std::stringstream &line) float emission; float roughness; float metallic; - int type; + std::string type; Material *mat; @@ -59,15 +65,20 @@ void SceneParser::parseMaterial(std::stringstream &line) throw std::runtime_error("Material: Missing material properties"); if (!(line >> type)) - type = 0; - + type = "LAM"; + mat = new Material; mat->color = glm::vec3(r / 255.0f, g / 255.0f, b / 255.0f); mat->emission = emission; mat->roughness = roughness; mat->metallic = metallic; - mat->type = type; + + mat->type = 0; + if (type == "LAM") + mat->type = 0; + else if (type == "DIE") + mat->type = 1; _scene->addMaterial(mat); }