mirror of
https://github.com/TheRedShip/RT_GPU.git
synced 2025-09-27 18:48:36 +02:00
+ | BVH Sah
This commit is contained in:
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
44
srcs/RT.cpp
44
srcs/RT.cpp
@ -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()));
|
||||
|
@ -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++;
|
||||
|
Reference in New Issue
Block a user