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;
|
glm::vec3 max;
|
||||||
|
|
||||||
AABB(glm::vec3 min, glm::vec3 max) : min(min), max(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 min_triangles;
|
||||||
int max_triangles;
|
int max_triangles;
|
||||||
float average_triangles;
|
float average_triangles;
|
||||||
@ -44,6 +53,8 @@ class BVH
|
|||||||
void updateBounds(std::vector <GPUTriangle> &primitives);
|
void updateBounds(std::vector <GPUTriangle> &primitives);
|
||||||
void subdivide(std::vector<GPUTriangle> &primitives);
|
void subdivide(std::vector<GPUTriangle> &primitives);
|
||||||
|
|
||||||
|
float evaluateSah(std::vector<GPUTriangle> &primitives, int axis, float pos);
|
||||||
|
|
||||||
int getSize();
|
int getSize();
|
||||||
int getLeaves();
|
int getLeaves();
|
||||||
BVHStats analyzeBVHLeaves(BVH* root);
|
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
|
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 -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
|
# 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[];
|
GPUTriangle triangles[];
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(std430, binding = 3) buffer MaterialBuffer
|
layout(std430, binding = 3) buffer BvhBuffer
|
||||||
|
{
|
||||||
|
GPUBvh bvh[];
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std430, binding = 4) buffer MaterialBuffer
|
||||||
{
|
{
|
||||||
GPUMaterial materials[];
|
GPUMaterial materials[];
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(std430, binding = 4) buffer LightsBuffer
|
layout(std430, binding = 5) buffer LightsBuffer
|
||||||
{
|
{
|
||||||
int lightsIndex[];
|
int lightsIndex[];
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(std430, binding = 5) buffer BvhBuffer
|
|
||||||
{
|
|
||||||
GPUBvh bvh[];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
layout(std140, binding = 0) uniform CameraData
|
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);
|
return (1);
|
||||||
|
|
||||||
Window window(&scene, WIDTH, HEIGHT, "RT_GPU", 0);
|
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");
|
// Shader shader("shaders/vertex.vert", "shaders/frag.frag", "shaders/debug.glsl");
|
||||||
|
|
||||||
GLint max_gpu_size;
|
GLint max_gpu_size;
|
||||||
glGetIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &max_gpu_size);
|
glGetIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &max_gpu_size);
|
||||||
|
|
||||||
const std::vector<GPUObject> &object_data = scene.getObjectData();
|
const std::vector<GPUObject> &object_data = scene.getObjectData();
|
||||||
const std::vector<GPUTriangle> &triangle_data = scene.getTriangleData();
|
const std::vector<GPUTriangle> &triangle_data = scene.getTriangleData();
|
||||||
|
const std::vector<GPUBvh> &bvh_data = scene.getBVH();
|
||||||
const std::vector<GPUMaterial> &material_data = scene.getMaterialData();
|
const std::vector<GPUMaterial> &material_data = scene.getMaterialData();
|
||||||
|
|
||||||
std::cout << "Sending " << object_data.size() << " objects for " << \
|
std::cout << "Sending " << object_data.size() << " objects for " << \
|
||||||
object_data.size() * sizeof(GPUObject) + \
|
object_data.size() * sizeof(GPUObject) + \
|
||||||
triangle_data.size() * sizeof(GPUTriangle) + \
|
triangle_data.size() * sizeof(GPUTriangle) + \
|
||||||
|
bvh_data.size() * sizeof(GPUBvh) + \
|
||||||
material_data.size() * sizeof(GPUMaterial) \
|
material_data.size() * sizeof(GPUMaterial) \
|
||||||
<< " / " << max_gpu_size << " bytes" << std::endl;
|
<< " / " << max_gpu_size << " bytes" << std::endl;
|
||||||
|
|
||||||
GLuint objectSSBO;
|
GLuint objectSSBO;
|
||||||
glGenBuffers(1, &objectSSBO);
|
glGenBuffers(1, &objectSSBO);
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 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);
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, objectSSBO);
|
||||||
|
|
||||||
GLuint trianglesSSBO;
|
GLuint trianglesSSBO;
|
||||||
glGenBuffers(1, &trianglesSSBO);
|
glGenBuffers(1, &trianglesSSBO);
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 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);
|
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;
|
GLuint materialSSBO;
|
||||||
glGenBuffers(1, &materialSSBO);
|
glGenBuffers(1, &materialSSBO);
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, materialSSBO);
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, materialSSBO);
|
||||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GPUMaterial) * material_data.size(), nullptr, GL_STATIC_DRAW);
|
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;
|
GLuint lightSSBO;
|
||||||
glGenBuffers(1, &lightSSBO);
|
glGenBuffers(1, &lightSSBO);
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, lightSSBO);
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, lightSSBO);
|
||||||
glBufferData(GL_SHADER_STORAGE_BUFFER, scene.getGPULights().size() * sizeof(int), nullptr, GL_STATIC_DRAW);
|
glBufferData(GL_SHADER_STORAGE_BUFFER, scene.getGPULights().size() * sizeof(int), nullptr, GL_STATIC_DRAW);
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, lightSSBO);
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, 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);
|
|
||||||
|
|
||||||
|
|
||||||
GLuint cameraUBO;
|
GLuint cameraUBO;
|
||||||
@ -99,13 +100,7 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
|
|
||||||
glUseProgram(shader.getProgramCompute());
|
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);
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, materialSSBO);
|
||||||
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, material_data.size() * sizeof(GPUMaterial), material_data.data());
|
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());
|
std::vector<int> gpu_lights_array(gpu_lights.begin(), gpu_lights.end());
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, lightSSBO);
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, lightSSBO);
|
||||||
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, gpu_lights_array.size() * sizeof(int), gpu_lights_array.data());
|
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();
|
Camera *camera = scene.getCamera();
|
||||||
|
|
||||||
// performance profiling
|
// performance profiling
|
||||||
if (true)
|
if (false)
|
||||||
{
|
{
|
||||||
float time = (float)(glfwGetTime()) ;
|
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_frameCount", window.getFrameCount());
|
||||||
shader.set_int("u_objectsNum", object_data.size());
|
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_lightsNum", gpu_lights.size());
|
||||||
shader.set_int("u_pixelisation", window.getPixelisation());
|
shader.set_int("u_pixelisation", window.getPixelisation());
|
||||||
shader.set_float("u_time", (float)(glfwGetTime()));
|
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)
|
void BVH::subdivide(std::vector<GPUTriangle> &primitives)
|
||||||
{
|
{
|
||||||
if (_primitive_count <= 100)
|
if (_primitive_count <= 4)
|
||||||
return ;
|
return ;
|
||||||
|
|
||||||
glm::vec3 extent = _aabb.max - _aabb.min;
|
glm::vec3 extent = _aabb.max - _aabb.min;
|
||||||
|
|
||||||
int axis = 0;
|
const int num_test_per_axis = 5;
|
||||||
if (extent.y > extent.x) axis = 1;
|
|
||||||
if (extent.z > extent[axis]) axis = 2;
|
|
||||||
|
|
||||||
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 i = _first_primitive;
|
||||||
int j = _first_primitive + _primitive_count - 1;
|
int j = _first_primitive + _primitive_count - 1;
|
||||||
|
|
||||||
while (i <= j)
|
while (i <= j)
|
||||||
{
|
{
|
||||||
glm::vec3 centroid = primitives[i].position + primitives[i].vertex1 + primitives[i].vertex2;
|
GPUTriangle triangle = primitives[i];
|
||||||
centroid /= 3.0f;
|
glm::vec3 centroid = (triangle.position + triangle.vertex1 + triangle.vertex2) / 3.0f;
|
||||||
|
|
||||||
if (centroid[axis] < split_pos)
|
if (centroid[axis] < split_pos)
|
||||||
i++;
|
i++;
|
||||||
|
Reference in New Issue
Block a user