diff --git a/imgui.ini b/imgui.ini index fe07d99..c6c3f9e 100644 --- a/imgui.ini +++ b/imgui.ini @@ -29,6 +29,6 @@ Pos=1556,610 Size=284,382 [Window][Settings] -Pos=1582,12 +Pos=1616,42 Size=340,941 diff --git a/includes/RT/Shader.hpp b/includes/RT/Shader.hpp index 32c7624..07381a3 100644 --- a/includes/RT/Shader.hpp +++ b/includes/RT/Shader.hpp @@ -21,15 +21,19 @@ class Shader Shader(GLenum type, const std::string &file_path); ~Shader(void); + void compile(void); void reload(); + void setDefine(const std::string &name, const std::string &value); + GLuint getShader(void) const; private: void checkCompileErrors(); - // + std::map _defines; + GLenum _type; GLuint _shader_id; std::string _file_path; diff --git a/includes/RT/ShaderProgram.hpp b/includes/RT/ShaderProgram.hpp index 7863733..8a788b3 100644 --- a/includes/RT/ShaderProgram.hpp +++ b/includes/RT/ShaderProgram.hpp @@ -39,6 +39,8 @@ class ShaderProgram void set_textures(std::map> texture_ids); + void set_define(const std::string &name, const std::string &value); + GLuint getProgram(void) const; private: diff --git a/includes/RT/Window.hpp b/includes/RT/Window.hpp index e139ddf..15535a1 100644 --- a/includes/RT/Window.hpp +++ b/includes/RT/Window.hpp @@ -16,6 +16,7 @@ # include "RT.hpp" class Scene; +class ShaderProgram; class Window { @@ -35,7 +36,7 @@ class Window static void mouseButtonCallback(GLFWwindow *window, int button, int action, int mods); void imGuiNewFrame(); - void imGuiRender(); + void imGuiRender(ShaderProgram &raytracing_program); GLFWwindow *getWindow(void) const; float getFps(void) const; diff --git a/shaders/compute.glsl b/shaders/compute.glsl index c712094..9bbd2cd 100644 --- a/shaders/compute.glsl +++ b/shaders/compute.glsl @@ -1,278 +1,5 @@ -#version 430 core - -layout(local_size_x = 16, local_size_y = 16) in; -layout(binding = 0, rgba32f) uniform image2D output_image; -layout(binding = 1, rgba32f) uniform image2D accumulation_image; - -layout(binding = 3, rgba32f) uniform image2D normal_texture; -layout(binding = 4, rgba32f) uniform image2D position_texture; - -struct GPUObject { - mat4 rotation; - - vec3 position; // 12 + 4 - - vec3 normal; // 12 + 4 - - vec3 vertex1; // 12 + 4 - vec3 vertex2; // 12 + 4 - - float radius; // 4 - - int mat_index; // 4 - int type; // 4 -}; - -struct GPUTriangle -{ - vec3 position; - vec3 vertex1; - vec3 vertex2; - vec3 normal; - - vec2 texture_vertex1; - vec2 texture_vertex2; - vec2 texture_vertex3; - - int mat_index; -}; - -struct GPUMaterial -{ - vec3 color; // 12 + 4 - float emission; // 4 - float roughness; // 4 - float metallic; // 4 - float refraction; // 4 - int type; // 4 - int texture_index; // 4 - int emission_texture_index; // 4 -}; - -struct GPUCamera -{ - mat4 view_matrix; - vec3 position; - - float aperture_size; - float focus_distance; - float fov; - - int bounce; -}; - -struct GPUVolume -{ - vec3 sigma_a; // absorption coefficient - vec3 sigma_s; // scattering coefficient - vec3 sigma_t; // extinction coefficient - float g; // phase function parameter - int enabled; -}; - -struct GPUBvhData -{ - mat4 transform; - mat4 inv_transform; - vec3 offset; - float scale; - - int bvh_start_index; - int triangle_start_index; -}; - -struct GPUBvh -{ - vec3 min; - vec3 max; - - int index; - int primitive_count; -}; - -layout(std430, binding = 1) buffer ObjectBuffer -{ - GPUObject objects[]; -}; - -layout(std430, binding = 2) buffer TriangleBuffer -{ - GPUTriangle triangles[]; -}; - -layout(std430, binding = 3) buffer BvhDataBuffer -{ - GPUBvhData BvhData[]; -}; - -layout(std430, binding = 4) buffer BvhBuffer -{ - GPUBvh Bvh[]; -}; - -layout(std430, binding = 5) buffer MaterialBuffer -{ - GPUMaterial materials[]; -}; - -layout(std430, binding = 6) buffer LightsBuffer -{ - int lightsIndex[]; -}; - - - -layout(std140, binding = 0) uniform CameraData -{ - GPUCamera camera; -}; - -layout(std140, binding = 1) uniform VolumeData -{ - GPUVolume volume; -}; - - -uniform int u_objectsNum; -uniform int u_bvhNum; -uniform int u_lightsNum; -uniform vec2 u_resolution; -uniform int u_pixelisation; -uniform int u_frameCount; -uniform float u_time; - -struct Ray -{ - vec3 origin; - vec3 direction; - vec3 inv_direction; -}; - -struct hitInfo -{ - float t; - float last_t; - vec3 normal; - vec3 position; - - int obj_index; - int mat_index; - int obj_type; - - float u; - float v; -}; - -#include "shaders/random.glsl" -#include "shaders/intersect.glsl" -#include "shaders/scatter.glsl" -#include "shaders/light.glsl" -#include "shaders/volumetric.glsl" -#include "shaders/trace.glsl" - -vec3 pathtrace(Ray ray, inout uint rng_state) -{ - vec3 color = vec3(1.0); - vec3 light = vec3(0.0); - vec3 transmittance = vec3(1.0); - - for (int i = 0; i < camera.bounce; i++) - { - hitInfo hit = traceRay(ray); - - #if 0 - float t_scatter = 0.0; - bool scatter_valid = bool(volume.enabled != 0 && atmosScatter(hit, t_scatter, rng_state)); - if (scatter_valid) - { - calculateVolumetricLight(t_scatter, ray, color, light, transmittance, rng_state); - continue ; - } - #endif - - if (hit.obj_index == -1) - { - light += transmittance * GetEnvironmentLight(ray); - break; - } - - if (i == 0) - { - imageStore(normal_texture, ivec2(gl_GlobalInvocationID.xy), vec4(normalize(hit.normal), 1.0)); - imageStore(position_texture, ivec2(gl_GlobalInvocationID.xy), vec4(normalize(hit.position), 1.0)); - } - - float p = max(color.r, max(color.g, color.b)); - if (randomValue(rng_state) >= p) break; - color /= max(p, 0.001); - - GPUMaterial mat = materials[hit.mat_index]; - calculateLightColor(mat, hit, color, light, rng_state); - - if (mat.emission > 0.0 && mat.emission_texture_index == -1) - break; - - ray = newRay(hit, ray, rng_state); - ray.inv_direction = 1.0 / ray.direction; - } - - return color * light; -} - -Ray initRay(vec2 uv, inout uint rng_state) -{ - float focal_length = 1.0 / tan(radians(camera.fov) / 2.0); - - vec3 origin = camera.position; - vec3 view_space_ray = normalize(vec3(uv.x, uv.y, -focal_length)); - vec3 ray_direction = normalize((inverse(camera.view_matrix) * vec4(view_space_ray, 0.0)).xyz); - - vec3 right = vec3(camera.view_matrix[0][0], camera.view_matrix[1][0], camera.view_matrix[2][0]); - vec3 up = vec3(camera.view_matrix[0][1], camera.view_matrix[1][1], camera.view_matrix[2][1]); - - vec3 focal_point = origin + ray_direction * camera.focus_distance; - - float r = sqrt(randomValue(rng_state)); - float theta = 2.0 * M_PI * randomValue(rng_state); - vec2 lens_point = camera.aperture_size * r * vec2(cos(theta), sin(theta)); - - origin += right * lens_point.x + up * lens_point.y; - ray_direction = normalize(focal_point - origin); - - return (Ray(origin, ray_direction, 1.0 / ray_direction)); -} - -void main() -{ - ivec2 pixel_coords = ivec2(gl_GlobalInvocationID.xy); - if (pixel_coords.x >= int(u_resolution.x) || pixel_coords.y >= int(u_resolution.y)) - return; - - if (u_pixelisation != 1 && (uint(pixel_coords.x) % u_pixelisation != 0 || uint(pixel_coords.y) % u_pixelisation != 0)) - return; - - uint rng_state = uint(u_resolution.x) * uint(pixel_coords.y) + uint(pixel_coords.x); - rng_state = rng_state + u_frameCount * 719393; - - vec2 jitter = randomPointInCircle(rng_state) * 1; - - vec2 uv = ((vec2(pixel_coords) + jitter) / u_resolution) * 2.0 - 1.0; - uv.x *= u_resolution.x / u_resolution.y; - - Ray ray = initRay(uv, rng_state); - vec3 color = pathtrace(ray, rng_state); - - float blend = 1.0 / float(u_frameCount + 1); - vec4 accum = imageLoad(accumulation_image, pixel_coords); - accum.rgb = mix(accum.rgb, color, blend); - accum.a = 1.0; - - imageStore(accumulation_image, pixel_coords, accum); - - vec4 final_color = vec4(sqrt(accum.r), sqrt(accum.g), sqrt(accum.b), accum.a); - - for (int y = 0; y < u_pixelisation; y++) - for (int x = 0; x < u_pixelisation; x++) - imageStore(output_image, pixel_coords + ivec2(x, y), final_color); -} - +#if SHADER_DEBUG +#include "shaders/debug.glsl" +#else +#include "shaders/raytracing.glsl" +#endif \ No newline at end of file diff --git a/shaders/debug.glsl b/shaders/debug.glsl index 8385276..6c7e15f 100644 --- a/shaders/debug.glsl +++ b/shaders/debug.glsl @@ -1,5 +1,3 @@ -#version 430 core - layout(local_size_x = 16, local_size_y = 16) in; layout(binding = 0, rgba32f) uniform image2D output_image; diff --git a/shaders/denoising.glsl b/shaders/denoising.glsl index 1f94f62..0e5525d 100644 --- a/shaders/denoising.glsl +++ b/shaders/denoising.glsl @@ -1,11 +1,9 @@ -#version 430 core - layout(local_size_x = 16, local_size_y = 16) in; layout(binding = 0, rgba32f) uniform image2D read_texture; layout(binding = 2, rgba32f) uniform image2D write_texture; -layout(binding = 3, rgba32f) uniform image2D position_texture; -layout(binding = 4, rgba32f) uniform image2D normal_texture; +layout(binding = 3, rgba32f) uniform image2D normal_texture; +layout(binding = 4, rgba32f) uniform image2D position_texture; uniform vec2 u_resolution; @@ -20,7 +18,7 @@ void main() ivec2 pixel_coords = ivec2(gl_GlobalInvocationID.xy); if (pixel_coords.x >= int(u_resolution.x) || pixel_coords.y >= int(u_resolution.y)) return; - + int holes = int(pow(2, u_pass)); vec4 color_center = imageLoad(read_texture, pixel_coords); @@ -32,6 +30,7 @@ void main() float totalWeight = 0.; vec4 color = vec4(vec3(0.), 1.0); + for (int x = -2; x <= 2; x++) { for (int y = -2; y <= 2; y++) diff --git a/shaders/frag.frag b/shaders/frag.frag index b89b6c6..fd4524e 100644 --- a/shaders/frag.frag +++ b/shaders/frag.frag @@ -1,10 +1,9 @@ -#version 430 core in vec2 TexCoords; out vec4 FragColor; -layout (binding = 0, rgba32f) uniform image2D screenTexture; +uniform sampler2D screenTexture; void main() { - FragColor = imageLoad(screenTexture, ivec2(gl_FragCoord.xy)); - // FragColor = vec4(1.0, 0.0, 0.0, 1.0); + // FragColor = imageLoad(screenTexture, ivec2(gl_FragCoord.xy)); + FragColor = texture(screenTexture, TexCoords); } \ No newline at end of file diff --git a/shaders/raytracing.glsl b/shaders/raytracing.glsl new file mode 100644 index 0000000..668ccc5 --- /dev/null +++ b/shaders/raytracing.glsl @@ -0,0 +1,277 @@ + +layout(local_size_x = 16, local_size_y = 16) in; +layout(binding = 0, rgba32f) uniform image2D output_image; +layout(binding = 1, rgba32f) uniform image2D accumulation_image; + +layout(binding = 3, rgba32f) uniform image2D normal_texture; +layout(binding = 4, rgba32f) uniform image2D position_texture; + +struct GPUObject { + mat4 rotation; + + vec3 position; // 12 + 4 + + vec3 normal; // 12 + 4 + + vec3 vertex1; // 12 + 4 + vec3 vertex2; // 12 + 4 + + float radius; // 4 + + int mat_index; // 4 + int type; // 4 +}; + +struct GPUTriangle +{ + vec3 position; + vec3 vertex1; + vec3 vertex2; + vec3 normal; + + vec2 texture_vertex1; + vec2 texture_vertex2; + vec2 texture_vertex3; + + int mat_index; +}; + +struct GPUMaterial +{ + vec3 color; // 12 + 4 + float emission; // 4 + float roughness; // 4 + float metallic; // 4 + float refraction; // 4 + int type; // 4 + int texture_index; // 4 + int emission_texture_index; // 4 +}; + +struct GPUCamera +{ + mat4 view_matrix; + vec3 position; + + float aperture_size; + float focus_distance; + float fov; + + int bounce; +}; + +struct GPUVolume +{ + vec3 sigma_a; // absorption coefficient + vec3 sigma_s; // scattering coefficient + vec3 sigma_t; // extinction coefficient + float g; // phase function parameter + int enabled; +}; + +struct GPUBvhData +{ + mat4 transform; + mat4 inv_transform; + vec3 offset; + float scale; + + int bvh_start_index; + int triangle_start_index; +}; + +struct GPUBvh +{ + vec3 min; + vec3 max; + + int index; + int primitive_count; +}; + +layout(std430, binding = 1) buffer ObjectBuffer +{ + GPUObject objects[]; +}; + +layout(std430, binding = 2) buffer TriangleBuffer +{ + GPUTriangle triangles[]; +}; + +layout(std430, binding = 3) buffer BvhDataBuffer +{ + GPUBvhData BvhData[]; +}; + +layout(std430, binding = 4) buffer BvhBuffer +{ + GPUBvh Bvh[]; +}; + +layout(std430, binding = 5) buffer MaterialBuffer +{ + GPUMaterial materials[]; +}; + +layout(std430, binding = 6) buffer LightsBuffer +{ + int lightsIndex[]; +}; + + + +layout(std140, binding = 0) uniform CameraData +{ + GPUCamera camera; +}; + +layout(std140, binding = 1) uniform VolumeData +{ + GPUVolume volume; +}; + + +uniform int u_objectsNum; +uniform int u_bvhNum; +uniform int u_lightsNum; +uniform vec2 u_resolution; +uniform int u_pixelisation; +uniform int u_frameCount; +uniform float u_time; + +struct Ray +{ + vec3 origin; + vec3 direction; + vec3 inv_direction; +}; + +struct hitInfo +{ + float t; + float last_t; + vec3 normal; + vec3 position; + + int obj_index; + int mat_index; + int obj_type; + + float u; + float v; +}; + +#include "shaders/random.glsl" +#include "shaders/intersect.glsl" +#include "shaders/scatter.glsl" +#include "shaders/light.glsl" +#include "shaders/volumetric.glsl" +#include "shaders/trace.glsl" + +vec3 pathtrace(Ray ray, inout uint rng_state) +{ + vec3 color = vec3(1.0); + vec3 light = vec3(0.0); + vec3 transmittance = vec3(1.0); + + for (int i = 0; i < camera.bounce; i++) + { + hitInfo hit = traceRay(ray); + + #if SHADER_FOG + float t_scatter = 0.0; + bool scatter_valid = bool(volume.enabled != 0 && atmosScatter(hit, t_scatter, rng_state)); + if (scatter_valid) + { + calculateVolumetricLight(t_scatter, ray, color, light, transmittance, rng_state); + continue ; + } + #endif + + if (hit.obj_index == -1) + { + light += transmittance * GetEnvironmentLight(ray); + break; + } + + if (i == 0) + { + imageStore(normal_texture, ivec2(gl_GlobalInvocationID.xy), vec4(normalize(hit.normal), 1.0)); + imageStore(position_texture, ivec2(gl_GlobalInvocationID.xy), vec4(normalize(hit.position), 1.0)); + } + + float p = max(color.r, max(color.g, color.b)); + if (randomValue(rng_state) >= p) break; + color /= max(p, 0.001); + + GPUMaterial mat = materials[hit.mat_index]; + calculateLightColor(mat, hit, color, light, rng_state); + + if (mat.emission > 0.0 && mat.emission_texture_index == -1) + break; + + ray = newRay(hit, ray, rng_state); + ray.inv_direction = 1.0 / ray.direction; + } + + return color * light; +} + +Ray initRay(vec2 uv, inout uint rng_state) +{ + float focal_length = 1.0 / tan(radians(camera.fov) / 2.0); + + vec3 origin = camera.position; + vec3 view_space_ray = normalize(vec3(uv.x, uv.y, -focal_length)); + vec3 ray_direction = normalize((inverse(camera.view_matrix) * vec4(view_space_ray, 0.0)).xyz); + + vec3 right = vec3(camera.view_matrix[0][0], camera.view_matrix[1][0], camera.view_matrix[2][0]); + vec3 up = vec3(camera.view_matrix[0][1], camera.view_matrix[1][1], camera.view_matrix[2][1]); + + vec3 focal_point = origin + ray_direction * camera.focus_distance; + + float r = sqrt(randomValue(rng_state)); + float theta = 2.0 * M_PI * randomValue(rng_state); + vec2 lens_point = camera.aperture_size * r * vec2(cos(theta), sin(theta)); + + origin += right * lens_point.x + up * lens_point.y; + ray_direction = normalize(focal_point - origin); + + return (Ray(origin, ray_direction, 1.0 / ray_direction)); +} + +void main() +{ + ivec2 pixel_coords = ivec2(gl_GlobalInvocationID.xy); + if (pixel_coords.x >= int(u_resolution.x) || pixel_coords.y >= int(u_resolution.y)) + return; + + if (u_pixelisation != 1 && (uint(pixel_coords.x) % u_pixelisation != 0 || uint(pixel_coords.y) % u_pixelisation != 0)) + return; + + uint rng_state = uint(u_resolution.x) * uint(pixel_coords.y) + uint(pixel_coords.x); + rng_state = rng_state + u_frameCount * 719393; + + vec2 jitter = randomPointInCircle(rng_state) * 1; + + vec2 uv = ((vec2(pixel_coords) + jitter) / u_resolution) * 2.0 - 1.0; + uv.x *= u_resolution.x / u_resolution.y; + + Ray ray = initRay(uv, rng_state); + vec3 color = pathtrace(ray, rng_state); + + float blend = 1.0 / float(u_frameCount + 1); + vec4 accum = imageLoad(accumulation_image, pixel_coords); + accum.rgb = mix(accum.rgb, color, blend); + accum.a = 1.0; + + imageStore(accumulation_image, pixel_coords, accum); + + vec4 final_color = vec4(sqrt(accum.r), sqrt(accum.g), sqrt(accum.b), accum.a); + + for (int y = 0; y < u_pixelisation; y++) + for (int x = 0; x < u_pixelisation; x++) + imageStore(output_image, pixel_coords + ivec2(x, y), final_color); +} + diff --git a/shaders/vertex.vert b/shaders/vertex.vert index 4c038e7..078500c 100644 --- a/shaders/vertex.vert +++ b/shaders/vertex.vert @@ -1,4 +1,3 @@ -#version 430 core layout(location = 0) in vec2 aPos; layout(location = 1) in vec2 aTexCoord; diff --git a/srcs/RT.cpp b/srcs/RT.cpp index ffe8a70..ae1cdc5 100644 --- a/srcs/RT.cpp +++ b/srcs/RT.cpp @@ -18,6 +18,32 @@ std::vector generateTextures(unsigned int textures_count); std::vector createDataOnGPU(Scene &scene); void updateDataOnGPU(Scene &scene, std::vector buffers); +void shaderDenoise(ShaderProgram &denoising_program, GPUDenoise &denoise, std::vector textures) +{ + denoising_program.use(); + + denoising_program.set_vec2("u_resolution", glm::vec2(WIDTH, HEIGHT)); + denoising_program.set_float("u_c_phi", denoise.c_phi); + denoising_program.set_float("u_p_phi", denoise.p_phi); + denoising_program.set_float("u_n_phi", denoise.n_phi); + + int output_texture = 0; + int denoising_texture = 2; + + for (int pass = 0; pass < denoise.pass ; ++pass) + { + glBindImageTexture(0, textures[output_texture], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); + glBindImageTexture(2, textures[denoising_texture], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); + + denoising_program.set_int("u_pass", pass); + denoising_program.dispathCompute((WIDTH + 15) / 16, (HEIGHT + 15) / 16, 1); + + std::swap(output_texture, denoising_texture); + } + + glBindImageTexture(0, textures[output_texture], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); +} + int main(int argc, char **argv) { Arguments args(argc, argv); @@ -33,20 +59,21 @@ int main(int argc, char **argv) GLuint VAO; setupScreenTriangle(&VAO); - std::vector textures = generateTextures(2); - GLuint output_texture = textures[0]; + std::vector textures = generateTextures(5); ShaderProgram raytracing_program; Shader compute = Shader(GL_COMPUTE_SHADER, "shaders/compute.glsl"); - Shader debug = Shader(GL_COMPUTE_SHADER, "shaders/debug.glsl"); - raytracing_program.attachShader(&compute); raytracing_program.link(); + ShaderProgram denoising_program; + Shader denoise = Shader(GL_COMPUTE_SHADER, "shaders/denoising.glsl"); + denoising_program.attachShader(&denoise); + denoising_program.link(); + ShaderProgram render_program; Shader vertex = Shader(GL_VERTEX_SHADER, "shaders/vertex.vert"); Shader frag = Shader(GL_FRAGMENT_SHADER, "shaders/frag.frag"); - render_program.attachShader(&vertex); render_program.attachShader(&frag); render_program.link(); @@ -62,15 +89,6 @@ int main(int argc, char **argv) glClear(GL_COLOR_BUFFER_BIT); updateDataOnGPU(scene, buffers); - - if (scene.getDebug().enabled) - { - raytracing_program.clearShaders(); - - raytracing_program.attachShader(&debug); - raytracing_program.link(); - scene.getDebug().enabled = 0; - } raytracing_program.use(); raytracing_program.set_int("u_frameCount", window.getFrameCount()); @@ -88,15 +106,21 @@ int main(int argc, char **argv) raytracing_program.dispathCompute((WIDTH + 15) / 16, (HEIGHT + 15) / 16, 1); + if (scene.getDenoise().enabled) + shaderDenoise(denoising_program, scene.getDenoise(), textures); + window.imGuiNewFrame(); render_program.use(); - drawScreenTriangle(VAO, output_texture, render_program.getProgram()); + drawScreenTriangle(VAO, textures[0], render_program.getProgram()); - window.imGuiRender(); + window.imGuiRender(raytracing_program); window.display(); window.pollEvents(); + + glClearTexImage(textures[3], 0, GL_RGBA, GL_FLOAT, nullptr); + glClearTexImage(textures[4], 0, GL_RGBA, GL_FLOAT, nullptr); } ImGui_ImplOpenGL3_Shutdown(); diff --git a/srcs/class/Shader.cpp b/srcs/class/Shader.cpp index 13b62af..1e90182 100644 --- a/srcs/class/Shader.cpp +++ b/srcs/class/Shader.cpp @@ -16,12 +16,12 @@ #include #include -const char *loadFileWithIncludes(const std::string& path) +std::stringstream loadFileWithIncludes(const std::string& path) { std::ifstream file(path); if (!file.is_open()) { std::cerr << "Failed to open file: " << path << std::endl; - return ""; + return std::stringstream(); } std::stringstream fileContent; @@ -36,7 +36,7 @@ const char *loadFileWithIncludes(const std::string& path) if (start != std::string::npos && end != std::string::npos && end > start) { std::string includePath = line.substr(start + 1, end - start - 1); - std::string includedContent = loadFileWithIncludes(includePath); + std::string includedContent = loadFileWithIncludes(includePath).str(); fileContent << includedContent << "\n"; } } @@ -44,7 +44,7 @@ const char *loadFileWithIncludes(const std::string& path) fileContent << line << "\n"; } - return strdup(fileContent.str().c_str()); + return fileContent; } @@ -78,10 +78,16 @@ void Shader::compile() { _shader_id = glCreateShader(_type); - const char *shader_code = loadFileWithIncludes(_file_path); - // printWithLineNumbers(shader_code); + std::string shader_code = loadFileWithIncludes(_file_path).str(); - glShaderSource(_shader_id, 1, &shader_code, NULL); + for (auto &define : _defines) + shader_code = "#define SHADER_" + define.first + " " + define.second + "\n" + shader_code; + shader_code = "#version 430\n" + shader_code; + + const char *shader_code_cstr = shader_code.c_str(); + // printWithLineNumbers(shader_code_cstr); + + glShaderSource(_shader_id, 1, &shader_code_cstr, NULL); glCompileShader(_shader_id); this->checkCompileErrors(); @@ -106,6 +112,11 @@ void Shader::checkCompileErrors() } } +void Shader::setDefine(const std::string &name, const std::string &value) +{ + _defines[name] = value; +} + GLuint Shader::getShader(void) const { return (_shader_id); diff --git a/srcs/class/ShaderProgram.cpp b/srcs/class/ShaderProgram.cpp index 1b00c7e..0d4f81c 100644 --- a/srcs/class/ShaderProgram.cpp +++ b/srcs/class/ShaderProgram.cpp @@ -115,6 +115,12 @@ void ShaderProgram::set_textures(std::map> text } } +void ShaderProgram::set_define(const std::string &name, const std::string &value) +{ + for (Shader *shader : _shaders) + shader->setDefine(name, value); +} + GLuint ShaderProgram::getProgram(void) const { return (_program); diff --git a/srcs/class/Window.cpp b/srcs/class/Window.cpp index 11de6d7..c71008c 100644 --- a/srcs/class/Window.cpp +++ b/srcs/class/Window.cpp @@ -184,7 +184,7 @@ void Window::imGuiNewFrame() ImGui::NewFrame(); } -void Window::imGuiRender() +void Window::imGuiRender(ShaderProgram &raytracing_program) { bool has_changed = false; @@ -253,7 +253,12 @@ void Window::imGuiRender() if (ImGui::CollapsingHeader("Fog")) { - has_changed |= ImGui::Checkbox("Enable", (bool *)(&_scene->getVolume().enabled)); + if (ImGui::Checkbox("Enable", (bool *)(&_scene->getVolume().enabled))) + { + raytracing_program.set_define("FOG", std::to_string(_scene->getVolume().enabled)); + raytracing_program.reloadShaders(); + has_changed = true; + } ImGui::Separator(); if (ImGui::SliderFloat("Absorption", &_scene->getVolume().sigma_a.x, 0., 0.1)) @@ -292,7 +297,12 @@ void Window::imGuiRender() { ImGui::PushID(0); - has_changed |= ImGui::Checkbox("Enable", (bool *)(&_scene->getDebug().enabled)); + if (ImGui::Checkbox("Enable", (bool *)(&_scene->getDebug().enabled))) + { + raytracing_program.set_define("DEBUG", std::to_string(_scene->getDebug().enabled)); + raytracing_program.reloadShaders(); + has_changed = true; + } ImGui::Separator(); has_changed |= ImGui::SliderInt("Debug mode", &_scene->getDebug().mode, 0, 2); has_changed |= ImGui::SliderInt("Box treshold", &_scene->getDebug().box_treshold, 1, 2000);