diff --git a/includes/RT/Scene.hpp b/includes/RT/Scene.hpp index b13c9bd..a931e10 100644 --- a/includes/RT/Scene.hpp +++ b/includes/RT/Scene.hpp @@ -19,10 +19,7 @@ struct GPUObject { alignas(16) glm::vec3 position; - alignas(16) glm::vec3 color; - float emission; - float roughness; - float metallic; + int mat_index; float radius; // sphere alignas(16) glm::vec3 normal; // plane @@ -33,6 +30,14 @@ struct GPUObject int type; }; +struct GPUMaterial +{ + alignas(16) glm::vec3 color; + float emission; + float roughness; + float metallic; +}; + class Sphere; class Camera; @@ -49,18 +54,21 @@ class Scene void updateGPUData(); - const std::vector &getGPUData() const; - Camera *getCamera(void) const; + const std::vector &getObjectData() const; + const std::vector &getMaterialData() const; + Camera *getCamera(void) const; Material *getMaterial(int material_index); private: - std::vector _objects; - std::vector _gpu_objects; + std::vector _objects; + std::vector _materials; - std::vector _materials; + std::vector _gpu_objects; + std::vector _gpu_materials; - Camera *_camera; + + Camera *_camera; }; #endif \ No newline at end of file diff --git a/shaders/compute.glsl b/shaders/compute.glsl index 4f44f37..7a117d8 100644 --- a/shaders/compute.glsl +++ b/shaders/compute.glsl @@ -7,10 +7,7 @@ layout(binding = 1, rgba32f) uniform image2D accumulation_image; struct GPUObject { vec3 position; // 12 + 4 - vec3 color; // 12 + 4 - float emission; // 4 - float roughness; // 4 - float metallic; // 4 + int mat_index; // 4 float radius; // 4 vec3 normal; // 12 + 4 @@ -21,11 +18,24 @@ struct GPUObject { int type; // 4 }; +struct GPUMaterial +{ + vec3 color; // 12 + 4 + float emission; // 4 + float roughness; // 4 + float metallic; // 4 +}; + layout(std430, binding = 1) buffer ObjectBuffer { GPUObject objects[]; }; +layout(std430, binding = 2) buffer MaterialBuffer +{ + GPUMaterial materials[]; +}; + uniform int u_objectsNum; uniform vec2 u_resolution; uniform vec3 u_cameraPosition; @@ -91,6 +101,7 @@ vec3 pathtrace(Ray ray, inout uint rng_state) } GPUObject obj = objects[hit.obj_index]; + GPUMaterial mat = materials[obj.mat_index]; // RR float p = max(color.r, max(color.g, color.b)); @@ -99,10 +110,10 @@ vec3 pathtrace(Ray ray, inout uint rng_state) color /= p; // - color *= obj.color; - light += obj.emission * obj.color; + color *= mat.color; + light += mat.emission * mat.color; - if (obj.emission > 0.0) + if (mat.emission > 0.0) break; ray = newRay(hit, ray, rng_state); diff --git a/shaders/scatter.glsl b/shaders/scatter.glsl index 2814668..3eda948 100644 --- a/shaders/scatter.glsl +++ b/shaders/scatter.glsl @@ -2,17 +2,19 @@ Ray newRay(hitInfo hit, Ray ray, inout uint rng_state) { GPUObject obj; + GPUMaterial mat; Ray new_ray; obj = objects[hit.obj_index]; - + mat = materials[obj.mat_index]; + vec3 diffuse_dir = normalize(hit.normal + randomDirection(rng_state)); vec3 specular_dir = reflect(ray.direction, hit.normal); - bool is_specular = (obj.metallic >= randomValue(rng_state)); + bool is_specular = (mat.metallic >= randomValue(rng_state)); new_ray.origin = hit.position + hit.normal * 0.001; - new_ray.direction = mix(diffuse_dir, specular_dir, obj.roughness * float(is_specular)); + new_ray.direction = mix(diffuse_dir, specular_dir, mat.roughness * float(is_specular)); return (new_ray); } \ No newline at end of file diff --git a/srcs/RT.cpp b/srcs/RT.cpp index 7d66f7c..e89e224 100644 --- a/srcs/RT.cpp +++ b/srcs/RT.cpp @@ -25,6 +25,9 @@ int main(int argc, char **argv) GLuint objectSSBO; glGenBuffers(1, &objectSSBO); + GLuint materialSSBO; + glGenBuffers(1, &materialSSBO); + shader.attach(); Vertex vertices[3] = {{{-1.0f, -1.0f}, {0.0f, 0.0f}},{{3.0f, -1.0f}, {2.0f, 0.0f}},{{-1.0f, 3.0f}, {0.0f, 2.0f}}}; @@ -34,19 +37,24 @@ int main(int argc, char **argv) GLint max_gpu_size; glGetIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &max_gpu_size); - const std::vector &gpu_data = scene.getGPUData(); - std::cout << "Sending " << gpu_data.size() << " objects for "<< gpu_data.size() * sizeof(GPUObject) << " / " << max_gpu_size << " bytes" << std::endl; + const std::vector &object_data = scene.getObjectData(); + const std::vector &material_data = scene.getMaterialData(); + std::cout << "Sending " << object_data.size() << " objects for "<< object_data.size() * sizeof(GPUObject) << " / " << max_gpu_size << " bytes" << std::endl; while (!window.shouldClose()) { glUseProgram(shader.getProgramCompute()); glBindBuffer(GL_SHADER_STORAGE_BUFFER, objectSSBO); - glBufferData(GL_SHADER_STORAGE_BUFFER, gpu_data.size() * sizeof(GPUObject), gpu_data.data(), GL_DYNAMIC_DRAW); + glBufferData(GL_SHADER_STORAGE_BUFFER, object_data.size() * sizeof(GPUObject), object_data.data(), GL_DYNAMIC_DRAW); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, objectSSBO); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, materialSSBO); + glBufferData(GL_SHADER_STORAGE_BUFFER, material_data.size() * sizeof(GPUMaterial), material_data.data(), GL_DYNAMIC_DRAW); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, materialSSBO); + shader.set_int("u_frameCount", window.getFrameCount()); - shader.set_int("u_objectsNum", gpu_data.size()); + shader.set_int("u_objectsNum", object_data.size()); shader.set_float("u_time", (float)(glfwGetTime())); shader.set_vec2("u_resolution", glm::vec2(WIDTH, HEIGHT)); shader.set_vec3("u_cameraPosition", scene.getCamera()->getPosition()); diff --git a/srcs/class/Scene.cpp b/srcs/class/Scene.cpp index 3668452..6feb349 100644 --- a/srcs/class/Scene.cpp +++ b/srcs/class/Scene.cpp @@ -64,20 +64,15 @@ void Scene::addMaterial(Material *material) void Scene::updateGPUData() { GPUObject gpu_obj; - Material *mat; + GPUMaterial gpu_mat; _gpu_objects.clear(); + _gpu_materials.clear(); + for (const auto& obj : _objects) { - mat = getMaterial(obj->getMaterialIndex()); - + gpu_obj.mat_index = obj->getMaterialIndex(); gpu_obj.position = obj->getPosition(); - - gpu_obj.color = mat->color; - gpu_obj.emission = mat->emission; - gpu_obj.roughness = mat->roughness; - gpu_obj.metallic = mat->metallic; - gpu_obj.type = static_cast(obj->getType()); if (obj->getType() == Object::Type::SPHERE) @@ -106,13 +101,27 @@ void Scene::updateGPUData() _gpu_objects.push_back(gpu_obj); } + for (const auto &material : _materials) + { + gpu_mat.color = material->color; + gpu_mat.emission = material->emission; + gpu_mat.roughness = material->roughness; + gpu_mat.metallic = material->metallic; + + _gpu_materials.push_back(gpu_mat); + } } -const std::vector& Scene::getGPUData() const +const std::vector& Scene::getObjectData() const { return (_gpu_objects); } +const std::vector& Scene::getMaterialData() const +{ + return (_gpu_materials); +} + Camera *Scene::getCamera(void) const { return (_camera);