+ | BVH Sah

This commit is contained in:
TheRedShip
2025-01-19 17:58:11 +01:00
parent 71df788350
commit 0ae411d8ea
6 changed files with 104 additions and 2703 deletions

2661
fps.txt

File diff suppressed because it is too large Load Diff

View File

@ -25,9 +25,18 @@ struct AABB
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 BVHStats {
struct BVHStats
{
int min_triangles;
int max_triangles;
float average_triangles;
@ -44,6 +53,8 @@ class BVH
void updateBounds(std::vector <GPUTriangle> &primitives);
void subdivide(std::vector<GPUTriangle> &primitives);
float evaluateSah(std::vector<GPUTriangle> &primitives, int axis, float pos);
int getSize();
int getLeaves();
BVHStats analyzeBVHLeaves(BVH* root);

View File

@ -24,7 +24,7 @@ pl 0 -2 0 0 1 0 2 // floor
qu -1 1.999 -1 2 0 0 0 0 2 6
OBJ obj/Dragon_80K.obj
OBJ obj/Dragon_800K.obj
# po -1.99 -0.5 -0.5 0 1 0 0 0 1 1 4
# po -0.5 -0.5 -1.99 0 1 0 1 0 0 0 4

View File

@ -85,20 +85,22 @@ layout(std430, binding = 2) buffer TriangleBuffer
GPUTriangle triangles[];
};
layout(std430, binding = 3) buffer MaterialBuffer
layout(std430, binding = 3) buffer BvhBuffer
{
GPUBvh bvh[];
};
layout(std430, binding = 4) buffer MaterialBuffer
{
GPUMaterial materials[];
};
layout(std430, binding = 4) buffer LightsBuffer
layout(std430, binding = 5) buffer LightsBuffer
{
int lightsIndex[];
};
layout(std430, binding = 5) buffer BvhBuffer
{
GPUBvh bvh[];
};
layout(std140, binding = 0) uniform CameraData

View File

@ -20,52 +20,53 @@ 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);
const std::vector<GPUObject> &object_data = scene.getObjectData();
const std::vector<GPUTriangle> &triangle_data = scene.getTriangleData();
const std::vector<GPUBvh> &bvh_data = scene.getBVH();
const std::vector<GPUMaterial> &material_data = scene.getMaterialData();
std::cout << "Sending " << object_data.size() << " objects for " << \
object_data.size() * sizeof(GPUObject) + \
triangle_data.size() * sizeof(GPUTriangle) + \
bvh_data.size() * sizeof(GPUBvh) + \
material_data.size() * sizeof(GPUMaterial) \
<< " / " << max_gpu_size << " bytes" << std::endl;
GLuint objectSSBO;
glGenBuffers(1, &objectSSBO);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, objectSSBO);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GPUObject) * object_data.size(), nullptr, GL_STATIC_DRAW);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GPUObject) * object_data.size(), object_data.data(), GL_STATIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, objectSSBO);
GLuint trianglesSSBO;
glGenBuffers(1, &trianglesSSBO);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, trianglesSSBO);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GPUTriangle) * triangle_data.size(), nullptr, GL_STATIC_DRAW);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GPUTriangle) * triangle_data.size(), triangle_data.data(), GL_STATIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, trianglesSSBO);
GLuint bvhSSBO;
glGenBuffers(1, &bvhSSBO);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, bvhSSBO);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GPUBvh) * bvh_data.size(), bvh_data.data(), GL_STATIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, bvhSSBO);
GLuint materialSSBO;
glGenBuffers(1, &materialSSBO);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, materialSSBO);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GPUMaterial) * material_data.size(), nullptr, GL_STATIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, materialSSBO);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, materialSSBO);
GLuint lightSSBO;
glGenBuffers(1, &lightSSBO);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, lightSSBO);
glBufferData(GL_SHADER_STORAGE_BUFFER, scene.getGPULights().size() * sizeof(int), nullptr, GL_STATIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, 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, 5, bvhSSBO);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, lightSSBO);
GLuint cameraUBO;
@ -99,13 +100,7 @@ int main(int argc, char **argv)
{
glUseProgram(shader.getProgramCompute());
glBindBuffer(GL_SHADER_STORAGE_BUFFER, objectSSBO);
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, object_data.size() * sizeof(GPUObject), object_data.data());
glBindBuffer(GL_SHADER_STORAGE_BUFFER, trianglesSSBO);
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, triangle_data.size() * sizeof(GPUTriangle), triangle_data.data());
glBindBuffer(GL_SHADER_STORAGE_BUFFER, materialSSBO);
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, material_data.size() * sizeof(GPUMaterial), material_data.data());
@ -113,16 +108,11 @@ int main(int argc, char **argv)
std::vector<int> gpu_lights_array(gpu_lights.begin(), gpu_lights.end());
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());
Camera *camera = scene.getCamera();
// performance profiling
if (true)
if (false)
{
float time = (float)(glfwGetTime()) ;
@ -161,7 +151,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_bvhNum", scene.getBVH().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

@ -44,26 +44,85 @@ void BVH::updateBounds(std::vector<GPUTriangle> &primitives)
}
}
float BVH::evaluateSah(std::vector<GPUTriangle> &primitives, 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 (unsigned int i = 0; i < _primitive_count; i++)
{
GPUTriangle triangle = primitives[_first_primitive + i];
glm::vec3 centroid = (triangle.position + triangle.vertex1 + triangle.vertex2) / 3.0f;
if (centroid[axis] < pos)
{
left_count++;
left_box.grow( triangle.position );
left_box.grow( triangle.vertex1 );
left_box.grow( triangle.vertex2 );
}
else
{
right_count++;
right_box.grow( triangle.position );
right_box.grow( triangle.vertex1 );
right_box.grow( triangle.vertex2 );
}
}
float cost = left_count * left_box.area() + right_count * right_box.area();
return (cost > 0 ? cost : 1e30f);
}
void BVH::subdivide(std::vector<GPUTriangle> &primitives)
{
if (_primitive_count <= 100)
if (_primitive_count <= 4)
return ;
glm::vec3 extent = _aabb.max - _aabb.min;
int axis = 0;
if (extent.y > extent.x) axis = 1;
if (extent.z > extent[axis]) axis = 2;
const int num_test_per_axis = 5;
float split_pos = _aabb.min[axis] + extent[axis] * 0.5f;
int best_axis = 0;
float best_pos = 0;
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(primitives, 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_primitive;
int j = _first_primitive + _primitive_count - 1;
while (i <= j)
{
glm::vec3 centroid = primitives[i].position + primitives[i].vertex1 + primitives[i].vertex2;
centroid /= 3.0f;
GPUTriangle triangle = primitives[i];
glm::vec3 centroid = (triangle.position + triangle.vertex1 + triangle.vertex2) / 3.0f;
if (centroid[axis] < split_pos)
i++;