From a890cca50ba69e8e619d1c4a30cea024466c26e6 Mon Sep 17 00:00:00 2001 From: TheRedShip Date: Tue, 4 Mar 2025 20:43:06 +0100 Subject: [PATCH 1/3] + | first fog laser bounce --- scenes/test.rt | 2 +- scenes/window2.rt | 3 ++- shaders/light.glsl | 42 +++++++++++++++++++++++++++++++++++++---- shaders/raytracing.glsl | 2 +- shaders/volumetric.glsl | 7 +++++-- 5 files changed, 47 insertions(+), 9 deletions(-) diff --git a/scenes/test.rt b/scenes/test.rt index 051f89b..e0be014 100644 --- a/scenes/test.rt +++ b/scenes/test.rt @@ -7,5 +7,5 @@ MAT 255 255 255 1.0 0.0 0.0 LAM 0 // 1 # sp 0 2 0 150 1 # pl 0 0 0 0 1 0 0 -OBJ obj/lambo2.obj 0 0 0 0.25 +OBJ obj/castle.obj 0 0 0 1 diff --git a/scenes/window2.rt b/scenes/window2.rt index 83ba873..0327005 100644 --- a/scenes/window2.rt +++ b/scenes/window2.rt @@ -5,7 +5,7 @@ MAT 150 150 150 0.0 1.0 0.0 //grey MAT 255 255 255 1.0 0.0 0.0 //light -sp -5 5 0 1 2 +sp -10 5 0 0.01 2 # qu -5 0 -2.5 0 5 0 0 0 5 0 2 @@ -17,6 +17,7 @@ qu -2.5 0 -2.5 0 5 0 5 0 0 0 0 qu -2.5 0 2.5 0 5 0 5 0 0 0 0 qu -2.5 5 -2.5 0 0 5 5 0 0 0 0 + qu -2.5 0 -2.5 0 2.5 0 0 0 5 0 0 qu -2.5 3.5 -2.5 0 1.5 0 0 0 5 0 0 diff --git a/shaders/light.glsl b/shaders/light.glsl index 2176895..ddc4c38 100644 --- a/shaders/light.glsl +++ b/shaders/light.glsl @@ -2,7 +2,7 @@ hitInfo traceRay(inout Ray ray); vec3 GetEnvironmentLight(Ray ray) { - // return vec3(0.); + return vec3(0.); vec3 sun_pos = vec3(-0.5, 0.5, 0.5); float SunFocus = 1.5; float SunIntensity = 1.; @@ -36,9 +36,37 @@ vec3 sampleSphereLight(vec3 position, GPUObject obj, int light_index, GPUMateria Ray shadow_ray = Ray(position + light_dir * 0.001, light_dir, (1.0 / light_dir)); hitInfo shadow_hit = traceRay(shadow_ray); - - if (shadow_hit.obj_index != light_index) - return vec3(0.0); + + vec3 dir = normalize(vec3(-0.5, 0.2, 0.)); + if (dot(shadow_ray.direction, dir) < 0.995 || shadow_hit.obj_index != light_index) + { + theta = 2.0 * M_PI * randomValue(rng_state); + phi = acos(2.0 * randomValue(rng_state) - 1.0); + + sample_point = obj.position + tan(acos(0.995)) * light_dist * vec3( + sin(phi) * cos(theta), + sin(phi) * sin(theta), + cos(phi) + ); + + Ray light_ray = Ray(sample_point, -dir, (1.0 / -dir)); + hitInfo light_ray_hit = traceRay(light_ray); + + if (light_ray_hit.obj_index == -1) + return (vec3(0.0)); + + GPUMaterial light_ray_mat = materials[light_ray_hit.mat_index]; + if (light_ray_mat.metallic == 0.) + return vec3(0.0); + + Ray reflect_ray = newRay(light_ray_hit, light_ray, rng_state); + reflect_ray.inv_direction = 1.0 / reflect_ray.direction; + + vec3 reflect_to_particle = normalize(position - reflect_ray.origin); + + if (dot(reflect_ray.direction, reflect_to_particle) < 0.995) + return vec3(0.0); + } float cos_theta = max(0.0, -dot(light_dir, normalize(sample_point - obj.position))); return mat.emission * mat.color / (light_dist * light_dist) * cos_theta / (4.0 * M_PI * (obj.radius / 2.0) * (obj.radius / 2.0)); @@ -59,6 +87,10 @@ vec3 sampleQuadLight(vec3 position, GPUObject obj, int light_index, GPUMaterial if (shadow_hit.obj_index != light_index) return vec3(0.0); + vec3 dir = normalize(vec3(-0.5, 0., 0.)); + if (dot(shadow_ray.direction, dir) < 0.995) + return vec3(0.); + vec3 crossQuad = cross(obj.vertex1, obj.vertex2); float area = length(crossQuad); float pdf = 1.0 / area; @@ -143,8 +175,10 @@ void calculateLightColor(GPUMaterial mat, hitInfo hit, inout vec3 color, inou else { vec3 mat_color = (mat.type == 3) ? getCheckerboardColor(mat, hit) : mat.color; + color *= mat_color; light += mat.emission * mat_color; + // if (mat.emission == 0.0) // light += sampleLights(hit.position, rng_state); } diff --git a/shaders/raytracing.glsl b/shaders/raytracing.glsl index c5081af..53ae38c 100644 --- a/shaders/raytracing.glsl +++ b/shaders/raytracing.glsl @@ -216,7 +216,7 @@ vec3[2] pathtrace(Ray ray, inout uint rng_state) color /= max(p, 0.001); GPUMaterial mat = materials[hit.mat_index]; - calculateLightColor(mat, hit, color, light, rng_state, ray); + calculateLightColor(mat, hit, color, light, rng_state); if (mat.emission > 0.0 && mat.emission_texture_index == -1) break; diff --git a/shaders/volumetric.glsl b/shaders/volumetric.glsl index 95ca3c8..cb7111d 100644 --- a/shaders/volumetric.glsl +++ b/shaders/volumetric.glsl @@ -44,11 +44,14 @@ void calculateVolumetricLight(float t_scatter, inout Ray ray, inout vec3 color, transmittance *= exp(-volume.sigma_t * t_scatter); color *= volume.sigma_s / volume.sigma_t; - light += transmittance * color * sampleLights(scatter_pos, rng_state); - + vec3 direct_light = sampleLights(scatter_pos, rng_state); + float cos_theta = sampleHG(volume.g, rng_state); vec3 new_dir = sampleDirection(ray.direction, cos_theta, rng_state); ray.origin = scatter_pos; ray.direction = new_dir; + ray.inv_direction = 1.0 / new_dir; + + light += transmittance * color * direct_light; } From 680ff6eb032bca815a87c6651ae8758959541660 Mon Sep 17 00:00:00 2001 From: TheRedShip Date: Tue, 4 Mar 2025 21:15:04 +0100 Subject: [PATCH 2/3] + | Better bouncing --- scenes/window2.rt | 2 +- shaders/light.glsl | 31 +++++++++++++++++++++---------- srcs/class/Window.cpp | 2 -- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/scenes/window2.rt b/scenes/window2.rt index 0327005..4e52591 100644 --- a/scenes/window2.rt +++ b/scenes/window2.rt @@ -5,7 +5,7 @@ MAT 150 150 150 0.0 1.0 0.0 //grey MAT 255 255 255 1.0 0.0 0.0 //light -sp -10 5 0 0.01 2 +sp -10 7 0 0.1 2 # qu -5 0 -2.5 0 5 0 0 0 5 0 2 diff --git a/shaders/light.glsl b/shaders/light.glsl index ddc4c38..d094dff 100644 --- a/shaders/light.glsl +++ b/shaders/light.glsl @@ -2,7 +2,7 @@ hitInfo traceRay(inout Ray ray); vec3 GetEnvironmentLight(Ray ray) { - return vec3(0.); + // return vec3(0.); vec3 sun_pos = vec3(-0.5, 0.5, 0.5); float SunFocus = 1.5; float SunIntensity = 1.; @@ -37,17 +37,26 @@ vec3 sampleSphereLight(vec3 position, GPUObject obj, int light_index, GPUMateria Ray shadow_ray = Ray(position + light_dir * 0.001, light_dir, (1.0 / light_dir)); hitInfo shadow_hit = traceRay(shadow_ray); - vec3 dir = normalize(vec3(-0.5, 0.2, 0.)); + vec3 dir = normalize(vec3(-0.5, 0.15, 0.)); if (dot(shadow_ray.direction, dir) < 0.995 || shadow_hit.obj_index != light_index) { - theta = 2.0 * M_PI * randomValue(rng_state); - phi = acos(2.0 * randomValue(rng_state) - 1.0); - - sample_point = obj.position + tan(acos(0.995)) * light_dist * vec3( - sin(phi) * cos(theta), - sin(phi) * sin(theta), - cos(phi) - ); + float circleRadius = light_dist * tan(acos(0.995)); + + // Uniformly sample a point in a disk. + float r = circleRadius * sqrt(randomValue(rng_state)); + float theta = 2.0 * M_PI * randomValue(rng_state); + vec2 diskSample = vec2(r * cos(theta), r * sin(theta)); + + // Build an orthonormal basis for the plane perpendicular to 'dir'. + vec3 up = abs(dir.y) < 0.99 ? vec3(0, 1, 0) : vec3(1, 0, 0); + vec3 tangent = normalize(cross(up, dir)); + vec3 bitangent = cross(dir, tangent); + + // Determine the center of the projected circle on the wall. + vec3 circleCenter = obj.position + light_dist * dir; + + // Compute the final sample point on the projected circle. + vec3 sample_point = circleCenter + diskSample.x * tangent + diskSample.y * bitangent; Ray light_ray = Ray(sample_point, -dir, (1.0 / -dir)); hitInfo light_ray_hit = traceRay(light_ray); @@ -66,6 +75,8 @@ vec3 sampleSphereLight(vec3 position, GPUObject obj, int light_index, GPUMateria if (dot(reflect_ray.direction, reflect_to_particle) < 0.995) return vec3(0.0); + mat.color *= light_ray_mat.color; + return mat.emission * mat.color * vec3(10.0); } float cos_theta = max(0.0, -dot(light_dir, normalize(sample_point - obj.position))); diff --git a/srcs/class/Window.cpp b/srcs/class/Window.cpp index 7c0968d..c25adb6 100644 --- a/srcs/class/Window.cpp +++ b/srcs/class/Window.cpp @@ -318,7 +318,6 @@ void Window::imGuiRender(ShaderProgram &raytracing_program) has_changed |= ImGui::SliderInt("Triangle treshold", &_scene->getDebug().triangle_treshold, 1, 2000); } - _renderer->renderImgui(); ImGui::End(); @@ -326,7 +325,6 @@ void Window::imGuiRender(ShaderProgram &raytracing_program) ImGui::Render(); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); - if (has_changed) _frameCount = (accumulate == 0) - 1; } From 0a13d3acc508b7d565b68e7722d7ca188379ada7 Mon Sep 17 00:00:00 2001 From: TheRedShip Date: Sat, 8 Mar 2025 20:36:10 +0100 Subject: [PATCH 3/3] + | Fog beam laser now in objects --- includes/RT.hpp | 1 + includes/RT/Object.hpp | 4 +- includes/RT/Scene.hpp | 1 - includes/RT/objects/SpotLight.hpp | 68 +++++++++++++++++++++++ scenes/fog.rt | 24 +++++++++ scenes/window2.rt | 3 +- shaders/intersect.glsl | 2 +- shaders/light.glsl | 89 ++++++++++++++++++------------- srcs/class/Scene.cpp | 31 +++++------ srcs/class/SceneParser.cpp | 4 +- srcs/class/Window.cpp | 6 +-- 11 files changed, 168 insertions(+), 65 deletions(-) create mode 100644 includes/RT/objects/SpotLight.hpp create mode 100644 scenes/fog.rt diff --git a/includes/RT.hpp b/includes/RT.hpp index 87f7736..f8f023a 100644 --- a/includes/RT.hpp +++ b/includes/RT.hpp @@ -58,6 +58,7 @@ struct Vertex { # include "objects/Cube.hpp" # include "objects/Portal.hpp" # include "objects/Cylinder.hpp" +# include "objects/SpotLight.hpp" # include "Buffer.hpp" # include "Arguments.hpp" diff --git a/includes/RT/Object.hpp b/includes/RT/Object.hpp index 95cea16..b57dfaf 100644 --- a/includes/RT/Object.hpp +++ b/includes/RT/Object.hpp @@ -47,7 +47,9 @@ class Object TRIANGLE, CUBE, PORTAL, - CYLINDER + CYLINDER, + SPOTLIGHT, + LASERBEAM }; virtual Type getType() const = 0; diff --git a/includes/RT/Scene.hpp b/includes/RT/Scene.hpp index f208ee1..c75e8d4 100644 --- a/includes/RT/Scene.hpp +++ b/includes/RT/Scene.hpp @@ -127,7 +127,6 @@ class Scene bool loadTextures(); - void updateLightAndObjects(int mat_id); std::set getGPULights(); void addBvh(std::vector &triangles, glm::vec3 offset, float scale, glm::mat4 transform); diff --git a/includes/RT/objects/SpotLight.hpp b/includes/RT/objects/SpotLight.hpp new file mode 100644 index 0000000..2ba834f --- /dev/null +++ b/includes/RT/objects/SpotLight.hpp @@ -0,0 +1,68 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* SpotLight.hpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: TheRed +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/03/08 18:50:04 by TheRed #+# #+# */ +/* Updated: 2025/03/08 18:50:04 by TheRed ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef RT_SPOTLIGHT__HPP +# define RT_SPOTLIGHT__HPP + +# include "RT.hpp" + +class SpotLight : public Object +{ + public: + SpotLight(std::stringstream &line) : Object(glm::vec3(0.0f), -1) + { + float x, y, z, radius; + float dir_x, dir_y, dir_z; + float angle; + + int mat_index; + + if (!(line >> x >> y >> z >> radius)) + throw std::runtime_error("Missing position or radius values"); + + if (radius <= 0.0f) + throw std::runtime_error("Radius must be positive"); + + if (!(line >> dir_x >> dir_y >> dir_z)) + throw std::runtime_error("Missing direction values"); + + if (!(line >> angle)) + throw std::runtime_error("Missing angle value"); + + if (!(line >> mat_index)) + throw std::runtime_error("Missing material properties"); + + _position = glm::vec3(x, y, z); + _radius = radius / 2.0; + + _direction = glm::normalize(glm::vec3(dir_x, dir_y, dir_z)); + _angle = angle; + + _mat_index = mat_index; + } + SpotLight(const glm::vec3& position, float radius, const int mat_index) + : Object(position, mat_index), _radius(radius) {} + + float getRadius() const { return (_radius); } + float getAngle() const { return (_angle); } + const glm::vec3 &getDirection() const { return (_direction); } + + Type getType() const override { return Type::SPOTLIGHT; } + + private: + float _radius; + + glm::vec3 _direction; + float _angle; +}; + +#endif \ No newline at end of file diff --git a/scenes/fog.rt b/scenes/fog.rt new file mode 100644 index 0000000..d7e5b27 --- /dev/null +++ b/scenes/fog.rt @@ -0,0 +1,24 @@ +CAM 0. 2.5 10. 5 -90 1.0 14 90 5 + +MAT 150 150 150 0.0 1.0 0.0 // 0 grey +MAT 200 200 200 0.0 1.0 0.0 // 1 white +MAT 255 255 255 0.0 1.0 1.0 // 2 reflective white + +MAT 255 50 50 3.0 2.0 0.0 // 3 red light +MAT 50 255 50 3.0 2.0 0.0 // 4 green light +MAT 50 50 255 3.0 2.0 0.0 // 5 blue light +MAT 255 255 255 3.0 2.0 0.0 // 6 white light + +OBJ obj/Dragon_800K.obj 0 2.2 -2 30 0 0 0 1 +# sp 0 1 -6 2 1 + +sl -10 20 -6 0.25 -0.5 1 0 0.95 3 +sl 0 20 -6 0.25 0 1 0 0.95 4 +sl 10 20 -6 0.25 0.5 1 0 0.95 5 + +qu -5 0.5 2.5 0 1 0 1 0 0.5 0 6 +qu 5 0.5 2.5 0 1 0 -1 0 0.5 0 6 + +pl 0 0 0 0 1 0 0 + + diff --git a/scenes/window2.rt b/scenes/window2.rt index 4e52591..5248bd5 100644 --- a/scenes/window2.rt +++ b/scenes/window2.rt @@ -5,7 +5,8 @@ MAT 150 150 150 0.0 1.0 0.0 //grey MAT 255 255 255 1.0 0.0 0.0 //light -sp -10 7 0 0.1 2 +sp -20 7 0 5 2 +sl -2 6 0 0.25 -0.5 1 0 0.99 2 # qu -5 0 -2.5 0 5 0 0 0 5 0 2 diff --git a/shaders/intersect.glsl b/shaders/intersect.glsl index 23fe42a..9f85371 100644 --- a/shaders/intersect.glsl +++ b/shaders/intersect.glsl @@ -205,7 +205,7 @@ bool intersectCylinder(Ray ray, GPUObject obj, out hitInfo hit) bool intersect(Ray ray, GPUObject obj, out hitInfo hit) { - if (obj.type == 0) + if (obj.type == 0 || obj.type == 7) return (intersectSphere(ray, obj, hit)); if (obj.type == 1) return (intersectPlane(ray, obj, hit)); diff --git a/shaders/light.glsl b/shaders/light.glsl index d094dff..857f884 100644 --- a/shaders/light.glsl +++ b/shaders/light.glsl @@ -20,6 +20,8 @@ vec3 GetEnvironmentLight(Ray ray) return composite; } +#define FOG_BOUNCE 0 + vec3 sampleSphereLight(vec3 position, GPUObject obj, int light_index, GPUMaterial mat, inout uint rng_state) { float theta = 2.0 * M_PI * randomValue(rng_state); @@ -37,46 +39,48 @@ vec3 sampleSphereLight(vec3 position, GPUObject obj, int light_index, GPUMateria Ray shadow_ray = Ray(position + light_dir * 0.001, light_dir, (1.0 / light_dir)); hitInfo shadow_hit = traceRay(shadow_ray); - vec3 dir = normalize(vec3(-0.5, 0.15, 0.)); - if (dot(shadow_ray.direction, dir) < 0.995 || shadow_hit.obj_index != light_index) + float beam_cos_angle = obj.vertex1.x; + vec3 dir = obj.normal; + + if (shadow_hit.obj_index != light_index || dot(shadow_ray.direction, dir) < beam_cos_angle) { - float circleRadius = light_dist * tan(acos(0.995)); + #if FOG_BOUNCE + float circleRadius = light_dist * tan(acos(beam_cos_angle)); - // Uniformly sample a point in a disk. - float r = circleRadius * sqrt(randomValue(rng_state)); - float theta = 2.0 * M_PI * randomValue(rng_state); - vec2 diskSample = vec2(r * cos(theta), r * sin(theta)); + float r = circleRadius * sqrt(randomValue(rng_state)); + float theta = 2.0 * M_PI * randomValue(rng_state); + vec2 diskSample = vec2(r * cos(theta), r * sin(theta)); - // Build an orthonormal basis for the plane perpendicular to 'dir'. - vec3 up = abs(dir.y) < 0.99 ? vec3(0, 1, 0) : vec3(1, 0, 0); - vec3 tangent = normalize(cross(up, dir)); - vec3 bitangent = cross(dir, tangent); + vec3 up = abs(dir.y) < 0.99 ? vec3(0, 1, 0) : vec3(1, 0, 0); + vec3 tangent = normalize(cross(up, dir)); + vec3 bitangent = cross(dir, tangent); - // Determine the center of the projected circle on the wall. - vec3 circleCenter = obj.position + light_dist * dir; + vec3 circleCenter = obj.position + light_dist * dir; - // Compute the final sample point on the projected circle. - vec3 sample_point = circleCenter + diskSample.x * tangent + diskSample.y * bitangent; + vec3 sample_point = circleCenter + diskSample.x * tangent + diskSample.y * bitangent; - Ray light_ray = Ray(sample_point, -dir, (1.0 / -dir)); - hitInfo light_ray_hit = traceRay(light_ray); + Ray light_ray = Ray(sample_point, -dir, (1.0 / -dir)); + hitInfo light_ray_hit = traceRay(light_ray); - if (light_ray_hit.obj_index == -1) - return (vec3(0.0)); + if (light_ray_hit.obj_index == -1) + return (vec3(0.0)); - GPUMaterial light_ray_mat = materials[light_ray_hit.mat_index]; - if (light_ray_mat.metallic == 0.) - return vec3(0.0); + GPUMaterial light_ray_mat = materials[light_ray_hit.mat_index]; + if (light_ray_mat.metallic == 0.) + return vec3(0.0); - Ray reflect_ray = newRay(light_ray_hit, light_ray, rng_state); - reflect_ray.inv_direction = 1.0 / reflect_ray.direction; + Ray reflect_ray = newRay(light_ray_hit, light_ray, rng_state); + reflect_ray.inv_direction = 1.0 / reflect_ray.direction; - vec3 reflect_to_particle = normalize(position - reflect_ray.origin); - - if (dot(reflect_ray.direction, reflect_to_particle) < 0.995) - return vec3(0.0); - mat.color *= light_ray_mat.color; - return mat.emission * mat.color * vec3(10.0); + vec3 reflect_to_particle = normalize(position - reflect_ray.origin); + + if (dot(reflect_ray.direction, reflect_to_particle) < beam_cos_angle) + return vec3(0.0); + + mat.color *= light_ray_mat.color; + #else + return vec3(0.); + #endif } float cos_theta = max(0.0, -dot(light_dir, normalize(sample_point - obj.position))); @@ -98,16 +102,28 @@ vec3 sampleQuadLight(vec3 position, GPUObject obj, int light_index, GPUMaterial if (shadow_hit.obj_index != light_index) return vec3(0.0); - vec3 dir = normalize(vec3(-0.5, 0., 0.)); - if (dot(shadow_ray.direction, dir) < 0.995) - return vec3(0.); + vec3 quad_to_camera = position - obj.position; + float distance_plane = dot(quad_to_camera, obj.normal); + vec3 point_projected = position - distance_plane * obj.normal; + + mat2 A = mat2( + dot(obj.vertex1, obj.vertex1), dot(obj.vertex1, obj.vertex2), + dot(obj.vertex1, obj.vertex2), dot(obj.vertex2, obj.vertex2) + ); + vec2 b = vec2( + dot(point_projected - obj.position, obj.vertex1), + dot(point_projected - obj.position, obj.vertex2) + ); + vec2 alphaBeta = inverse(A) * b; + + if (alphaBeta.x < 0.0f || alphaBeta.x > 1.0f || alphaBeta.y < 0.0f || alphaBeta.y > 1.0f) + return vec3(0.0); vec3 crossQuad = cross(obj.vertex1, obj.vertex2); float area = length(crossQuad); float pdf = 1.0 / area; - vec3 normal = normalize(crossQuad); - float cos_theta = max(0.0, dot(normal, -light_dir)); + float cos_theta = max(0.0, dot(obj.normal, -light_dir)); return mat.emission * mat.color / (light_dist * light_dist) * pdf; } @@ -119,10 +135,11 @@ vec3 sampleLights(in vec3 position, inout uint rng_state) GPUObject light_obj = objects[light_index]; GPUMaterial lightMat = materials[light_obj.mat_index]; - if (light_obj.type == 0) + if (light_obj.type == 7) return float(u_lightsNum) * sampleSphereLight(position, light_obj, light_index, lightMat, rng_state); else if (light_obj.type == 2) return float(u_lightsNum) * sampleQuadLight(position, light_obj, light_index, lightMat, rng_state); + return (vec3(0.)); } vec2 getSphereUV(vec3 surfacePoint) diff --git a/srcs/class/Scene.cpp b/srcs/class/Scene.cpp index 6258d27..26a8c69 100644 --- a/srcs/class/Scene.cpp +++ b/srcs/class/Scene.cpp @@ -94,6 +94,9 @@ void Scene::addObject(Object *obj) gpu_obj.vertex2 = quad->getRight(); gpu_obj.normal = quad->getNormal(); gpu_obj.radius = quad->getSingleSided(); + + if (_gpu_materials[gpu_obj.mat_index].emission > 0.) + this->_gpu_lights.insert(_gpu_objects.size()); } else if (obj->getType() == Object::Type::CUBE) { @@ -115,6 +118,16 @@ void Scene::addObject(Object *obj) gpu_obj.vertex2 = triangle->getVertex3(); gpu_obj.normal = triangle->getNormal(); } + else if (obj->getType() == Object::Type::SPOTLIGHT) + { + auto spotlight = static_cast(obj); + + gpu_obj.radius = spotlight->getRadius(); + gpu_obj.normal = spotlight->getDirection(); + gpu_obj.vertex1 = glm::vec3(spotlight->getAngle(), 0.0f, 0.0f); + + this->_gpu_lights.insert(_gpu_objects.size()); + } else if (obj->getType() == Object::Type::PORTAL) { auto portal = static_cast(obj); @@ -293,25 +306,9 @@ bool Scene::loadTextures() return (true); } -void Scene::updateLightAndObjects(int mat_id) -{ - for (unsigned int i = 0; i < _gpu_objects.size(); i++) - { - if (_gpu_objects[i].mat_index == mat_id) - _gpu_lights.insert(i); - } - for (auto it = _gpu_lights.begin(); it != _gpu_lights.end(); ) - { - if (_gpu_materials[_gpu_objects[*it].mat_index].emission <= 0.0) - it = _gpu_lights.erase(it); - else - ++it; - } -} - bool Scene::fail(void) const { - return(_fail); + return (_fail); } std::set Scene::getGPULights() diff --git a/srcs/class/SceneParser.cpp b/srcs/class/SceneParser.cpp index adf5d59..aeab35d 100644 --- a/srcs/class/SceneParser.cpp +++ b/srcs/class/SceneParser.cpp @@ -21,6 +21,7 @@ SceneParser::SceneParser(Scene *scene, std::string filename) : _scene(scene), _f object_parsers["cu"] = [](std::stringstream &ss) -> Object * { return (new Cube(ss)); }; object_parsers["po"] = [](std::stringstream &ss) -> Object * { return (new Portal(ss)); }; object_parsers["cy"] = [](std::stringstream &ss) -> Object * { return (new Cylinder(ss)); }; + object_parsers["sl"] = [](std::stringstream &ss) -> Object * { return (new SpotLight(ss)); }; } void SceneParser::parseMaterial(std::stringstream &line) @@ -170,9 +171,6 @@ bool SceneParser::parseLine(const std::string &line) _scene->addObject(static_cast(obj)->createSupportQuad()); _scene->addObject(obj); - - if (mat.emission > 0.0) - _scene->updateLightAndObjects(obj->getMaterialIndex()); } if (identifier == "MAT") diff --git a/srcs/class/Window.cpp b/srcs/class/Window.cpp index c25adb6..a3172a1 100644 --- a/srcs/class/Window.cpp +++ b/srcs/class/Window.cpp @@ -231,11 +231,7 @@ void Window::imGuiRender(ShaderProgram &raytracing_program) ImGui::Text("Material %d", i); has_changed |= ImGui::ColorEdit3("Color", &mat.color[0]); - if (ImGui::SliderFloat("Emission", &mat.emission, 0.0f, 10.0f)) - { - has_changed = 1; - _scene->updateLightAndObjects(i); - } + has_changed |= ImGui::SliderFloat("Emission", &mat.emission, 0.0f, 10.0f); if (mat.type == 0) {