+ | Fog beam laser now in objects

This commit is contained in:
TheRedShip
2025-03-08 20:36:10 +01:00
committed by tomoron
parent ecc1f68329
commit 075c2a959a
11 changed files with 172 additions and 51 deletions

View File

@ -74,6 +74,7 @@ struct GPUDenoise
# include "objects/Cube.hpp"
# include "objects/Portal.hpp"
# include "objects/Cylinder.hpp"
# include "objects/SpotLight.hpp"
# include "Buffer.hpp"
# include "Arguments.hpp"

View File

@ -47,7 +47,9 @@ class Object
TRIANGLE,
CUBE,
PORTAL,
CYLINDER
CYLINDER,
SPOTLIGHT,
LASERBEAM
};
virtual Type getType() const = 0;

View File

@ -6,7 +6,7 @@
/* By: ycontre <ycontre@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/12/23 18:30:18 by ycontre #+# #+# */
/* Updated: 2025/03/18 13:37:23 by tomoron ### ########.fr */
/* Updated: 2025/03/18 16:47:45 by tomoron ### ########.fr */
/* */
/* ************************************************************************** */
@ -117,7 +117,6 @@ class Scene
bool loadTextures();
void updateLightAndObjects(int mat_id);
std::set<int> getGPULights();
void addBvh(std::vector<Triangle> &triangles, glm::vec3 offset, float scale, glm::mat4 transform);
@ -147,6 +146,7 @@ class Scene
void changeScene(std::string &name, std::vector<Buffer *> &buffers);
std::vector<Buffer *> createDataOnGPU(void);
void updateLightAndObjects(int mat_id);
private:
void init(std::string &name);

View File

@ -0,0 +1,68 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* SpotLight.hpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: TheRed <TheRed@students.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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

24
scenes/fog.rt Normal file
View File

@ -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

View File

@ -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

View File

@ -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));

View File

@ -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,25 +39,24 @@ 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 circleRadius = light_dist * tan(acos(0.995));
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)
{
#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));
// 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));
@ -73,10 +74,13 @@ vec3 sampleSphereLight(vec3 position, GPUObject obj, int light_index, GPUMateria
vec3 reflect_to_particle = normalize(position - reflect_ray.origin);
if (dot(reflect_ray.direction, reflect_to_particle) < 0.995)
if (dot(reflect_ray.direction, reflect_to_particle) < beam_cos_angle)
return vec3(0.0);
mat.color *= light_ray_mat.color;
return mat.emission * mat.color * vec3(10.0);
#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)

View File

@ -6,7 +6,7 @@
/* By: ycontre <ycontre@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/12/23 18:29:41 by ycontre #+# #+# */
/* Updated: 2025/03/18 13:37:16 by tomoron ### ########.fr */
/* Updated: 2025/03/18 16:14:11 by tomoron ### ########.fr */
/* */
/* ************************************************************************** */
@ -100,6 +100,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)
{
@ -121,6 +124,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<SpotLight *>(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<Portal *>(obj);

View File

@ -6,7 +6,7 @@
/* By: ycontre <ycontre@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/12/26 21:43:51 by TheRed #+# #+# */
/* Updated: 2025/02/04 01:21:11 by tomoron ### ########.fr */
/* Updated: 2025/03/18 16:47:59 by tomoron ### ########.fr */
/* */
/* ************************************************************************** */
@ -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)
@ -165,14 +166,12 @@ bool SceneParser::parseLine(const std::string &line)
Object *obj = it->second(ss);
GPUMaterial mat = _scene->getMaterial(obj->getMaterialIndex()); //verify material
(void)mat;
if (obj->getType() == Object::Type::PORTAL)
_scene->addObject(static_cast<Portal *>(obj)->createSupportQuad());
_scene->addObject(obj);
if (mat.emission > 0.0)
_scene->updateLightAndObjects(obj->getMaterialIndex());
}
if (identifier == "MAT")

View File

@ -239,11 +239,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)
{