diff --git a/Makefile b/Makefile index 9d73d4b..f26802f 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ ifeq ($(OS),Windows_NT) LINE_CLR = \33[2K\r RM := del /S /Q DIR_DUP = if not exist "$(@D)" mkdir "$(@D)" - CC := g++ -O3 + CC := g++ -g IFLAGS := -I./includes -I./includes/RT -I./includes/imgui LDFLAGS := -L./lib -lglfw3 -lopengl32 -lgdi32 -lcglm else @@ -28,7 +28,7 @@ else RM := rm -rf DIR_DUP = mkdir -p $(@D) CC := clang++ - CFLAGS := -Wall -Wextra -Werror -g -O3 + CFLAGS := -Wall -Wextra -Werror -g IFLAGS := -I./includes -I./includes/RT -I./includes/imgui -I/usr/include LDFLAGS := -L/usr/lib/x86_64-linux-gnu -lglfw -lGL -lGLU -lX11 -lpthread -ldl -lstdc++ FILE = $(shell ls -lR srcs/ | grep -F .c | wc -l) @@ -55,6 +55,7 @@ ALL_SRCS := $(IMGUI_SRCS) \ class/SceneParser.cpp \ class/ObjParser.cpp \ class/BVH.cpp \ + class/TopBVH.cpp \ SRCS := $(ALL_SRCS:%=$(SRCS_DIR)/%) OBJS := $(addprefix $(OBJS_DIR)/, $(SRCS:%.cpp=%.o)) diff --git a/RT.exe b/RT.exe new file mode 100644 index 0000000..e4c83cf Binary files /dev/null and b/RT.exe differ diff --git a/imgui.ini b/imgui.ini index e0f3220..821a02d 100644 --- a/imgui.ini +++ b/imgui.ini @@ -3,26 +3,22 @@ Pos=60,60 Size=400,400 [Window][Camera] -Pos=1643,7 -Size=259,200 -Collapsed=1 +Pos=1636,1 +Size=259,208 [Window][Material] -Pos=1642,29 -Size=266,299 -Collapsed=1 +Pos=1634,219 +Size=266,290 [Window][Fog settings] -Pos=1641,52 +Pos=1625,788 Size=247,130 -Collapsed=1 [Window][Debug] Pos=1642,668 Size=260,143 [Window][Debug BVH] -Pos=1641,72 -Size=274,205 -Collapsed=1 +Pos=1625,930 +Size=274,137 diff --git a/includes/RT.hpp b/includes/RT.hpp index bfde952..f1f995c 100644 --- a/includes/RT.hpp +++ b/includes/RT.hpp @@ -62,7 +62,25 @@ struct Vertex { # include "Scene.hpp" # include "SceneParser.hpp" # include "ObjParser.hpp" + +struct AABB +{ + glm::vec3 min; + glm::vec3 max; + + AABB(glm::vec3 min, glm::vec3 max) : min(min), max(max) {} + + void grow( glm::vec3 p ) { min = glm::min( min, p ), max = glm::max( max, p ); } + + float area() + { + glm::vec3 e = max - min; + return (e.x * e.y + e.y * e.z + e.z * e.x); + } +}; + # include "BVH.hpp" +# include "TopBVH.hpp" diff --git a/includes/RT/BVH.hpp b/includes/RT/BVH.hpp index 8fa34ad..198e210 100644 --- a/includes/RT/BVH.hpp +++ b/includes/RT/BVH.hpp @@ -18,22 +18,7 @@ struct GPUTriangle; struct GPUObject; struct GPUBvh; - -struct AABB -{ - glm::vec3 min; - glm::vec3 max; - - AABB(glm::vec3 min, glm::vec3 max) : min(min), max(max) {} - - void grow( glm::vec3 p ) { min = glm::min( min, p ), max = glm::max( max, p ); } - - float area() - { - glm::vec3 e = max - min; - return (e.x * e.y + e.y * e.z + e.z * e.x); - } -}; +struct AABB; struct BVHStats { diff --git a/includes/RT/TopBVH.hpp b/includes/RT/TopBVH.hpp new file mode 100644 index 0000000..fe09d63 --- /dev/null +++ b/includes/RT/TopBVH.hpp @@ -0,0 +1,54 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* TopBVH.hpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ycontre +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/01/16 21:36:19 by TheRed #+# #+# */ +/* Updated: 2025/01/17 18:59:28 by ycontre ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef RT_TOPBVH__HPP +# define RT_TOPBVH__HPP + +# include "RT.hpp" + +struct GPUBvhData; +struct GPUTopBvh; +struct AABB; + +class TopBVH +{ + public: + TopBVH(std::vector &bvhs_data, std::vector &bvhs, int first_bvh, int bvh_count); + + void updateBounds(std::vector &bvhs_data, std::vector &bvhs); + void subdivide(std::vector &bvhs_data, std::vector &bvhs); + + float evaluateSah(std::vector &bvhs_data, std::vector &bvhs, int axis, float pos); + + // int getSize(); + // int getLeaves(); + + // void flatten(std::vector &TopBVHs, int ¤tIndex); + // GPUTopBVH toGPUTopBVH(); + + // const AABB &getAABB() const; + // std::vector getGPUTopBVHs(); + + + private: + AABB _aabb; + + TopBVH *_left; + TopBVH *_right; + + bool _is_leaf; + + int _first_bvh; + int _bvh_count; +}; + +#endif \ No newline at end of file diff --git a/scenes/dragon.rt b/scenes/dragon.rt index 9ec9a3b..2ba38ce 100644 --- a/scenes/dragon.rt +++ b/scenes/dragon.rt @@ -24,8 +24,8 @@ pl 0 -2 0 0 1 0 2 // floor qu -1 1.999 -1 2 0 0 0 0 2 6 -OBJ obj/Dragon_800K.obj -0.5 0 0.55 5 0 90 0 -OBJ obj/Dragon_800K.obj 0.5 0 -0.55 5 0 -90 0 +OBJ scenes/obj/Dragon_800K.obj -0.5 0 0.55 5 0 90 0 +OBJ scenes/obj/Dragon_800K.obj 0.5 0 -0.55 5 0 -90 0 # OBJ obj/Model.obj diff --git a/scenes/test.rt b/scenes/test.rt index 62a746e..3db285a 100644 --- a/scenes/test.rt +++ b/scenes/test.rt @@ -24,7 +24,8 @@ qu -2.5 0 -2.5 0 5 0 15 0 0 3 qu 11.5 0 -2.5 0 5 0 0 0 15 1 qu -2.5 0 11.5 0 5 0 15 0 0 4 - +OBJ obj/Dragon_8K.obj -5 0.38 0 1 +OBJ obj/Dragon_8K.obj 5 0.38 0 1 OBJ obj/Dragon_8K.obj 0 0.38 0 1 OBJ obj/Dragon_8K.obj 0 0.38 1 1 diff --git a/shaders/debug.glsl b/shaders/debug.glsl index 3fa249c..6c8ddcc 100644 --- a/shaders/debug.glsl +++ b/shaders/debug.glsl @@ -212,44 +212,6 @@ hitInfo traceBVH(Ray ray, GPUBvhData bvh_data, inout Stats stats) return (hit); } -mat3 rotateX(float angleRadians) { - float c = cos(angleRadians); - float s = sin(angleRadians); - return mat3( - 1.0, 0.0, 0.0, - 0.0, c, -s, - 0.0, s, c - ); -} - -mat3 rotateY(float angleRadians) { - float c = cos(angleRadians); - float s = sin(angleRadians); - return mat3( - c, 0.0, s, - 0.0, 1.0, 0.0, - -s, 0.0, c - ); -} - -mat3 rotateZ(float angleRadians) { - float c = cos(angleRadians); - float s = sin(angleRadians); - return mat3( - c, -s, 0.0, - s, c, 0.0, - 0.0, 0.0, 1.0 - ); -} - -mat3 createTransformMatrix(vec3 rotationAngles, float scale) { - mat3 rotMatrix = rotateZ(rotationAngles.z) * - rotateY(rotationAngles.y) * - rotateX(rotationAngles.x); - - return rotMatrix * scale; -} - hitInfo traverseBVHs(Ray ray, inout Stats stats) { hitInfo hit; diff --git a/srcs/RT.cpp b/srcs/RT.cpp index 492a9d2..cda5306 100644 --- a/srcs/RT.cpp +++ b/srcs/RT.cpp @@ -20,8 +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/debug.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); diff --git a/srcs/class/Scene.cpp b/srcs/class/Scene.cpp index f3aab2c..d7a378b 100644 --- a/srcs/class/Scene.cpp +++ b/srcs/class/Scene.cpp @@ -58,6 +58,9 @@ bool Scene::parseScene(char *name) } file.close(); + TopBVH *top_bvh = new TopBVH(_gpu_bvh_data, _gpu_bvh, 0, _gpu_bvh_data.size()); + (void) top_bvh; + std::cout << "Parsing done" << std::endl; @@ -187,7 +190,6 @@ void Scene::addBvh(std::vector &triangles, glm::vec3 offset, float sc std::cout << "\tMin triangles per leaf: " << stats.min_triangles << std::endl; std::cout << "\tMax triangles per leaf: " << stats.max_triangles << std::endl; std::cout << "\tAverage triangles per leaf: " << stats.average_triangles << std::endl << std::endl; - } void Scene::addMaterial(Material *material) diff --git a/srcs/class/TopBVH.cpp b/srcs/class/TopBVH.cpp new file mode 100644 index 0000000..2a05fba --- /dev/null +++ b/srcs/class/TopBVH.cpp @@ -0,0 +1,144 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* TopBvh.cpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: TheRed +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/01/21 21:46:45 by TheRed #+# #+# */ +/* Updated: 2025/01/21 21:46:45 by TheRed ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "TopBVH.hpp" + +TopBVH::TopBVH(std::vector &bvhs_data, std::vector &bvhs, int first_bvh, int bvh_count) : _aabb(AABB(glm::vec3(1e30f), glm::vec3(-1e30f))) +{ + _left = nullptr; + _right = nullptr; + + _is_leaf = true; + + _first_bvh = first_bvh; + _bvh_count = bvh_count; + + updateBounds(bvhs_data, bvhs); + subdivide(bvhs_data, bvhs); +} + +void TopBVH::updateBounds(std::vector &bvhs_data, std::vector &bvhs) +{ + for (int i = 0; i < _bvh_count; i++) + { + GPUBvhData bvh_data = bvhs_data[_first_bvh + i]; + GPUBvh root_bvh = bvhs[bvh_data.bvh_start_index]; + + glm::vec3 min = root_bvh.min - bvh_data.offset; + glm::vec3 max = root_bvh.max - bvh_data.offset; + + _aabb.min = glm::min(_aabb.min, min); + _aabb.max = glm::max(_aabb.max, max); + } +} + +float TopBVH::evaluateSah(std::vector &bvhs_data, std::vector &bvhs, int axis, float pos) +{ + AABB left_box(glm::vec3(1e30f), glm::vec3(-1e30f)); + AABB right_box(glm::vec3(1e30f), glm::vec3(-1e30f)); + + int left_count = 0; + int right_count = 0; + + for (int i = 0; i < _bvh_count; i++) + { + GPUBvhData bvh_data = bvhs_data[_first_bvh + i]; + GPUBvh bvh_root = bvhs[bvh_data.bvh_start_index]; + + glm::vec3 min = bvh_root.min - bvh_data.offset; + glm::vec3 max = bvh_root.max - bvh_data.offset; + + if (min[axis] < pos) + { + left_count++; + left_box.grow( min ); + left_box.grow( max ); + } + else + { + right_count++; + right_box.grow( min ); + right_box.grow( max ); + } + } + + return (left_box.area() * left_count + right_box.area() * right_count); +} + +void TopBVH::subdivide(std::vector &bvhs_data, std::vector &bvhs) +{ + if (_bvh_count <= 1) + return ; + + + const int num_test_per_axis = 5; + + int best_axis = 0; + float best_pos = 0.0f; + float best_cost = 1e30f; + + for (int axis = 0; axis < 3; axis++) + { + float start_pos = _aabb.min[axis]; + float end_pos = _aabb.max[axis]; + + for (int i = 0; i < num_test_per_axis; i++) + { + float split_t = (i + 1) / (num_test_per_axis + 1.0f); + float candidate_pos = start_pos + (end_pos - start_pos) * split_t; + + float cost = evaluateSah(bvhs_data, bvhs, axis, candidate_pos); + + if (cost < best_cost) + { + best_pos = candidate_pos; + best_axis = axis; + best_cost = cost; + } + } + } + + int axis = best_axis; + float split_pos = best_pos; + + int i = _first_bvh; + int j = _first_bvh + _bvh_count - 1; + + while (i <= j) + { + GPUBvhData bvh_data = bvhs_data[i]; + GPUBvh root = bvhs[bvh_data.bvh_start_index]; + glm::vec3 min = root.min - bvh_data.offset; + glm::vec3 max = root.max - bvh_data.offset; + glm::vec3 centroid = (min + max) * 0.5f; + + if (centroid[axis] < split_pos) + i++; + else + { + std::swap(bvhs_data[i], bvhs_data[j]); + j--; + } + } + + int left_count = i - _first_bvh; + + if (left_count == 0 || left_count == _bvh_count) + return ; + + _is_leaf = false; + + _left = new TopBVH(bvhs_data, bvhs, _first_bvh, left_count); + _right = new TopBVH(bvhs_data, bvhs, i, _bvh_count - left_count); + + _bvh_count = 0; +} \ No newline at end of file