~ | BVH sent to gpu

This commit is contained in:
TheRedShip
2025-01-17 16:27:39 +01:00
parent 6f80a66550
commit 6fdea11adb
14 changed files with 359 additions and 46 deletions

View File

@ -54,7 +54,7 @@ ALL_SRCS := $(IMGUI_SRCS) \
class/Scene.cpp \
class/SceneParser.cpp \
class/ObjParser.cpp \
CLASS/BVH.cpp \
class/BVH.cpp \
SRCS := $(ALL_SRCS:%=$(SRCS_DIR)/%)
OBJS := $(addprefix $(OBJS_DIR)/, $(SRCS:%.cpp=%.o))

BIN
RT

Binary file not shown.

View File

@ -15,6 +15,9 @@
# include "RT.hpp"
struct GPUObject;
struct GPUBvh;
struct AABB
{
glm::vec3 min;
@ -23,7 +26,6 @@ struct AABB
AABB(glm::vec3 min, glm::vec3 max) : min(min), max(max) {}
};
struct GPUObject;
class BVH
{
@ -36,7 +38,13 @@ class BVH
void updateBounds(std::vector<GPUObject> primitives);
void subdivide(std::vector<GPUObject> primitives);
int size();
void flatten(std::vector<GPUBvh> &bvhs, int &currentIndex);
GPUBvh toGPUBvh();
const AABB &getAABB() const;
std::vector<GPUBvh> getGPUBvhs();
private:

View File

@ -54,6 +54,20 @@ struct GPUVolume
int enabled;
};
struct GPUBvh
{
alignas(16) glm::vec3 min;
alignas(16) glm::vec3 max;
int left_index;
int right_index;
int is_leaf;
int first_primitive;
int primitive_count;
};
class Sphere;
class Camera;
@ -74,11 +88,14 @@ class Scene
const std::vector<GPUObject> &getObjectData() const;
std::vector<GPUMaterial> &getMaterialData();
GPUVolume &getVolume();
std::vector<GPUBvh> &getBVH();
Camera *getCamera(void) const;
GPUMaterial getMaterial(int material_index);
private:
std::vector<GPUBvh> _gpu_bvh;
std::vector<GPUObject> _gpu_objects;
std::vector<GPUMaterial> _gpu_materials;

View File

@ -25,8 +25,6 @@ class Shader
void setupVertexBuffer(const Vertex* vertices, size_t size);
void drawTriangles(size_t size);
// void setBool(const std::string &name, bool value) const;
void set_int(const std::string &name, int value) const;
void set_float(const std::string &name, float value) const;

View File

@ -42,8 +42,8 @@ class Triangle : public Object
_vertex2 = glm::vec3(x2, y2, z2);
_vertex3 = glm::vec3(x3, y3, z3);
_vertex2 -= _position; //optimization
_vertex3 -= _position; //optimization
// _vertex2 -= _position; //optimization
// _vertex3 -= _position; //optimization
_normal = glm::normalize(glm::cross(_vertex2, _vertex3)); //optimization
@ -51,8 +51,8 @@ class Triangle : public Object
}
Triangle(const glm::vec3& position, const glm::vec3& vertex2, const glm::vec3& vertex3, const int mat_index)
: Object(position, mat_index), _vertex2(vertex2), _vertex3(vertex3) {
_vertex2 -= _position; //optimization
_vertex3 -= _position; //optimization
// _vertex2 -= _position; //optimization
// _vertex3 -= _position; //optimization
_normal = glm::normalize(glm::cross(_vertex2, _vertex3)); //optimization
}

View File

@ -11,17 +11,18 @@ MAT 255 255 255 5.0 0.0 0.0 //light
MAT 255 255 255 0.0 0.0 0.0 TRN // glass
# sp 0 -25 0 50 1
sp 0 -25 0 50 4
tr -4 5 0 -3 5 0 -4 5 1 0
tr 0 7 2 1 4 2 0 5 3 0
tr 3 7 2 4 5 1 2 6 3 0
sp 1 1 -0.5 2 0
sp -0.8 0.8 0 1.5 1
sp -2.2 0.4 0.25 1 2
sp -3 0.2 0.50 0.75 3
sp -3.8 -0.1 0.60 0.5 5
tr 7 5 0 8 5 0 7 5 1 0
tr 7 7 2 8 4 2 7 5 3 0
tr 10 7 2 11 5 1 8 6 3 0
tr 15 -2 4 11 5 1 8 6 3 0
tr 15 -2 4 11 5 1 7 5 9 0
tr 12 4 4 4 3 1 7 5 9 0
sp -0.071350 13.247917 0.518550 2 5
cy 0 1 2 0.5 2 -1.5 0 0.75 1
OBJ obj/Lowpoly_tree_sample.obj
# OBJ obj/Lowpoly_tree_sample.obj

17
shaders/bvh.glsl Normal file
View File

@ -0,0 +1,17 @@
bool intersectRayBVH(Ray ray, GPUBvh node)
{
vec3 invDir = 1.0 / ray.direction;
vec3 t1 = (node.min - ray.origin) * invDir;
vec3 t2 = (node.max - ray.origin) * invDir;
vec3 tMin = min(t1, t2);
vec3 tMax = max(t1, t2);
float tEnter = max(max(tMin.x, tMin.y), tMin.z);
float tExit = min(min(tMax.x, tMax.y), tMax.z);
return tEnter <= tExit && tExit >= 0.0;
}

View File

@ -161,7 +161,6 @@ hitInfo traceRay(Ray ray)
ray = portalRay(ray, hit);
}
return (hit);
}

204
shaders/debug.glsl Normal file
View File

@ -0,0 +1,204 @@
#version 430 core
layout(local_size_x = 16, local_size_y = 16) in;
layout(binding = 0, rgba32f) uniform image2D output_image;
layout(binding = 1, rgba32f) uniform image2D accumulation_image;
struct GPUCamera
{
mat4 view_matrix;
vec3 position;
float aperture_size;
float focus_distance;
float fov;
int bounce;
};
layout(std140, binding = 0) uniform CameraData
{
GPUCamera camera;
};
struct GPUObject {
mat4 rotation;
vec3 position; // 12 + 4
vec3 normal; // 12 + 4
vec3 vertex1; // 12 + 4
vec3 vertex2; // 12 + 4
float radius; // 4
int mat_index; // 4
int type; // 4
};
layout(std430, binding = 1) buffer ObjectBuffer
{
GPUObject objects[];
};
struct GPUBvh
{
vec3 min;
vec3 max;
int left_index;
int right_index;
int is_leaf;
int first_primitive;
int primitive_count;
};
layout(std430, binding = 4) buffer BvhBuffer
{
GPUBvh bvh[];
};
uniform int u_objectsNum;
uniform int u_bvhNum;
uniform vec2 u_resolution;
uniform int u_frameCount;
uniform float u_time;
struct Ray
{
vec3 origin;
vec3 direction;
};
struct hitInfo
{
float t;
float last_t;
vec3 normal;
vec3 position;
int obj_index;
};
#include "shaders/intersect.glsl"
#include "shaders/bvh.glsl"
int traceRay(Ray ray)
{
int num_hit;
num_hit = 0;
for (int i = 0; i < u_objectsNum; i++)
{
GPUObject obj = objects[i];
hitInfo temp_hit;
if (intersect(ray, obj, temp_hit))
num_hit++;
}
return (num_hit);
}
int traceBVHBad(Ray ray)
{
int num_hit;
num_hit = 0;
for (int i = 0; i < u_bvhNum; i++)
{
GPUBvh node = bvh[i];
if (intersectRayBVH(ray, node))
{
// num_hit++;
for (int i = 0; i < node.primitive_count; i++)
{
GPUObject obj = objects[node.first_primitive + i];
hitInfo tmp;
if (intersect(ray, obj, tmp))
num_hit++;
}
}
}
return (num_hit);
}
int traceBVH(Ray ray)
{
int num_hit = 0;
const int MAX_STACK_SIZE = 64;
int stack[MAX_STACK_SIZE];
int stack_ptr = 0;
stack[0] = 0;
vec3 inv_dir = 1.0 / ray.direction;
while (stack_ptr >= 0)
{
int current_index = stack[stack_ptr--];
GPUBvh node = bvh[current_index];
if (intersectRayBVH(ray, node))
{
num_hit++;
if (node.is_leaf != 0)
{
for (int i = 0; i < node.primitive_count; i++)
{
GPUObject obj = objects[node.first_primitive + i];
hitInfo tmp;
if (intersect(ray, obj, tmp))
num_hit++;
}
}
if (node.is_leaf == 0 && stack_ptr < MAX_STACK_SIZE - 2)
{
stack_ptr++;
stack[stack_ptr] = node.left_index;
stack_ptr++;
stack[stack_ptr] = node.right_index;
}
}
}
return (num_hit);
}
Ray initRay(vec2 uv)
{
float fov = camera.fov;
float focal_length = 1.0 / tan(radians(fov) / 2.0);
vec3 origin = camera.position;
vec3 view_space_ray = normalize(vec3(uv.x, uv.y, -focal_length));
vec3 ray_direction = normalize((inverse(camera.view_matrix) * vec4(view_space_ray, 0.0)).xyz);
return (Ray(origin, ray_direction));
}
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(pixel_coords)) / u_resolution) * 2.0 - 1.0;;
uv.x *= u_resolution.x / u_resolution.y;
Ray ray = initRay(uv);
int hits = traceBVH(ray);
vec3 color = vec3(float(hits) / float(10));
imageStore(output_image, pixel_coords, vec4(color, 1.));
}

View File

@ -68,15 +68,18 @@ bool intersectQuad(Ray ray, GPUObject obj, out hitInfo hit)
}
bool intersectTriangle(Ray ray, GPUObject obj, out hitInfo hit)
{
vec3 pvec = cross(ray.direction, obj.vertex2);
float det = dot(obj.vertex1, pvec);
vec3 vertex1 = obj.vertex1 - obj.position;
vec3 vertex2 = obj.vertex2 - obj.position;
vec3 pvec = cross(ray.direction, vertex2);
float det = dot(vertex1, pvec);
vec3 tvec = ray.origin - obj.position;
float invDet = 1.0 / det;
float u = dot(tvec, pvec) * invDet;
vec3 qvec = cross(tvec, obj.vertex1);
vec3 qvec = cross(tvec, vertex1);
float v = dot(ray.direction, qvec) * invDet;
float t = dot(obj.vertex2, qvec) * invDet;
float t = dot(vertex2, qvec) * invDet;
bool valid = abs(det) > 1e-8 &&
u >= 0.0 && u <= 1.0 &&

View File

@ -20,7 +20,8 @@ int main(int argc, char **argv)
return (1);
Window window(&scene, WIDTH, HEIGHT, "RT_GPU", 0);
Shader shader("shaders/vertex.vert", "shaders/frag.frag", "shaders/compute.glsl");
// Shader shader("shaders/vertex.vert", "shaders/frag.frag", "shaders/compute.glsl");
Shader shader("shaders/vertex.vert", "shaders/frag.frag", "shaders/debug.glsl");
GLint max_gpu_size;
glGetIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &max_gpu_size);
@ -51,6 +52,12 @@ int main(int argc, char **argv)
glBufferData(GL_SHADER_STORAGE_BUFFER, scene.getGPULights().size() * sizeof(int), nullptr, GL_STATIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, lightSSBO);
GLuint bvhSSBO;
glGenBuffers(1, &bvhSSBO);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, bvhSSBO);
glBufferData(GL_SHADER_STORAGE_BUFFER, scene.getBVH().size() * sizeof(GPUBvh), nullptr, GL_STATIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, bvhSSBO);
GLuint cameraUBO;
glGenBuffers(1, &cameraUBO);
@ -86,6 +93,11 @@ int main(int argc, char **argv)
glBindBuffer(GL_SHADER_STORAGE_BUFFER, lightSSBO);
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, gpu_lights_array.size() * sizeof(int), gpu_lights_array.data());
std::vector<GPUBvh> gpu_bvh = scene.getBVH();
glBindBuffer(GL_SHADER_STORAGE_BUFFER, bvhSSBO);
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, gpu_bvh.size() * sizeof(GPUBvh), gpu_bvh.data());
GPUCamera camera_data = scene.getCamera()->getGPUData();
glBindBuffer(GL_UNIFORM_BUFFER, cameraUBO);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(GPUCamera), &camera_data);
@ -96,6 +108,7 @@ int main(int argc, char **argv)
shader.set_int("u_frameCount", window.getFrameCount());
shader.set_int("u_objectsNum", object_data.size());
shader.set_int("u_bvhNum", gpu_bvh.size());
shader.set_int("u_lightsNum", gpu_lights.size());
shader.set_int("u_pixelisation", window.getPixelisation());
shader.set_float("u_time", (float)(glfwGetTime()));

View File

@ -35,12 +35,6 @@ void BVH::updateBounds(std::vector <GPUObject> primitives)
if (leaf_triangle.type != (int)Object::Type::TRIANGLE)
continue ;
if (leaf_triangle.type == (int)Object::Type::TRIANGLE)
{
leaf_triangle.vertex1 += leaf_triangle.position;
leaf_triangle.vertex2 += leaf_triangle.position;
}
_aabb.min = glm::min(_aabb.min, leaf_triangle.position);
_aabb.min = glm::min(_aabb.min, leaf_triangle.vertex1);
_aabb.min = glm::min(_aabb.min, leaf_triangle.vertex2);
@ -63,7 +57,7 @@ void BVH::subdivide(std::vector<GPUObject> primitives)
if (extent.y > extent.x) axis = 1;
if (extent.z > extent[axis]) axis = 2;
glm::vec3 split_pos = _aabb.min + extent[axis] * 0.5f;
float split_pos = _aabb.min[axis] + extent[axis] * 0.5f;
int i = _first_primitive;
int j = _first_primitive + _primitive_count - 1;
@ -73,7 +67,7 @@ void BVH::subdivide(std::vector<GPUObject> primitives)
glm::vec3 centroid = primitives[i].position + primitives[i].vertex1 + primitives[i].vertex2;
centroid /= 3.0f;
if (centroid[axis] < split_pos[axis])
if (centroid[axis] < split_pos)
i++;
else
{
@ -103,7 +97,6 @@ void BVH::showAABB(Scene *scene)
{
if (_is_leaf)
{
scene->addObject(new Sphere(_aabb.min, 0.5f, 6));
scene->addObject(new Sphere(_aabb.max, 0.5f, 6));
scene->addObject(new Sphere(glm::vec3(_aabb.min.x, _aabb.min.y, _aabb.max.z), 0.5f, 6));
@ -112,7 +105,6 @@ void BVH::showAABB(Scene *scene)
scene->addObject(new Sphere(glm::vec3(_aabb.min.x, _aabb.max.y, _aabb.max.z), 0.5f, 6));
scene->addObject(new Sphere(glm::vec3(_aabb.max.x, _aabb.min.y, _aabb.max.z), 0.5f, 6));
scene->addObject(new Sphere(glm::vec3(_aabb.max.x, _aabb.max.y, _aabb.min.z), 0.5f, 6));
}
else
{
@ -125,3 +117,59 @@ const AABB &BVH::getAABB() const
{
return (_aabb);
}
GPUBvh BVH::toGPUBvh()
{
GPUBvh bvh;
bvh.is_leaf = _is_leaf;
bvh.first_primitive = _first_primitive;
bvh.primitive_count = _primitive_count;
bvh.max = _aabb.max;
bvh.min = _aabb.min;
return (bvh);
}
void BVH::flatten(std::vector<GPUBvh> &bvhs, int &currentIndex)
{
GPUBvh self_bvh = toGPUBvh();
int self_index = currentIndex++;
self_bvh.left_index = -1;
self_bvh.right_index = -1;
if (!_is_leaf)
{
self_bvh.left_index = currentIndex;
_left->flatten(bvhs, currentIndex);
self_bvh.right_index = currentIndex;
_right->flatten(bvhs, currentIndex);
}
bvhs[self_index] = self_bvh;
}
int BVH::size()
{
int count = 0;
if (_is_leaf)
return (0);
count += 1 + _left->size();
count += 1 + _right->size();
return (count);
}
std::vector<GPUBvh> BVH::getGPUBvhs()
{
std::vector<GPUBvh> bvhs(size() + 1);
int currentIndex = 0;
flatten(bvhs, currentIndex);
return (bvhs);
}

View File

@ -53,11 +53,11 @@ bool Scene::parseScene(char *name)
}
file.close();
//bvh
BVH *bvh = new BVH(_gpu_objects, 0, _gpu_objects.size());
bvh->showAABB(this);
// addObject(new Cube((bvh->getAABB().max + bvh->getAABB().min) / 2.0f, bvh->getAABB().max - bvh->getAABB().min, 7));
//
_gpu_bvh = bvh->getGPUBvhs();
// bvh->showAABB(this);
return (true);
}
@ -182,6 +182,11 @@ GPUVolume &Scene::getVolume()
return (_gpu_volume);
}
std::vector<GPUBvh> &Scene::getBVH()
{
return (_gpu_bvh);
}
Camera *Scene::getCamera(void) const
{
return (_camera);