diff --git a/includes/RT.hpp b/includes/RT.hpp index 8cecaa2..15b6ee8 100644 --- a/includes/RT.hpp +++ b/includes/RT.hpp @@ -38,6 +38,7 @@ # include # include # include +# include # include struct Vertex { diff --git a/includes/RT/Scene.hpp b/includes/RT/Scene.hpp index 93c0021..45dd7ad 100644 --- a/includes/RT/Scene.hpp +++ b/includes/RT/Scene.hpp @@ -67,6 +67,9 @@ class Scene void addObject(Object *object); void addMaterial(Material *material); + + void updateLightAndObjects(int mat_id); + std::set getGPULights(); const std::vector &getObjectData() const; std::vector &getMaterialData(); @@ -79,6 +82,8 @@ class Scene std::vector _gpu_objects; std::vector _gpu_materials; + std::set _gpu_lights; + GPUVolume _gpu_volume; Camera *_camera; diff --git a/scenes/test.rt b/scenes/test.rt index 4a0bf69..198c3a3 100644 --- a/scenes/test.rt +++ b/scenes/test.rt @@ -27,4 +27,4 @@ sp 0 1 5 1 7 cy 0 1 2 0.5 2 -1.5 0 0.75 1 -OBJ obj/Lowpoly_tree_sample.obj +# OBJ obj/Lowpoly_tree_sample.obj diff --git a/shaders/compute.glsl b/shaders/compute.glsl index 4bdc459..4f1bce4 100644 --- a/shaders/compute.glsl +++ b/shaders/compute.glsl @@ -61,6 +61,12 @@ layout(std430, binding = 2) buffer MaterialBuffer GPUMaterial materials[]; }; +layout(std430, binding = 3) buffer LightsBuffer +{ + int lightsIndex[]; +}; + + layout(std140, binding = 0) uniform CameraData { GPUCamera camera; @@ -71,7 +77,9 @@ layout(std140, binding = 1) uniform VolumeData GPUVolume volume; }; + uniform int u_objectsNum; +uniform int u_lightsNum; uniform vec2 u_resolution; uniform int u_pixelisation; uniform int u_frameCount; diff --git a/shaders/light.glsl b/shaders/light.glsl index 6dc902d..987574b 100644 --- a/shaders/light.glsl +++ b/shaders/light.glsl @@ -71,9 +71,10 @@ vec3 sampleLights(vec3 position, inout uint rng_state) { vec3 light = vec3(0.0); - for (int i = 0; i < u_objectsNum; i++) + for (int i = 0; i < u_lightsNum; i++) { - GPUObject obj = objects[i]; + int light_index = lightsIndex[i]; + GPUObject obj = objects[light_index]; GPUMaterial mat = materials[obj.mat_index]; if (mat.emission > 0.0) { @@ -83,7 +84,7 @@ vec3 sampleLights(vec3 position, inout uint rng_state) Ray shadow_ray = Ray(position + light_dir * 0.01, light_dir); hitInfo shadow_hit = traceRay(shadow_ray); - if (shadow_hit.obj_index == i) + if (shadow_hit.obj_index == light_index) light += mat.emission * mat.color / (light_dist); } } @@ -116,6 +117,6 @@ vec3 sampleLights(vec3 position, inout uint rng_state) void calculateLightColor(GPUMaterial mat, hitInfo hit, inout vec3 color, inout vec3 light, inout uint rng_state) { color *= mat.color; - light += mat.emission * mat.color; - // light += sampleLights(hit.position, rng_state); + // light += mat.emission * mat.color; + light += sampleLights(hit.position, rng_state); } \ No newline at end of file diff --git a/srcs/RT.cpp b/srcs/RT.cpp index bcb0b45..62d5e6f 100644 --- a/srcs/RT.cpp +++ b/srcs/RT.cpp @@ -44,6 +44,14 @@ int main(int argc, char **argv) glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GPUMaterial) * material_data.size(), nullptr, GL_STATIC_DRAW); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, 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, 3, lightSSBO); + + GLuint cameraUBO; glGenBuffers(1, &cameraUBO); glBindBuffer(GL_UNIFORM_BUFFER, cameraUBO); @@ -56,6 +64,7 @@ int main(int argc, char **argv) glBufferData(GL_UNIFORM_BUFFER, sizeof(GPUVolume), nullptr, GL_STATIC_DRAW); glBindBufferBase(GL_UNIFORM_BUFFER, 1, volumeUBO); + 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}}}; @@ -72,6 +81,11 @@ int main(int argc, char **argv) glBindBuffer(GL_SHADER_STORAGE_BUFFER, materialSSBO); glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, material_data.size() * sizeof(GPUMaterial), material_data.data()); + std::set gpu_lights = scene.getGPULights(); + std::vector 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()); + GPUCamera camera_data = scene.getCamera()->getGPUData(); glBindBuffer(GL_UNIFORM_BUFFER, cameraUBO); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(GPUCamera), &camera_data); @@ -79,12 +93,14 @@ int main(int argc, char **argv) glBindBuffer(GL_UNIFORM_BUFFER, volumeUBO); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(GPUVolume), &scene.getVolume()); + shader.set_int("u_frameCount", window.getFrameCount()); shader.set_int("u_objectsNum", object_data.size()); + shader.set_int("u_lightsNum", gpu_lights.size()); shader.set_int("u_pixelisation", window.getPixelisation()); shader.set_float("u_time", (float)(glfwGetTime())); shader.set_vec2("u_resolution", glm::vec2(WIDTH, HEIGHT)); - + glDispatchCompute((WIDTH + 15) / 16, (HEIGHT + 15) / 16, 1); glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); diff --git a/srcs/class/Scene.cpp b/srcs/class/Scene.cpp index 4f3478c..eafb359 100644 --- a/srcs/class/Scene.cpp +++ b/srcs/class/Scene.cpp @@ -139,6 +139,27 @@ void Scene::addMaterial(Material *material) _gpu_materials.push_back(gpu_mat); } +void Scene::updateLightAndObjects(int mat_id) +{ + for (unsigned int i = 0; i < _gpu_objects.size(); i++) + { + if (_gpu_objects[i].mat_index == mat_id) + _gpu_lights.insert(i); + } + for (auto it = _gpu_lights.begin(); it != _gpu_lights.end(); ) + { + if (_gpu_materials[_gpu_objects[*it].mat_index].emission <= 0.0) + it = _gpu_lights.erase(it); + else + ++it; + } +} + +std::set Scene::getGPULights() +{ + return (_gpu_lights); +} + const std::vector& Scene::getObjectData() const { return (_gpu_objects); diff --git a/srcs/class/SceneParser.cpp b/srcs/class/SceneParser.cpp index efd309c..0b0da61 100644 --- a/srcs/class/SceneParser.cpp +++ b/srcs/class/SceneParser.cpp @@ -257,12 +257,16 @@ bool SceneParser::parseLine(const std::string &line) if (it != object_parsers.end()) { Object *obj = it->second(ss); - (void) _scene->getMaterial(obj->getMaterialIndex()); //verify material + + GPUMaterial mat = _scene->getMaterial(obj->getMaterialIndex()); //verify material if (obj->getType() == Object::Type::PORTAL) _scene->addObject(static_cast(obj)->createSupportQuad()); _scene->addObject(obj); + + if (mat.emission > 0.0) + _scene->updateLightAndObjects(obj->getMaterialIndex()); } if (identifier == "MAT") diff --git a/srcs/class/Window.cpp b/srcs/class/Window.cpp index 1f930c3..1e5f34f 100644 --- a/srcs/class/Window.cpp +++ b/srcs/class/Window.cpp @@ -197,7 +197,11 @@ void Window::imGuiRender() ImGui::Text("Material %d", i); has_changed |= ImGui::ColorEdit3("Color", &mat.color[0]); - has_changed |= ImGui::SliderFloat("Emission", &mat.emission, 0.0f, 10.0f); + if (ImGui::SliderFloat("Emission", &mat.emission, 0.0f, 10.0f)) + { + has_changed = 1; + _scene->updateLightAndObjects(i); + } if (mat.type == 0) {