mirror of
https://github.com/TheRedShip/RT_GPU.git
synced 2025-09-27 18:48:36 +02:00
+ | Fog beam laser now in objects
This commit is contained in:
@ -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"
|
||||
|
@ -47,7 +47,9 @@ class Object
|
||||
TRIANGLE,
|
||||
CUBE,
|
||||
PORTAL,
|
||||
CYLINDER
|
||||
CYLINDER,
|
||||
SPOTLIGHT,
|
||||
LASERBEAM
|
||||
};
|
||||
|
||||
virtual Type getType() const = 0;
|
||||
|
@ -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);
|
||||
|
68
includes/RT/objects/SpotLight.hpp
Normal file
68
includes/RT/objects/SpotLight.hpp
Normal 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
24
scenes/fog.rt
Normal 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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
{
|
||||
|
Reference in New Issue
Block a user