Commit: 5ee116d4489ae9d6cbef4acec75f5bf12a5adcd7 Author: Omar Emara Date: Fri Dec 9 17:04:34 2022 +0200 Branches: master https://developer.blender.org/rB5ee116d4489ae9d6cbef4acec75f5bf12a5adcd7
Realtime Compositor: Implement Simple Star Glare node This patch implements the Simple Star Glare node. This is only an approximation of the existing implementation in the CPU compositor, an approximation that removes the row-column dependency in the original algorithm, yielding an order of magnitude faster computations. The difference due to the approximation is readily visible in artificial test cases, but is less visible in actual use cases, so it was agreed that this approximation is worthwhile. For the future, we can look into approximating this further using a closed form IIR recursive filter with parallel interconnection and block-based parallelism. Which is expected to yield another order of magnitude faster computations. The different passes can potentially be combined into a single shader with some preprocessor tricks, but doing that complicated that code in a way that makes it difficult to experiment with future optimizations, so I decided to leave it as is for now. Differential Revision: https://developer.blender.org/D16724 Reviewed By: Clement Foucault =================================================================== M source/blender/compositor/realtime_compositor/CMakeLists.txt A source/blender/compositor/realtime_compositor/shaders/compositor_glare_simple_star_anti_diagonal_pass.glsl A source/blender/compositor/realtime_compositor/shaders/compositor_glare_simple_star_diagonal_pass.glsl A source/blender/compositor/realtime_compositor/shaders/compositor_glare_simple_star_horizontal_pass.glsl A source/blender/compositor/realtime_compositor/shaders/compositor_glare_simple_star_vertical_pass.glsl M source/blender/compositor/realtime_compositor/shaders/infos/compositor_glare_info.hh A source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_image_diagonals.glsl M source/blender/nodes/composite/nodes/node_composite_glare.cc =================================================================== diff --git a/source/blender/compositor/realtime_compositor/CMakeLists.txt b/source/blender/compositor/realtime_compositor/CMakeLists.txt index 7d7448a448f..0881982c6d3 100644 --- a/source/blender/compositor/realtime_compositor/CMakeLists.txt +++ b/source/blender/compositor/realtime_compositor/CMakeLists.txt @@ -102,6 +102,10 @@ set(GLSL_SRC shaders/compositor_glare_ghost_base.glsl shaders/compositor_glare_highlights.glsl shaders/compositor_glare_mix.glsl + shaders/compositor_glare_simple_star_anti_diagonal_pass.glsl + shaders/compositor_glare_simple_star_diagonal_pass.glsl + shaders/compositor_glare_simple_star_horizontal_pass.glsl + shaders/compositor_glare_simple_star_vertical_pass.glsl shaders/compositor_image_crop.glsl shaders/compositor_morphological_distance.glsl shaders/compositor_morphological_distance_feather.glsl @@ -135,6 +139,7 @@ set(GLSL_SRC shaders/library/gpu_shader_compositor_gamma.glsl shaders/library/gpu_shader_compositor_hue_correct.glsl shaders/library/gpu_shader_compositor_hue_saturation_value.glsl + shaders/library/gpu_shader_compositor_image_diagonals.glsl shaders/library/gpu_shader_compositor_invert.glsl shaders/library/gpu_shader_compositor_luminance_matte.glsl shaders/library/gpu_shader_compositor_main.glsl diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_glare_simple_star_anti_diagonal_pass.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_glare_simple_star_anti_diagonal_pass.glsl new file mode 100644 index 00000000000..7cfec6c4d95 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_glare_simple_star_anti_diagonal_pass.glsl @@ -0,0 +1,55 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_image_diagonals.glsl) +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +void main() +{ + ivec2 size = imageSize(anti_diagonal_img); + int index = int(gl_GlobalInvocationID.x); + int anti_diagonal_length = compute_anti_diagonal_length(size, index); + ivec2 start = compute_anti_diagonal_start(size, index); + ivec2 direction = get_anti_diagonal_direction(); + ivec2 end = start + (anti_diagonal_length - 1) * direction; + + /* For each iteration, apply a causal filter followed by a non causal filters along the anti + * diagonal mapped to the current thread invocation. */ + for (int i = 0; i < iterations; i++) { + /* Causal Pass: + * Sequentially apply a causal filter running from the start of the anti diagonal to its end by + * mixing the value of the pixel in the anti diagonal with the average value of the previous + * output and next input in the same anti diagonal. */ + for (int j = 0; j < anti_diagonal_length; j++) { + ivec2 texel = start + j * direction; + vec4 previous_output = imageLoad(anti_diagonal_img, texel - i * direction); + vec4 current_input = imageLoad(anti_diagonal_img, texel); + vec4 next_input = imageLoad(anti_diagonal_img, texel + i * direction); + + vec4 neighbour_average = (previous_output + next_input) / 2.0; + vec4 causal_output = mix(current_input, neighbour_average, fade_factor); + imageStore(anti_diagonal_img, texel, causal_output); + } + + /* Non Causal Pass: + * Sequentially apply a non causal filter running from the end of the diagonal to its start by + * mixing the value of the pixel in the diagonal with the average value of the previous output + * and next input in the same diagonal. */ + for (int j = 0; j < anti_diagonal_length; j++) { + ivec2 texel = end - j * direction; + vec4 previous_output = imageLoad(anti_diagonal_img, texel + i * direction); + vec4 current_input = imageLoad(anti_diagonal_img, texel); + vec4 next_input = imageLoad(anti_diagonal_img, texel - i * direction); + + vec4 neighbour_average = (previous_output + next_input) / 2.0; + vec4 non_causal_output = mix(current_input, neighbour_average, fade_factor); + imageStore(anti_diagonal_img, texel, non_causal_output); + } + } + + /* For each pixel in the anti diagonal mapped to the current invocation thread, add the result of + * the diagonal pass to the vertical pass. */ + for (int j = 0; j < anti_diagonal_length; j++) { + ivec2 texel = start + j * direction; + vec4 horizontal = texture_load(diagonal_tx, texel); + vec4 vertical = imageLoad(anti_diagonal_img, texel); + imageStore(anti_diagonal_img, texel, horizontal + vertical); + } +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_glare_simple_star_diagonal_pass.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_glare_simple_star_diagonal_pass.glsl new file mode 100644 index 00000000000..c8a703ae67c --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_glare_simple_star_diagonal_pass.glsl @@ -0,0 +1,45 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_image_diagonals.glsl) + +void main() +{ + ivec2 size = imageSize(diagonal_img); + int index = int(gl_GlobalInvocationID.x); + int diagonal_length = compute_diagonal_length(size, index); + ivec2 start = compute_diagonal_start(size, index); + ivec2 direction = get_diagonal_direction(); + ivec2 end = start + (diagonal_length - 1) * direction; + + /* For each iteration, apply a causal filter followed by a non causal filters along the diagonal + * mapped to the current thread invocation. */ + for (int i = 0; i < iterations; i++) { + /* Causal Pass: + * Sequentially apply a causal filter running from the start of the diagonal to its end by + * mixing the value of the pixel in the diagonal with the average value of the previous output + * and next input in the same diagonal. */ + for (int j = 0; j < diagonal_length; j++) { + ivec2 texel = start + j * direction; + vec4 previous_output = imageLoad(diagonal_img, texel - i * direction); + vec4 current_input = imageLoad(diagonal_img, texel); + vec4 next_input = imageLoad(diagonal_img, texel + i * direction); + + vec4 neighbour_average = (previous_output + next_input) / 2.0; + vec4 causal_output = mix(current_input, neighbour_average, fade_factor); + imageStore(diagonal_img, texel, causal_output); + } + + /* Non Causal Pass: + * Sequentially apply a non causal filter running from the end of the diagonal to its start by + * mixing the value of the pixel in the diagonal with the average value of the previous output + * and next input in the same diagonal. */ + for (int j = 0; j < diagonal_length; j++) { + ivec2 texel = end - j * direction; + vec4 previous_output = imageLoad(diagonal_img, texel + i * direction); + vec4 current_input = imageLoad(diagonal_img, texel); + vec4 next_input = imageLoad(diagonal_img, texel - i * direction); + + vec4 neighbour_average = (previous_output + next_input) / 2.0; + vec4 non_causal_output = mix(current_input, neighbour_average, fade_factor); + imageStore(diagonal_img, texel, non_causal_output); + } + } +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_glare_simple_star_horizontal_pass.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_glare_simple_star_horizontal_pass.glsl new file mode 100644 index 00000000000..94d935a4c1d --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_glare_simple_star_horizontal_pass.glsl @@ -0,0 +1,38 @@ +void main() +{ + int width = imageSize(horizontal_img).x; + + /* For each iteration, apply a causal filter followed by a non causal filters along the row + * mapped to the current thread invocation. */ + for (int i = 0; i < iterations; i++) { + /* Causal Pass: + * Sequentially apply a causal filter running from left to right by mixing the value of the + * pixel in the row with the average value of the previous output and next input in the same + * row. */ + for (int x = 0; x < width; x++) { + ivec2 texel = ivec2(x, gl_GlobalInvocationID.x); + vec4 previous_output = imageLoad(horizontal_img, texel - ivec2(i, 0)); + vec4 current_input = imageLoad(horizontal_img, texel); + vec4 next_input = imageLoad(horizontal_img, texel + ivec2(i, 0)); + + vec4 neighbour_average = (previous_output + next_input) / 2.0; + vec4 causal_output = mix(current_input, neighbour_average, fade_factor); + imageStore(horizontal_img, texel, causal_output); + } + + /* Non Causal Pass: + * Sequentially apply a non causal filter running from right to left by mixing the value of the + * pixel in the row with the average value of the previous output and next input in the same + * row. */ + for (int x = width - 1; x >= 0; x--) { + ivec2 texel = ivec2(x, gl_GlobalInvocationID.x); + vec4 previous_output = imageLoad(horizontal_img, texel + ivec2(i, 0)); + vec4 current_input = imageLoad(horizontal_img, texel); + vec4 next_input = imageLoad(horizontal_img, texel - ivec2(i, 0)); + + vec4 neighbour_average = (previous_output + next_input) / 2.0; + vec4 non_causal_output = mix(current_input, neighbour_average, fade_factor); + imageStore(horizontal_img, texel, non_causal_output); + } + } +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_glare_simple_star_vertical_pass.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_glare_simple_star_vertical_pass.glsl new file mode 100644 index 00000000000..abc92883c17 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_glare_simple_star_vertical_pass.glsl @@ -0,0 +1,49 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +void main() +{ + int height = imageSize(vertical_img).y; + + /* For each iteration, apply a causal filter followed by a non causal filters along the column + * mapped to the current thread invocation. */ + for (int i = 0; i < iterations; i++) { + /* Causal Pass: + * Sequentially apply a causal filter running from bottom to top by mixing the value of the + * pixel in the column with the average value of the previous output and next input @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list [email protected] List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs
