mirror of
https://github.com/TheRedShip/RT_GPU.git
synced 2025-09-27 18:48:36 +02:00
+ | Optimization + reflection
This commit is contained in:
@ -37,6 +37,7 @@ struct Vertex {
|
||||
|
||||
# include "Object.hpp"
|
||||
# include "objects/Sphere.hpp"
|
||||
# include "objects/Plane.hpp"
|
||||
|
||||
# include "Camera.hpp"
|
||||
# include "Window.hpp"
|
||||
|
@ -38,6 +38,7 @@ class Object
|
||||
|
||||
enum class Type {
|
||||
SPHERE,
|
||||
PLANE,
|
||||
};
|
||||
|
||||
virtual Type getType() const = 0;
|
||||
|
@ -18,11 +18,15 @@
|
||||
struct GPUObject
|
||||
{
|
||||
alignas(16) glm::vec3 position;
|
||||
|
||||
alignas(16) glm::vec3 color;
|
||||
float emission;
|
||||
float roughness;
|
||||
float specular;
|
||||
float radius;
|
||||
|
||||
float radius; // sphere
|
||||
alignas(16) glm::vec3 normal; // plane
|
||||
|
||||
int type;
|
||||
};
|
||||
|
||||
|
@ -41,8 +41,9 @@ class Window
|
||||
GLFWwindow *_window;
|
||||
Scene *_scene;
|
||||
|
||||
int _frameCount;
|
||||
float _fps;
|
||||
float _delta;
|
||||
int _frameCount;
|
||||
|
||||
};
|
||||
|
||||
|
54
includes/RT/objects/Plane.hpp
Normal file
54
includes/RT/objects/Plane.hpp
Normal 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
|
@ -1,14 +1,29 @@
|
||||
|
||||
MAT 255 255 255 0.0 1.0 2.0
|
||||
MAT 255 255 255 3.0 1.0 2.0
|
||||
MAT 255 0 0 0.0 1.0 2.0
|
||||
MAT 255 255 255 0.0 0.0 0.0
|
||||
MAT 255 255 255 2.0 0.0 0.0
|
||||
|
||||
sp 0 -50 -6 50.0 0
|
||||
sp 50 30 -6 30.0 1
|
||||
MAT 255 0 0 0.0 0.0 0.0
|
||||
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
|
||||
|
@ -1,19 +1,21 @@
|
||||
#version 430 core
|
||||
|
||||
#include "shaders/random.glsl"
|
||||
|
||||
layout(local_size_x = 16, local_size_y = 16) in;
|
||||
layout(binding = 0, rgba32f) uniform image2D outputImage;
|
||||
layout(binding = 1, rgba32f) uniform image2D accumulationImage;
|
||||
layout(binding = 0, rgba32f) uniform image2D output_image;
|
||||
layout(binding = 1, rgba32f) uniform image2D accumulation_image;
|
||||
|
||||
struct GPUObject {
|
||||
vec3 position; // 12 + 4
|
||||
|
||||
vec3 color; // 12 + 4
|
||||
float emission; // 4
|
||||
float roughness; // 4
|
||||
float specular; // 4
|
||||
|
||||
float radius; // 4
|
||||
int type; // 4 + 12
|
||||
vec3 normal; // 12 + 4
|
||||
|
||||
int type; // 4
|
||||
};
|
||||
|
||||
layout(std430, binding = 1) buffer ObjectBuffer
|
||||
@ -28,9 +30,6 @@ uniform mat4 u_viewMatrix;
|
||||
uniform int u_frameCount;
|
||||
uniform float u_time;
|
||||
|
||||
vec3 lightPos = vec3(5.0, 5.0, 5.0);
|
||||
vec3 lightColor = vec3(1.0, 1.0, 1.0);
|
||||
|
||||
struct Ray
|
||||
{
|
||||
vec3 origin;
|
||||
@ -45,29 +44,10 @@ struct hitInfo
|
||||
int obj_index;
|
||||
};
|
||||
|
||||
bool intersectSphere(Ray ray, GPUObject obj, out hitInfo hit)
|
||||
{
|
||||
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;
|
||||
#include "shaders/random.glsl"
|
||||
#include "shaders/intersect.glsl"
|
||||
|
||||
if (discriminant < 0.0)
|
||||
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 traceRay(Ray ray)
|
||||
{
|
||||
hitInfo hit;
|
||||
hit.t = 1e30;
|
||||
@ -77,31 +57,46 @@ hitInfo trace_ray(Ray ray)
|
||||
{
|
||||
GPUObject obj = objects[i];
|
||||
|
||||
hitInfo tempHit;
|
||||
if (intersectSphere(ray, obj, tempHit))
|
||||
hitInfo temp_hit;
|
||||
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 = tempHit.t;
|
||||
hit.t = temp_hit.t;
|
||||
hit.obj_index = i;
|
||||
hit.position = tempHit.position;
|
||||
hit.normal = tempHit.normal;
|
||||
}
|
||||
hit.position = temp_hit.position;
|
||||
hit.normal = temp_hit.normal;
|
||||
}
|
||||
}
|
||||
|
||||
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 light = vec3(0.0);
|
||||
|
||||
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)
|
||||
{
|
||||
light += vec3(0); //ambient color
|
||||
@ -117,40 +112,35 @@ vec3 pathtrace(Ray ray, vec2 random)
|
||||
break;
|
||||
}
|
||||
|
||||
ray.origin = hit.position + hit.normal * 0.001;
|
||||
//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);
|
||||
ray = newRay(hit, ray, uv);
|
||||
}
|
||||
return (color * light);
|
||||
}
|
||||
|
||||
void main() {
|
||||
ivec2 pixelCoords = ivec2(gl_GlobalInvocationID.xy);
|
||||
if (pixelCoords.x >= int(u_resolution.x) || pixelCoords.y >= int(u_resolution.y))
|
||||
void main()
|
||||
{
|
||||
ivec2 pixel_coords = ivec2(gl_GlobalInvocationID.xy);
|
||||
if (pixel_coords.x >= int(u_resolution.x) || pixel_coords.y >= int(u_resolution.y))
|
||||
return;
|
||||
|
||||
vec2 uv = vec2(pixelCoords) / u_resolution;
|
||||
uv = uv * 2.0 - 1.0;
|
||||
vec2 uv = (vec2(pixel_coords) / u_resolution) * 2.0 - 1.0;;
|
||||
uv.x *= u_resolution.x / u_resolution.y;
|
||||
|
||||
float fov = 90.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;
|
||||
rayDirection = normalize(rayDirection);
|
||||
Ray ray = Ray(u_cameraPosition, rayDirection);
|
||||
vec3 ray_direction = normalize((inverse(u_viewMatrix) * vec4(view_space_ray, 0.0)).xyz);
|
||||
Ray ray = Ray(u_cameraPosition, ray_direction);
|
||||
|
||||
vec3 color = pathtrace(ray, uv);
|
||||
|
||||
vec4 accum = imageLoad(accumulationImage, pixelCoords);
|
||||
accum.rgb = accum.rgb * float(u_frameCount) / float(u_frameCount + 1) + color / float(u_frameCount + 1);
|
||||
float blend = 1.0 / float(u_frameCount + 1);
|
||||
vec4 accum = imageLoad(accumulation_image, pixel_coords);
|
||||
accum.rgb = mix(accum.rgb, color, blend);
|
||||
accum.a = 1.0;
|
||||
|
||||
imageStore(accumulationImage, pixelCoords, accum);
|
||||
imageStore(outputImage, pixelCoords, accum);
|
||||
imageStore(accumulation_image, pixel_coords, accum);
|
||||
imageStore(output_image, pixel_coords, accum);
|
||||
}
|
||||
|
||||
|
39
shaders/intersect.glsl
Normal file
39
shaders/intersect.glsl
Normal 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);
|
||||
}
|
@ -38,22 +38,18 @@ void Camera::update_camera_vectors()
|
||||
|
||||
void Camera::update(float delta_time)
|
||||
{
|
||||
_velocity += _acceleration * delta_time;
|
||||
// std::cout << _acceleration.x << " " << _acceleration.y << " " << _acceleration.z << " " << std::endl;
|
||||
delta_time = 0.016;
|
||||
|
||||
_velocity += _acceleration * delta_time;
|
||||
|
||||
// Apply deceleration when no acceleration
|
||||
if (glm::length(_acceleration) < 0.1f)
|
||||
_velocity *= (1.0f - _deceleration_rate * delta_time);
|
||||
|
||||
// Clamp velocity to maximum speed
|
||||
float speed = glm::length(_velocity);
|
||||
if (speed > _maxSpeed)
|
||||
_velocity = (_velocity / speed) * _maxSpeed;
|
||||
|
||||
// Update position
|
||||
_position += _velocity * delta_time;
|
||||
|
||||
// Reset acceleration
|
||||
_acceleration = glm::vec3(0.0f);
|
||||
}
|
||||
|
||||
|
@ -72,17 +72,24 @@ void Scene::updateGPUData()
|
||||
mat = getMaterial(obj->getMaterialIndex());
|
||||
|
||||
gpu_obj.position = obj->getPosition();
|
||||
|
||||
gpu_obj.color = mat->color;
|
||||
gpu_obj.emission = mat->emission;
|
||||
gpu_obj.roughness = mat->roughness;
|
||||
gpu_obj.specular = mat->specular;
|
||||
|
||||
gpu_obj.type = static_cast<int>(obj->getType());
|
||||
|
||||
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();
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
@ -14,10 +14,16 @@
|
||||
|
||||
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)); }
|
||||
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; }
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -66,6 +66,7 @@ void Window::process_input()
|
||||
|
||||
if (forward || backward || left || right || up || down)
|
||||
_frameCount = 0;
|
||||
|
||||
_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)
|
||||
{
|
||||
win->_scene->getCamera()->process_mouse(xoffset, yoffset, true);
|
||||
|
||||
win->_frameCount = 0;
|
||||
}
|
||||
|
||||
@ -116,10 +116,11 @@ void Window::display()
|
||||
{
|
||||
static double lastTime = glfwGetTime();
|
||||
double currentTime = glfwGetTime();
|
||||
double delta = currentTime - lastTime;
|
||||
|
||||
_delta = currentTime - lastTime;
|
||||
|
||||
lastTime = currentTime;
|
||||
_fps = 1.0f / delta;
|
||||
_fps = 1.0f / _delta;
|
||||
|
||||
_frameCount++;
|
||||
|
||||
@ -128,7 +129,7 @@ void Window::display()
|
||||
void Window::pollEvents()
|
||||
{
|
||||
this->process_input();
|
||||
_scene->getCamera()->update(1.0f / _fps);
|
||||
_scene->getCamera()->update(_delta);
|
||||
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
@ -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 */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
Reference in New Issue
Block a user