From 93fa0b2e214fbb70e6c03f5ca7536c7c32544aa7 Mon Sep 17 00:00:00 2001 From: ladevieq Date: Sun, 1 Aug 2021 18:45:50 +0200 Subject: Pack bvh nodes, optimize vertices size --- include/aabb.hpp | 11 ++++++++--- include/bvh-node.hpp | 38 ++++++++++++++++++++++-------------- include/scene.hpp | 2 +- include/triangle.hpp | 7 +------ shaders/compute.comp | 54 +++++++++++++++++++++++----------------------------- src/main.cpp | 4 ++-- src/scene.cpp | 4 +--- 7 files changed, 61 insertions(+), 59 deletions(-) diff --git a/include/aabb.hpp b/include/aabb.hpp index 3a4e680..9bc69d1 100644 --- a/include/aabb.hpp +++ b/include/aabb.hpp @@ -2,15 +2,20 @@ #define __AABB_HPP_ #include "vec3.hpp" +#include "triangle.hpp" #include #include class aabb { public: aabb() = default; - aabb(vec3 min_point, vec3 max_point): minimum(min_point), maximum(max_point) {} - aabb(vec3 position, float radius): minimum(position - vec3(radius)), maximum(position + vec3(radius)) {} - aabb(point3 &v1, point3 &v2, point3 &v3) { + aabb(vec3 &min_point, vec3 &max_point): minimum(min_point), maximum(max_point) {} + aabb(vec3 &position, float radius): minimum(position - vec3(radius)), maximum(position + vec3(radius)) {} + aabb(triangle &tri) { + auto &v1 = tri.v1.position; + auto &v2 = tri.v2.position; + auto &v3 = tri.v3.position; + minimum.x = fmin(fmin(v1.x, v2.x), v3.x); minimum.y = fmin(fmin(v1.y, v2.y), v3.y); minimum.z = fmin(fmin(v1.z, v2.z), v3.z); diff --git a/include/bvh-node.hpp b/include/bvh-node.hpp index 72c4bdf..09c9420 100644 --- a/include/bvh-node.hpp +++ b/include/bvh-node.hpp @@ -20,6 +20,13 @@ class bvh_node { uint32_t padding[2]; }; +struct packed_bvh_node { + float min[3]; + int32_t next_id = -1; + float max[3]; + int32_t primitive_id = -1; +}; + struct temp_node : public bvh_node { int32_t left_id; int32_t df_id; @@ -60,14 +67,14 @@ public: // // exporter(); // } - bvh(std::vector& triangles, std::vector& nodes) - :triangles(triangles), nodes(nodes) { - nodes.resize(2 * triangles.size() - 1); + bvh(std::vector& triangles, std::vector& packed_nodes) + :triangles(triangles) { + packed_nodes.resize(2 * triangles.size() - 1); temp_nodes = std::vector(2 * triangles.size() - 1); leafs = std::vector(triangles.size()); for (uint32_t id = 0; id < triangles.size(); id++) { - leafs[id].bounding_box = triangles[id].bounding_box; + leafs[id].bounding_box = aabb(triangles[id]); leafs[id].primitive_id = id; } @@ -80,18 +87,23 @@ public: for (uint32_t id = 0; id < temp_nodes.size(); id++) { auto old_node = temp_nodes[id]; - auto &node = nodes[old_node.df_id]; + auto &node = packed_nodes[old_node.df_id]; node.primitive_id = old_node.primitive_id; - node.bounding_box = old_node.bounding_box; + + node.min[0] = old_node.bounding_box.minimum.x; + node.min[1] = old_node.bounding_box.minimum.y; + node.min[2] = old_node.bounding_box.minimum.z; + + node.max[0] = old_node.bounding_box.maximum.x; + node.max[1] = old_node.bounding_box.maximum.y; + node.max[2] = old_node.bounding_box.maximum.z; if (old_node.next_id != -1) { node.next_id = temp_nodes[old_node.next_id].df_id; } } - // TODO: Pack nodes - // exporter(); } @@ -148,7 +160,6 @@ public: return -1; } - std::vector& nodes; std::vector temp_nodes; std::vector leafs; @@ -164,10 +175,9 @@ private: aabb compute_bounds(uint32_t begin, uint32_t end) { aabb global_box = aabb(); - for (uint32_t box_id = begin; box_id < end; box_id++) { - auto leaf = leafs[box_id]; - // global_box = aabb::surrounding_box(global_box, spheres[leaf.primitive_id].bounding_box); - global_box.union_with(triangles[leaf.primitive_id].bounding_box); + for (uint32_t id = begin; id < end; id++) { + // global_box.union_with(spheres[leaf.primitive_id].bounding_box); + global_box.union_with(leafs[id].bounding_box); } return global_box; @@ -235,7 +245,7 @@ private: } buckets[bucket_index].count++; - buckets[bucket_index].bb.union_with(primitive.bounding_box); + buckets[bucket_index].bb.union_with(leafs[i].bounding_box); } // Compute each potential split axis cost diff --git a/include/scene.hpp b/include/scene.hpp index 2a9ebf2..0002b1d 100644 --- a/include/scene.hpp +++ b/include/scene.hpp @@ -44,7 +44,7 @@ public: // Geometry & BVH // std::vector spheres; std::vector triangles; - std::vector nodes; + std::vector packed_nodes; }; #endif // !__SCENE_HPP_ diff --git a/include/triangle.hpp b/include/triangle.hpp index f1af241..9993efe 100644 --- a/include/triangle.hpp +++ b/include/triangle.hpp @@ -1,9 +1,6 @@ #ifndef __TRIANGLE_HPP_ #define __TRIANGLE_HPP_ -#include "aabb.hpp" -#include "material.hpp" - struct vertex { vec3 position; }; @@ -11,7 +8,7 @@ struct vertex { struct triangle { triangle() = default; triangle(vertex v1, vertex v2, vertex v3) - : v1(v1), v2(v2), v3(v3), bounding_box(v1.position, v2.position, v3.position) + : v1(v1), v2(v2), v3(v3) {} vec3 center() { @@ -21,8 +18,6 @@ struct triangle { vertex v1; vertex v2; vertex v3; - - aabb bounding_box; }; #endif // !__TRIANGLE_HPP_ diff --git a/shaders/compute.comp b/shaders/compute.comp index dc82b91..3a4a043 100644 --- a/shaders/compute.comp +++ b/shaders/compute.comp @@ -28,15 +28,9 @@ struct hit_info { bool front_face; }; -struct aabb { - vec4 min; - vec4 max; -}; - struct sphere { vec4 position; material mat; - aabb bb; float radius; float[3] padding; }; @@ -44,11 +38,11 @@ struct sphere { struct vertex { vec4 position; }; + struct triangle { vertex v1; vertex v2; vertex v3; - aabb bb; }; struct camera { @@ -67,10 +61,10 @@ struct camera { }; struct bvh_node { - aabb bb; + vec3 min; int next_id; + vec3 max; int primitive_id; - uint[2] padding; }; layout(set = 0, binding = 0) buffer scene_metadata { @@ -143,10 +137,10 @@ vec2 disk_vec(inout uint seed) { return vec2(cos(a) * r, sin(a) * r); } -bool hit_aabb(aabb b, ray r, float min_t, float max_t) { +bool hit_aabb(vec3 minimum, vec3 maximum, ray r, float min_t, float max_t) { const vec3 invdir = 1.0 / r.direction; - const vec3 f = (b.max.xyz - r.origin.xyz) * invdir; - const vec3 n = (b.min.xyz - r.origin.xyz) * invdir; + const vec3 f = (maximum.xyz - r.origin.xyz) * invdir; + const vec3 n = (minimum.xyz - r.origin.xyz) * invdir; const vec3 tmax = max(f, n); const vec3 tmin = min(f, n); @@ -157,20 +151,20 @@ bool hit_aabb(aabb b, ray r, float min_t, float max_t) { return t1 >= t0; } -uint hit_aabbs(ray r, float min_t, float max_t) { - uint hit_count = 0; - // for (uint idx = 0; idx <= spheres_count * 2; idx++) { - for (uint idx = 0; idx <= triangles_count * 2; idx++) { - hit_count += uint(hit_aabb(nodes[idx].bb, r, min_t, max_t)); - - if (nodes[idx].primitive_id >= 0) { - // hit_count += uint(hit_aabb(spheres[nodes[idx].primitive_id].bb, r, min_t, max_t)); - hit_count += uint(hit_aabb(triangles[nodes[idx].primitive_id].bb, r, min_t, max_t)); - } - } - - return hit_count; -} +// uint hit_aabbs(ray r, float min_t, float max_t) { +// uint hit_count = 0; +// // for (uint idx = 0; idx <= spheres_count * 2; idx++) { +// for (uint idx = 0; idx <= triangles_count * 2; idx++) { +// hit_count += uint(hit_aabb(nodes[idx].bb, r, min_t, max_t)); +// +// if (nodes[idx].primitive_id >= 0) { +// // hit_count += uint(hit_aabb(spheres[nodes[idx].primitive_id].bb, r, min_t, max_t)); +// // hit_count += uint(hit_aabb(triangles[nodes[idx].primitive_id].bb, r, min_t, max_t)); +// } +// } +// +// return hit_count; +// } bool hit_sphere(sphere s, ray r, float min_t, float max_t, out hit_info info) { vec3 origin_center = r.origin - s.position.xyz; @@ -253,7 +247,7 @@ bool hit_node(ray r, float min_t, float max_t, out hit_info info) { } id = nodes[id].next_id; } else { // Internal nodes - if (hit_aabb(nodes[id].bb, r, min_t, closest_t)) { + if (hit_aabb(nodes[id].min, nodes[id].max, r, min_t, closest_t)) { id++; } else { id = nodes[id].next_id; @@ -372,9 +366,9 @@ void main() { ray r = ray(cam.position.xyz + offset, proj_plane_pos.xyz - cam.position.xyz - offset); vec4 out_color = ray_color(r, seed); - if (debug_bvh) { - out_color -= hit_aabbs(r, 0.001, 1e15) * vec4(0.0, 0.025, 0.025, 0.0); - } + // if (debug_bvh) { + // out_color -= hit_aabbs(r, 0.001, 1e15) * vec4(0.0, 0.025, 0.025, 0.0); + // } float spp_scale = (1.0 / sample_index); vec4 acc_color = imageLoad(accumulation_image, ivec2(x, y)); diff --git a/src/main.cpp b/src/main.cpp index d0500e7..c2643ca 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -63,14 +63,14 @@ int main() { auto cam = camera(position, target, v_fov, (float)width / (float)height, aperture, focus_distance); auto main_scene = scene(cam, width, height); auto can_render = true; - vkrenderer renderer { wnd, sizeof(main_scene.meta), sizeof(main_scene.triangles[1]) * main_scene.triangles.size(), sizeof(main_scene.nodes[0]) * main_scene.nodes.size() }; + vkrenderer renderer { wnd, sizeof(main_scene.meta), sizeof(main_scene.triangles[1]) * main_scene.triangles.size(), sizeof(main_scene.packed_nodes[0]) * main_scene.packed_nodes.size() }; // vkrenderer renderer { wnd, sizeof(main_scene.meta), sizeof(main_scene.spheres[0]) * main_scene.spheres.size(), sizeof(main_scene.nodes[0]) * main_scene.nodes.size() }; // Upload scene content std::memcpy(renderer.scene_buffer_ptr(), &main_scene.meta, sizeof(main_scene.meta)); // std::memcpy(renderer.geometry_buffer_ptr(), main_scene.spheres.data(), sizeof(main_scene.spheres[0]) * main_scene.spheres.size()); std::memcpy(renderer.geometry_buffer_ptr(), main_scene.triangles.data(), sizeof(main_scene.triangles[0]) * main_scene.triangles.size()); - std::memcpy(renderer.bvh_buffer_ptr(), main_scene.nodes.data(), sizeof(main_scene.nodes[0]) * main_scene.nodes.size()); + std::memcpy(renderer.bvh_buffer_ptr(), main_scene.packed_nodes.data(), sizeof(main_scene.packed_nodes[0]) * main_scene.packed_nodes.size()); ImGuiIO& io = ImGui::GetIO(); io.DisplaySize.x = (float)width; diff --git a/src/scene.cpp b/src/scene.cpp index b44abd5..73c73e5 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -90,9 +90,7 @@ scene::scene(camera cam, uint32_t width, uint32_t height) // random_scene(); - bvh builder(triangles, nodes); + bvh builder(triangles, packed_nodes); // bvh builder(spheres, nodes); // builder.exporter(); - - std::memcpy(nodes.data(), builder.nodes.data(), sizeof(nodes[0]) * nodes.size()); } -- cgit v1.3