+ | Optimization + reflection

This commit is contained in:
TheRedShip
2025-01-02 16:33:21 +01:00
parent 21f2e84b61
commit 5d92a82b66
14 changed files with 204 additions and 101 deletions

View File

@ -37,6 +37,7 @@ struct Vertex {
# include "Object.hpp" # include "Object.hpp"
# include "objects/Sphere.hpp" # include "objects/Sphere.hpp"
# include "objects/Plane.hpp"
# include "Camera.hpp" # include "Camera.hpp"
# include "Window.hpp" # include "Window.hpp"

View File

@ -38,6 +38,7 @@ class Object
enum class Type { enum class Type {
SPHERE, SPHERE,
PLANE,
}; };
virtual Type getType() const = 0; virtual Type getType() const = 0;

View File

@ -18,12 +18,16 @@
struct GPUObject struct GPUObject
{ {
alignas(16) glm::vec3 position; alignas(16) glm::vec3 position;
alignas(16) glm::vec3 color; alignas(16) glm::vec3 color;
float emission; float emission;
float roughness; float roughness;
float specular; float specular;
float radius;
int type; float radius; // sphere
alignas(16) glm::vec3 normal; // plane
int type;
}; };
class Sphere; class Sphere;

View File

@ -41,8 +41,9 @@ class Window
GLFWwindow *_window; GLFWwindow *_window;
Scene *_scene; Scene *_scene;
int _frameCount;
float _fps; float _fps;
float _delta;
int _frameCount;
}; };

View File

@ -0,0 +1,54 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Plane.hpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: ycontre <ycontre@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/12/23 19:12:51 by ycontre #+# #+# */
/* Updated: 2024/12/23 19:47:09 by ycontre ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef RT_Plane__HPP
# define RT_Plane__HPP
# include "RT.hpp"
class Plane : public Object
{
public:
Plane(std::stringstream &line) : Object(glm::vec3(0.0f), -1)
{
try {
float x, y, z;
float nx, ny, nz;
int mat_index;
if (!(line >> x >> y >> z))
throw std::runtime_error("Missing position");
if (!(line >> nx >> ny >> nz))
throw std::runtime_error("Missing plane's normal");
if (!(line >> mat_index))
throw std::runtime_error("Missing material properties");
_position = glm::vec3(x, y, z);
_normal = glm::vec3(nx, ny, nz);
_mat_index = mat_index;
}
catch (const std::exception &e) { throw; }
}
Plane(const glm::vec3 &position, const glm::vec3 &normal, const int mat_index)
: Object(position, mat_index), _normal(normal) {}
glm::vec3 getNormal() const { return (_normal); }
Type getType() const override { return Type::PLANE; }
private:
glm::vec3 _normal;
};
#endif

View File

@ -1,14 +1,29 @@
MAT 255 255 255 0.0 1.0 2.0 MAT 255 255 255 0.0 0.0 0.0
MAT 255 255 255 3.0 1.0 2.0 MAT 255 255 255 2.0 0.0 0.0
MAT 255 0 0 0.0 1.0 2.0
sp 0 -50 -6 50.0 0 MAT 255 0 0 0.0 0.0 0.0
sp 50 30 -6 30.0 1 MAT 0 150 255 0.0 0.0 0.0
MAT 150 255 150 0.0 0.0 0.0
MAT 255 255 255 0.0 1.0 0.0
sp 0 7.5 0 5 1
sp 0 1 0 0.5 5
sp 0 -2 -1 1 2
sp -1 -2 0.8 1 3
sp 1 -2 0.8 1 4
pl 0 -3 0 0 1 0 0
pl 3 0 0 -1 0 0 0
pl -3 0 0 1 0 0 0
pl 0 3 0 0 -1 0 0
pl 0 0 -3 0 0 1 0
pl 0 0 3 0 0 -1 0
sp 0 1 -2 1.5 0
sp 0 2 -5 1.5 2
sp 0 4 -1 1.5 2
R 1.0 -2.0 10 R 1.0 -2.0 10

View File

@ -1,19 +1,21 @@
#version 430 core #version 430 core
#include "shaders/random.glsl"
layout(local_size_x = 16, local_size_y = 16) in; layout(local_size_x = 16, local_size_y = 16) in;
layout(binding = 0, rgba32f) uniform image2D outputImage; layout(binding = 0, rgba32f) uniform image2D output_image;
layout(binding = 1, rgba32f) uniform image2D accumulationImage; layout(binding = 1, rgba32f) uniform image2D accumulation_image;
struct GPUObject { struct GPUObject {
vec3 position; // 12 + 4 vec3 position; // 12 + 4
vec3 color; // 12 + 4 vec3 color; // 12 + 4
float emission; // 4 float emission; // 4
float roughness; // 4 float roughness; // 4
float specular; // 4 float specular; // 4
float radius; // 4 float radius; // 4
int type; // 4 + 12 vec3 normal; // 12 + 4
int type; // 4
}; };
layout(std430, binding = 1) buffer ObjectBuffer layout(std430, binding = 1) buffer ObjectBuffer
@ -28,9 +30,6 @@ uniform mat4 u_viewMatrix;
uniform int u_frameCount; uniform int u_frameCount;
uniform float u_time; uniform float u_time;
vec3 lightPos = vec3(5.0, 5.0, 5.0);
vec3 lightColor = vec3(1.0, 1.0, 1.0);
struct Ray struct Ray
{ {
vec3 origin; vec3 origin;
@ -45,29 +44,10 @@ struct hitInfo
int obj_index; int obj_index;
}; };
bool intersectSphere(Ray ray, GPUObject obj, out hitInfo hit) #include "shaders/random.glsl"
{ #include "shaders/intersect.glsl"
vec3 oc = ray.origin - obj.position;
float a = dot(ray.direction, ray.direction);
float b = 2.0 * dot(oc, ray.direction);
float c = dot(oc, oc) - obj.radius * obj.radius;
float discriminant = b * b - 4.0 * a * c;
if (discriminant < 0.0) hitInfo traceRay(Ray ray)
return false;
float t = (-b - sqrt(discriminant)) / (2.0 * a);
if (t < 0.0)
t = (-b + sqrt(discriminant)) / (2.0 * a);
hit.t = t;
hit.position = ray.origin + ray.direction * t;
hit.normal = normalize(hit.position - obj.position);
return (true);
}
hitInfo trace_ray(Ray ray)
{ {
hitInfo hit; hitInfo hit;
hit.t = 1e30; hit.t = 1e30;
@ -77,31 +57,46 @@ hitInfo trace_ray(Ray ray)
{ {
GPUObject obj = objects[i]; GPUObject obj = objects[i];
hitInfo tempHit; hitInfo temp_hit;
if (intersectSphere(ray, obj, tempHit)) if (intersect(ray, obj, temp_hit) && temp_hit.t > 0.0f && temp_hit.t < hit.t)
{ {
if (tempHit.t > 0.0f && tempHit.t < hit.t) hit.t = temp_hit.t;
{ hit.obj_index = i;
hit.t = tempHit.t; hit.position = temp_hit.position;
hit.obj_index = i; hit.normal = temp_hit.normal;
hit.position = tempHit.position;
hit.normal = tempHit.normal;
}
} }
} }
return (hit); return (hit);
} }
vec3 pathtrace(Ray ray, vec2 random) Ray newRay(hitInfo hit, Ray ray, vec2 uv)
{
Ray new_ray;
vec3 in_unit_sphere;
in_unit_sphere = normalize(randomVec3(uv, u_time));
in_unit_sphere *= sign(dot(in_unit_sphere, hit.normal));
vec3 diffuse_dir = normalize(hit.normal + in_unit_sphere);
vec3 specular_dir = reflect(ray.direction, hit.normal);
new_ray.origin = hit.position + hit.normal * 0.001;
new_ray.direction = mix(diffuse_dir, specular_dir, objects[hit.obj_index].roughness);
return (new_ray);
}
vec3 pathtrace(Ray ray, vec2 uv)
{ {
vec3 color = vec3(1.0); vec3 color = vec3(1.0);
vec3 light = vec3(0.0); vec3 light = vec3(0.0);
float closest_t = 1e30; float closest_t = 1e30;
for (int i = 0; i < 10; i++)
for (int i = 0; i < 3; i++)
{ {
hitInfo hit = trace_ray(ray); hitInfo hit = traceRay(ray);
if (hit.obj_index == -1) if (hit.obj_index == -1)
{ {
light += vec3(0); //ambient color light += vec3(0); //ambient color
@ -117,40 +112,35 @@ vec3 pathtrace(Ray ray, vec2 random)
break; break;
} }
ray.origin = hit.position + hit.normal * 0.001; ray = newRay(hit, ray, uv);
//cosine weighted importance sampling
vec3 unit_sphere = normalize(randomVec3(random, u_time));
if (dot(unit_sphere, hit.normal) < 0.0)
unit_sphere = -unit_sphere;
ray.direction = normalize(hit.normal + unit_sphere);
} }
return (color * light); return (color * light);
} }
void main() { void main()
ivec2 pixelCoords = ivec2(gl_GlobalInvocationID.xy); {
if (pixelCoords.x >= int(u_resolution.x) || pixelCoords.y >= int(u_resolution.y)) ivec2 pixel_coords = ivec2(gl_GlobalInvocationID.xy);
if (pixel_coords.x >= int(u_resolution.x) || pixel_coords.y >= int(u_resolution.y))
return; return;
vec2 uv = vec2(pixelCoords) / u_resolution; vec2 uv = (vec2(pixel_coords) / u_resolution) * 2.0 - 1.0;;
uv = uv * 2.0 - 1.0;
uv.x *= u_resolution.x / u_resolution.y; uv.x *= u_resolution.x / u_resolution.y;
float fov = 90.0; float fov = 90.0;
float focal_length = 1.0 / tan(radians(fov) / 2.0); float focal_length = 1.0 / tan(radians(fov) / 2.0);
vec3 viewSpaceRay = normalize(vec3(uv.x, uv.y, -focal_length)); vec3 view_space_ray = normalize(vec3(uv.x, uv.y, -focal_length));
vec3 rayDirection = (inverse(u_viewMatrix) * vec4(viewSpaceRay, 0.0)).xyz; vec3 ray_direction = normalize((inverse(u_viewMatrix) * vec4(view_space_ray, 0.0)).xyz);
rayDirection = normalize(rayDirection); Ray ray = Ray(u_cameraPosition, ray_direction);
Ray ray = Ray(u_cameraPosition, rayDirection);
vec3 color = pathtrace(ray, uv); vec3 color = pathtrace(ray, uv);
vec4 accum = imageLoad(accumulationImage, pixelCoords); float blend = 1.0 / float(u_frameCount + 1);
accum.rgb = accum.rgb * float(u_frameCount) / float(u_frameCount + 1) + color / float(u_frameCount + 1); vec4 accum = imageLoad(accumulation_image, pixel_coords);
accum.rgb = mix(accum.rgb, color, blend);
accum.a = 1.0; accum.a = 1.0;
imageStore(accumulationImage, pixelCoords, accum); imageStore(accumulation_image, pixel_coords, accum);
imageStore(outputImage, pixelCoords, accum); imageStore(output_image, pixel_coords, accum);
} }

39
shaders/intersect.glsl Normal file
View File

@ -0,0 +1,39 @@
bool intersectSphere(Ray ray, GPUObject obj, out hitInfo hit)
{
vec3 oc = ray.origin - obj.position;
float b = dot(oc, ray.direction);
float c = dot(oc, oc) - obj.radius * obj.radius;
float h = b * b - c;
float t = -b - sqrt(h);
t = mix(t, -b + sqrt(h), step(t, 0.0));
hit.t = t;
hit.position = ray.origin + ray.direction * t;
hit.normal = normalize(hit.position - obj.position);
return (h >= 0.0 && t > 0.0);
}
bool intersectPlane(Ray ray, GPUObject obj, out hitInfo hit)
{
float d = dot(obj.normal, ray.direction);
float t = dot(obj.position - ray.origin, obj.normal) / d;
bool valid = t >= 0.0 && d != 0.0;
hit.t = t;
hit.position = ray.origin + ray.direction * t;
hit.normal = d < 0.0 ? obj.normal : -obj.normal;
return (valid);
}
bool intersect(Ray ray, GPUObject obj, out hitInfo hit)
{
if (obj.type == 0)
return (intersectSphere(ray, obj, hit));
if (obj.type == 1)
return (intersectPlane(ray, obj, hit));
return (false);
}

View File

@ -58,7 +58,7 @@ int main(int argc, char **argv)
shader.drawTriangles(size); shader.drawTriangles(size);
std::cout << "\rFrame: " << window.getFrameCount() << " Fps: " << int(window.getFps()) << " " << std::flush; std::cout << "\rFrame: " << window.getFrameCount() << " Fps: " << int(window.getFps()) << " " << std::flush;
window.display(); window.display();
window.pollEvents(); window.pollEvents();
} }

View File

@ -38,22 +38,18 @@ void Camera::update_camera_vectors()
void Camera::update(float delta_time) void Camera::update(float delta_time)
{ {
delta_time = 0.016;
_velocity += _acceleration * delta_time; _velocity += _acceleration * delta_time;
// std::cout << _acceleration.x << " " << _acceleration.y << " " << _acceleration.z << " " << std::endl;
// Apply deceleration when no acceleration
if (glm::length(_acceleration) < 0.1f) if (glm::length(_acceleration) < 0.1f)
_velocity *= (1.0f - _deceleration_rate * delta_time); _velocity *= (1.0f - _deceleration_rate * delta_time);
// Clamp velocity to maximum speed
float speed = glm::length(_velocity); float speed = glm::length(_velocity);
if (speed > _maxSpeed) if (speed > _maxSpeed)
_velocity = (_velocity / speed) * _maxSpeed; _velocity = (_velocity / speed) * _maxSpeed;
// Update position
_position += _velocity * delta_time; _position += _velocity * delta_time;
// Reset acceleration
_acceleration = glm::vec3(0.0f); _acceleration = glm::vec3(0.0f);
} }

View File

@ -72,17 +72,24 @@ void Scene::updateGPUData()
mat = getMaterial(obj->getMaterialIndex()); mat = getMaterial(obj->getMaterialIndex());
gpu_obj.position = obj->getPosition(); gpu_obj.position = obj->getPosition();
gpu_obj.color = mat->color; gpu_obj.color = mat->color;
gpu_obj.emission = mat->emission; gpu_obj.emission = mat->emission;
gpu_obj.roughness = mat->roughness; gpu_obj.roughness = mat->roughness;
gpu_obj.specular = mat->specular; gpu_obj.specular = mat->specular;
gpu_obj.type = static_cast<int>(obj->getType()); gpu_obj.type = static_cast<int>(obj->getType());
if (obj->getType() == Object::Type::SPHERE) if (obj->getType() == Object::Type::SPHERE)
{ {
auto sphere = static_cast<const Sphere*>(obj); auto sphere = static_cast<const Sphere *>(obj);
gpu_obj.radius = sphere->getRadius(); gpu_obj.radius = sphere->getRadius();
} }
else if (obj->getType() == Object::Type::PLANE)
{
auto plane = static_cast<const Plane *>(obj);
gpu_obj.normal = plane->getNormal();
}
_gpu_objects.push_back(gpu_obj); _gpu_objects.push_back(gpu_obj);
} }

View File

@ -14,10 +14,16 @@
SceneParser::SceneParser(Scene *scene) : _scene(scene) SceneParser::SceneParser(Scene *scene) : _scene(scene)
{ {
object_parsers["sp"] = [](std::stringstream& ss) -> Object* object_parsers["sp"] = [](std::stringstream &ss) -> Object *
{ {
try { return (new Sphere(ss)); } try { return (new Sphere(ss)); }
catch (const std::exception& e) { throw; } catch (const std::exception &e) { throw; }
};
object_parsers["pl"] = [](std::stringstream &ss) -> Object *
{
try { return (new Plane(ss)); }
catch (const std::exception &e) { throw; }
}; };
} }

View File

@ -66,6 +66,7 @@ void Window::process_input()
if (forward || backward || left || right || up || down) if (forward || backward || left || right || up || down)
_frameCount = 0; _frameCount = 0;
_scene->getCamera()->process_keyboard(forward, backward, left, right, up, down); _scene->getCamera()->process_keyboard(forward, backward, left, right, up, down);
} }
@ -89,7 +90,6 @@ void Window::mouseMoveCallback(GLFWwindow* window, double xpos, double ypos)
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS) if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS)
{ {
win->_scene->getCamera()->process_mouse(xoffset, yoffset, true); win->_scene->getCamera()->process_mouse(xoffset, yoffset, true);
win->_frameCount = 0; win->_frameCount = 0;
} }
@ -116,10 +116,11 @@ void Window::display()
{ {
static double lastTime = glfwGetTime(); static double lastTime = glfwGetTime();
double currentTime = glfwGetTime(); double currentTime = glfwGetTime();
double delta = currentTime - lastTime;
_delta = currentTime - lastTime;
lastTime = currentTime; lastTime = currentTime;
_fps = 1.0f / delta; _fps = 1.0f / _delta;
_frameCount++; _frameCount++;
@ -128,7 +129,7 @@ void Window::display()
void Window::pollEvents() void Window::pollEvents()
{ {
this->process_input(); this->process_input();
_scene->getCamera()->update(1.0f / _fps); _scene->getCamera()->update(_delta);
glfwPollEvents(); glfwPollEvents();
} }

View File

@ -1,12 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* parsing.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: ycontre <ycontre@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/12/23 18:28:59 by ycontre #+# #+# */
/* Updated: 2024/12/23 18:29:00 by ycontre ### ########.fr */
/* */
/* ************************************************************************** */