diff options
Diffstat (limited to 'source/blender/compositor/realtime_compositor/shaders/library')
27 files changed, 820 insertions, 0 deletions
diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_alpha_over.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_alpha_over.glsl new file mode 100644 index 00000000000..8e3e033147f --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_alpha_over.glsl @@ -0,0 +1,48 @@ +void node_composite_alpha_over_mixed( + float factor, vec4 color, vec4 over_color, float premultiply_factor, out vec4 result) +{ + if (over_color.a <= 0.0) { + result = color; + } + else if (factor == 1.0 && over_color.a >= 1.0) { + result = over_color; + } + else { + float add_factor = 1.0 - premultiply_factor + over_color.a * premultiply_factor; + float premultiplier = factor * add_factor; + float multiplier = 1.0 - factor * over_color.a; + + result = multiplier * color + vec2(premultiplier, factor).xxxy * over_color; + } +} + +void node_composite_alpha_over_key(float factor, vec4 color, vec4 over_color, out vec4 result) +{ + if (over_color.a <= 0.0) { + result = color; + } + else if (factor == 1.0 && over_color.a >= 1.0) { + result = over_color; + } + else { + result = mix(color, vec4(over_color.rgb, 1.0), factor * over_color.a); + } +} + +void node_composite_alpha_over_premultiply(float factor, + vec4 color, + vec4 over_color, + out vec4 result) +{ + if (over_color.a < 0.0) { + result = color; + } + else if (factor == 1.0 && over_color.a >= 1.0) { + result = over_color; + } + else { + float multiplier = 1.0 - factor * over_color.a; + + result = multiplier * color + factor * over_color; + } +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_blur_common.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_blur_common.glsl new file mode 100644 index 00000000000..e404c03bbb0 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_blur_common.glsl @@ -0,0 +1,32 @@ +/* Preprocess the input of the blur filter by squaring it in its alpha straight form, assuming the + * given color is alpha premultiplied. */ +vec4 gamma_correct_blur_input(vec4 color) +{ + /* Unpremultiply alpha. */ + color.rgb /= color.a > 0.0 ? color.a : 1.0; + + /* Square color channel if it is positive, otherwise zero it. */ + color.rgb *= mix(color.rgb, vec3(0.0), lessThan(color.rgb, vec3(0.0))); + + /* Premultiply alpha to undo previous alpha unpremultiplication. */ + color.rgb *= color.a > 0.0 ? color.a : 1.0; + + return color; +} + +/* Postprocess the output of the blur filter by taking its square root it in its alpha straight + * form, assuming the given color is alpha premultiplied. This essential undoes the processing done + * by the gamma_correct_blur_input function. */ +vec4 gamma_uncorrect_blur_output(vec4 color) +{ + /* Unpremultiply alpha. */ + color.rgb /= color.a > 0.0 ? color.a : 1.0; + + /* Take the square root of the color channel if it is positive, otherwise zero it. */ + color.rgb = mix(sqrt(color.rgb), vec3(0.0), lessThan(color.rgb, vec3(0.0))); + + /* Premultiply alpha to undo previous alpha unpremultiplication. */ + color.rgb *= color.a > 0.0 ? color.a : 1.0; + + return color; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_bright_contrast.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_bright_contrast.glsl new file mode 100644 index 00000000000..ce71b4fd8a4 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_bright_contrast.glsl @@ -0,0 +1,38 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) + +/* The algorithm is by Werner D. Streidt + * (http://visca.com/ffactory/archives/5-99/msg00021.html) + * Extracted of OpenCV demhist.c + */ + +#define FLT_EPSILON 1.192092896e-07F + +void node_composite_bright_contrast( + vec4 color, float brightness, float contrast, const float use_premultiply, out vec4 result) +{ + brightness /= 100.0; + float delta = contrast / 200.0; + + float multiplier, offset; + if (contrast > 0.0) { + multiplier = 1.0 - delta * 2.0; + multiplier = 1.0 / max(multiplier, FLT_EPSILON); + offset = multiplier * (brightness - delta); + } + else { + delta *= -1.0; + multiplier = max(1.0 - delta * 2.0, 0.0); + offset = multiplier * brightness + delta; + } + + if (use_premultiply != 0.0) { + color_alpha_unpremultiply(color, color); + } + + result.rgb = color.rgb * multiplier + offset; + result.a = color.a; + + if (use_premultiply != 0.0) { + color_alpha_premultiply(result, result); + } +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_channel_matte.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_channel_matte.glsl new file mode 100644 index 00000000000..f2dcc9543f2 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_channel_matte.glsl @@ -0,0 +1,52 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) + +#define CMP_NODE_CHANNEL_MATTE_CS_RGB 1.0 +#define CMP_NODE_CHANNEL_MATTE_CS_HSV 2.0 +#define CMP_NODE_CHANNEL_MATTE_CS_YUV 3.0 +#define CMP_NODE_CHANNEL_MATTE_CS_YCC 4.0 + +void node_composite_channel_matte(vec4 color, + const float color_space, + const float matte_channel, + const vec2 limit_channels, + float max_limit, + float min_limit, + out vec4 result, + out float matte) +{ + vec4 channels; + if (color_space == CMP_NODE_CHANNEL_MATTE_CS_HSV) { + rgb_to_hsv(color, channels); + } + else if (color_space == CMP_NODE_CHANNEL_MATTE_CS_YUV) { + rgba_to_yuva_itu_709(color, channels); + } + else if (color_space == CMP_NODE_CHANNEL_MATTE_CS_YCC) { + rgba_to_ycca_itu_709(color, channels); + } + else { + channels = color; + } + + float matte_value = channels[int(matte_channel)]; + float limit_value = max(channels[int(limit_channels.x)], channels[int(limit_channels.y)]); + + float alpha = 1.0 - (matte_value - limit_value); + if (alpha > max_limit) { + alpha = color.a; + } + else if (alpha < min_limit) { + alpha = 0.0; + } + else { + alpha = (alpha - min_limit) / (max_limit - min_limit); + } + + matte = min(alpha, color.a); + result = color * matte; +} + +#undef CMP_NODE_CHANNEL_MATTE_CS_RGB +#undef CMP_NODE_CHANNEL_MATTE_CS_HSV +#undef CMP_NODE_CHANNEL_MATTE_CS_YUV +#undef CMP_NODE_CHANNEL_MATTE_CS_YCC diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_chroma_matte.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_chroma_matte.glsl new file mode 100644 index 00000000000..5d6bea0c9db --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_chroma_matte.glsl @@ -0,0 +1,43 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_math_utils.glsl) +#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) + +/* Algorithm from the book Video Demystified. Chapter 7. Chroma Keying. */ +void node_composite_chroma_matte(vec4 color, + vec4 key, + float acceptance, + float cutoff, + float falloff, + out vec4 result, + out float matte) +{ + vec4 color_ycca; + rgba_to_ycca_itu_709(color, color_ycca); + vec4 key_ycca; + rgba_to_ycca_itu_709(key, key_ycca); + + /* Normalize the CrCb components into the [-1, 1] range. */ + vec2 color_cc = color_ycca.yz * 2.0 - 1.0; + vec2 key_cc = key_ycca.yz * 2.0 - 1.0; + + /* Rotate the color onto the space of the key such that x axis of the color space passes through + * the key color. */ + color_cc = vector_to_rotation_matrix(key_cc * vec2(1.0, -1.0)) * color_cc; + + /* Compute foreground key. If positive, the value is in the [0, 1] range. */ + float foreground_key = color_cc.x - (abs(color_cc.y) / acceptance); + + /* Negative foreground key values retain the original alpha. Positive values are scaled by the + * falloff, while colors that make an angle less than the cutoff angle get a zero alpha. */ + float alpha = color.a; + if (foreground_key > 0.0) { + alpha = 1.0 - (foreground_key / falloff); + + if (abs(atan(color_cc.y, color_cc.x)) < (cutoff / 2.0)) { + alpha = 0.0; + } + } + + /* Compute output. */ + matte = min(alpha, color.a); + result = color * matte; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_balance.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_balance.glsl new file mode 100644 index 00000000000..bffb94cdedb --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_balance.glsl @@ -0,0 +1,34 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) + +void node_composite_color_balance_lgg( + float factor, vec4 color, vec3 lift, vec3 gamma, vec3 gain, out vec4 result) +{ + lift = 2.0 - lift; + vec3 srgb_color = linear_rgb_to_srgb(color.rgb); + vec3 lift_balanced = ((srgb_color - 1.0) * lift) + 1.0; + + vec3 gain_balanced = lift_balanced * gain; + gain_balanced = max(gain_balanced, vec3(0.0)); + + vec3 linear_color = srgb_to_linear_rgb(gain_balanced); + gamma = mix(gamma, vec3(1e-6), equal(gamma, vec3(0.0))); + vec3 gamma_balanced = pow(linear_color, 1.0 / gamma); + + result.rgb = mix(color.rgb, gamma_balanced, min(factor, 1.0)); + result.a = color.a; +} + +void node_composite_color_balance_asc_cdl(float factor, + vec4 color, + vec3 offset, + vec3 power, + vec3 slope, + float offset_basis, + out vec4 result) +{ + offset += offset_basis; + vec3 balanced = color.rgb * slope + offset; + balanced = pow(max(balanced, vec3(0.0)), power); + result.rgb = mix(color.rgb, balanced, min(factor, 1.0)); + result.a = color.a; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_correction.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_correction.glsl new file mode 100644 index 00000000000..9b4858f03be --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_correction.glsl @@ -0,0 +1,87 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_math_utils.glsl) +#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) + +void node_composite_color_correction(vec4 color, + float mask, + const vec3 enabled_channels, + float start_midtones, + float end_midtones, + float master_saturation, + float master_contrast, + float master_gamma, + float master_gain, + float master_lift, + float shadows_saturation, + float shadows_contrast, + float shadows_gamma, + float shadows_gain, + float shadows_lift, + float midtones_saturation, + float midtones_contrast, + float midtones_gamma, + float midtones_gain, + float midtones_lift, + float highlights_saturation, + float highlights_contrast, + float highlights_gamma, + float highlights_gain, + float highlights_lift, + const vec3 luminance_coefficients, + out vec4 result) +{ + const float margin = 0.10; + const float margin_divider = 0.5 / margin; + float level = (color.r + color.g + color.b) / 3.0; + float level_shadows = 0.0; + float level_midtones = 0.0; + float level_highlights = 0.0; + if (level < (start_midtones - margin)) { + level_shadows = 1.0; + } + else if (level < (start_midtones + margin)) { + level_midtones = ((level - start_midtones) * margin_divider) + 0.5; + level_shadows = 1.0 - level_midtones; + } + else if (level < (end_midtones - margin)) { + level_midtones = 1.0; + } + else if (level < (end_midtones + margin)) { + level_highlights = ((level - end_midtones) * margin_divider) + 0.5; + level_midtones = 1.0 - level_highlights; + } + else { + level_highlights = 1.0; + } + + float contrast = level_shadows * shadows_contrast; + contrast += level_midtones * midtones_contrast; + contrast += level_highlights * highlights_contrast; + contrast *= master_contrast; + float saturation = level_shadows * shadows_saturation; + saturation += level_midtones * midtones_saturation; + saturation += level_highlights * highlights_saturation; + saturation *= master_saturation; + float gamma = level_shadows * shadows_gamma; + gamma += level_midtones * midtones_gamma; + gamma += level_highlights * highlights_gamma; + gamma *= master_gamma; + float gain = level_shadows * shadows_gain; + gain += level_midtones * midtones_gain; + gain += level_highlights * highlights_gain; + gain *= master_gain; + float lift = level_shadows * shadows_lift; + lift += level_midtones * midtones_lift; + lift += level_highlights * highlights_lift; + lift += master_lift; + + float inverse_gamma = 1.0 / gamma; + float luma = get_luminance(color.rgb, luminance_coefficients); + + vec3 corrected = luma + saturation * (color.rgb - luma); + corrected = 0.5 + (corrected - 0.5) * contrast; + corrected = fallback_pow(corrected * gain + lift, inverse_gamma, corrected); + corrected = mix(color.rgb, corrected, min(mask, 1.0)); + + result.rgb = mix(corrected, color.rgb, equal(enabled_channels, vec3(0.0))); + result.a = color.a; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_matte.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_matte.glsl new file mode 100644 index 00000000000..038471bc1bc --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_matte.glsl @@ -0,0 +1,27 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) + +void node_composite_color_matte(vec4 color, + vec4 key, + float hue_epsilon, + float saturation_epsilon, + float value_epsilon, + out vec4 result, + out float matte) + +{ + vec4 color_hsva; + rgb_to_hsv(color, color_hsva); + vec4 key_hsva; + rgb_to_hsv(key, key_hsva); + + bool is_within_saturation = distance(color_hsva.y, key_hsva.y) < saturation_epsilon; + bool is_within_value = distance(color_hsva.z, key_hsva.z) < value_epsilon; + bool is_within_hue = distance(color_hsva.x, key_hsva.x) < hue_epsilon; + /* Hue wraps around, so check the distance around the boundary. */ + float min_hue = min(color_hsva.x, key_hsva.x); + float max_hue = max(color_hsva.x, key_hsva.x); + is_within_hue = is_within_hue || ((min_hue + (1.0 - max_hue)) < hue_epsilon); + + matte = (is_within_hue && is_within_saturation && is_within_value) ? 0.0 : color.a; + result = color * matte; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_spill.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_spill.glsl new file mode 100644 index 00000000000..0adad53ad80 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_spill.glsl @@ -0,0 +1,13 @@ +void node_composite_color_spill(vec4 color, + float factor, + const float spill_channel, + vec3 spill_scale, + const vec2 limit_channels, + float limit_scale, + out vec4 result) +{ + float average_limit = (color[int(limit_channels.x)] + color[int(limit_channels.y)]) / 2.0; + float map = factor * color[int(spill_channel)] - limit_scale * average_limit; + result.rgb = map > 0.0 ? color.rgb + spill_scale * map : color.rgb; + result.a = color.a; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_to_luminance.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_to_luminance.glsl new file mode 100644 index 00000000000..bcdd625bd4f --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_to_luminance.glsl @@ -0,0 +1,6 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) + +void color_to_luminance(vec4 color, const vec3 luminance_coefficients, out float result) +{ + result = get_luminance(color.rgb, luminance_coefficients); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_difference_matte.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_difference_matte.glsl new file mode 100644 index 00000000000..d769cadce3c --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_difference_matte.glsl @@ -0,0 +1,10 @@ +void node_composite_difference_matte( + vec4 color, vec4 key, float tolerance, float falloff, out vec4 result, out float matte) +{ + vec4 difference = abs(color - key); + float average_difference = (difference.r + difference.g + difference.b) / 3.0; + bool is_opaque = average_difference > tolerance + falloff; + float alpha = is_opaque ? color.a : (max(0.0, average_difference - tolerance) / falloff); + matte = min(alpha, color.a); + result = color * matte; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_distance_matte.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_distance_matte.glsl new file mode 100644 index 00000000000..9beed66826c --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_distance_matte.glsl @@ -0,0 +1,26 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) + +void node_composite_distance_matte_rgba( + vec4 color, vec4 key, float tolerance, float falloff, out vec4 result, out float matte) +{ + float difference = distance(color.rgb, key.rgb); + bool is_opaque = difference > tolerance + falloff; + float alpha = is_opaque ? color.a : max(0.0, difference - tolerance) / falloff; + matte = min(alpha, color.a); + result = color * matte; +} + +void node_composite_distance_matte_ycca( + vec4 color, vec4 key, float tolerance, float falloff, out vec4 result, out float matte) +{ + vec4 color_ycca; + rgba_to_ycca_itu_709(color, color_ycca); + vec4 key_ycca; + rgba_to_ycca_itu_709(key, key_ycca); + + float difference = distance(color_ycca.yz, key_ycca.yz); + bool is_opaque = difference > tolerance + falloff; + float alpha = is_opaque ? color.a : max(0.0, difference - tolerance) / falloff; + matte = min(alpha, color.a); + result = color * matte; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_exposure.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_exposure.glsl new file mode 100644 index 00000000000..f246635a91e --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_exposure.glsl @@ -0,0 +1,6 @@ +void node_composite_exposure(vec4 color, float exposure, out vec4 result) +{ + float multiplier = exp2(exposure); + result.rgb = color.rgb * multiplier; + result.a = color.a; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_gamma.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_gamma.glsl new file mode 100644 index 00000000000..53070d4b0e2 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_gamma.glsl @@ -0,0 +1,7 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_math_utils.glsl) + +void node_composite_gamma(vec4 color, float gamma, out vec4 result) +{ + result.rgb = fallback_pow(color.rgb, gamma, color.rgb); + result.a = color.a; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_hue_correct.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_hue_correct.glsl new file mode 100644 index 00000000000..99eb125cdf2 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_hue_correct.glsl @@ -0,0 +1,39 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) + +/* Curve maps are stored in sampler objects that are evaluated in the [0, 1] range, so normalize + * parameters accordingly. */ +#define NORMALIZE_PARAMETER(parameter, minimum, range) ((parameter - minimum) * range) + +void node_composite_hue_correct(float factor, + vec4 color, + sampler1DArray curve_map, + const float layer, + vec3 minimums, + vec3 range_dividers, + out vec4 result) +{ + vec4 hsv; + rgb_to_hsv(color, hsv); + + /* First, adjust the hue channel on its own, since corrections in the saturation and value + * channels depends on the new value of the hue, not its original value. A curve map value of 0.5 + * means no change in hue, so adjust the value to get an identity at 0.5. Since the identity of + * addition is 0, we subtract 0.5 (0.5 - 0.5 = 0). */ + const float hue_parameter = NORMALIZE_PARAMETER(hsv.x, minimums.x, range_dividers.x); + hsv.x += texture(curve_map, vec2(hue_parameter, layer)).x - 0.5; + + /* Second, adjust the saturation and value based on the new value of the hue. A curve map value + * of 0.5 means no change in hue, so adjust the value to get an identity at 0.5. Since the + * identity of duplication is 1, we multiply by 2 (0.5 * 2 = 1). */ + vec2 parameters = NORMALIZE_PARAMETER(hsv.x, minimums.yz, range_dividers.yz); + hsv.y *= texture(curve_map, vec2(parameters.x, layer)).y * 2.0; + hsv.z *= texture(curve_map, vec2(parameters.y, layer)).z * 2.0; + + /* Sanitize the new hue and saturation values. */ + hsv.x = fract(hsv.x); + hsv.y = clamp(hsv.y, 0.0, 1.0); + + hsv_to_rgb(hsv, result); + + result = mix(color, result, factor); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_hue_saturation_value.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_hue_saturation_value.glsl new file mode 100644 index 00000000000..dd5eb33d318 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_hue_saturation_value.glsl @@ -0,0 +1,16 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) + +void node_composite_hue_saturation_value( + vec4 color, float hue, float saturation, float value, float factor, out vec4 result) +{ + vec4 hsv; + rgb_to_hsv(color, hsv); + + hsv.x = fract(hsv.x + hue + 0.5); + hsv.y = clamp(hsv.y * saturation, 0.0, 1.0); + hsv.z = hsv.z * value; + + hsv_to_rgb(hsv, result); + + result = mix(color, result, factor); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_invert.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_invert.glsl new file mode 100644 index 00000000000..59be746da7f --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_invert.glsl @@ -0,0 +1,13 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) + +void node_composite_invert(float fac, vec4 color, float do_rgb, float do_alpha, out vec4 result) +{ + result = color; + if (do_rgb != 0.0) { + result.rgb = 1.0 - result.rgb; + } + if (do_alpha != 0.0) { + result.a = 1.0 - result.a; + } + result = mix(color, result, fac); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_luminance_matte.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_luminance_matte.glsl new file mode 100644 index 00000000000..3647ac583fe --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_luminance_matte.glsl @@ -0,0 +1,14 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) + +void node_composite_luminance_matte(vec4 color, + float high, + float low, + const vec3 luminance_coefficients, + out vec4 result, + out float matte) +{ + float luminance = get_luminance(color.rgb, luminance_coefficients); + float alpha = clamp(0.0, 1.0, (luminance - low) / (high - low)); + matte = min(alpha, color.a); + result = color * matte; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_main.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_main.glsl new file mode 100644 index 00000000000..27624223dbc --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_main.glsl @@ -0,0 +1,7 @@ +/* The compute shader that will be dispatched by the compositor ShaderOperation. It just calls the + * evaluate function that will be dynamically generated and appended to this shader in the + * ShaderOperation::generate_code method. */ +void main() +{ + evaluate(); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_map_value.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_map_value.glsl new file mode 100644 index 00000000000..20874b4ef44 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_map_value.glsl @@ -0,0 +1,56 @@ +/* An arbitrary value determined by Blender. */ +#define BLENDER_ZMAX 10000.0 + +void node_composite_map_range(float value, + float from_min, + float from_max, + float to_min, + float to_max, + const float should_clamp, + out float result) +{ + if (abs(from_max - from_min) < 1e-6) { + result = 0.0; + } + else { + if (value >= -BLENDER_ZMAX && value <= BLENDER_ZMAX) { + result = (value - from_min) / (from_max - from_min); + result = to_min + result * (to_max - to_min); + } + else if (value > BLENDER_ZMAX) { + result = to_max; + } + else { + result = to_min; + } + + if (should_clamp != 0.0) { + if (to_max > to_min) { + result = clamp(result, to_min, to_max); + } + else { + result = clamp(result, to_max, to_min); + } + } + } +} + +void node_composite_map_value(float value, + float offset, + float size, + const float use_min, + float min, + const float use_max, + float max, + out float result) +{ + result = (value + offset) * size; + + if (use_min != 0.0 && result < min) { + result = min; + } + + if (use_max != 0.0 && result > max) { + result = max; + } +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_normal.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_normal.glsl new file mode 100644 index 00000000000..a2e3b6c4aaa --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_normal.glsl @@ -0,0 +1,9 @@ +void node_composite_normal(vec3 input_vector, + vec3 input_normal, + out vec3 result_normal, + out float result_dot) +{ + vec3 normal = normalize(input_normal); + result_normal = normal; + result_dot = -dot(input_vector, normal); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_posterize.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_posterize.glsl new file mode 100644 index 00000000000..ee8ae234abe --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_posterize.glsl @@ -0,0 +1,6 @@ +void node_composite_posterize(vec4 color, float steps, out vec4 result) +{ + steps = clamp(steps, 2.0, 1024.0); + result = floor(color * steps) / steps; + result.a = color.a; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_separate_combine.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_separate_combine.glsl new file mode 100644 index 00000000000..d72d2260394 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_separate_combine.glsl @@ -0,0 +1,132 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) + +/* ** Combine/Separate XYZ ** */ + +void node_composite_combine_xyz(float x, float y, float z, out vec3 vector) +{ + vector = vec3(x, y, z); +} + +void node_composite_separate_xyz(vec3 vector, out float x, out float y, out float z) +{ + x = vector.x; + y = vector.y; + z = vector.z; +} + +/* ** Combine/Separate RGBA ** */ + +void node_composite_combine_rgba(float r, float g, float b, float a, out vec4 color) +{ + color = vec4(r, g, b, a); +} + +void node_composite_separate_rgba(vec4 color, out float r, out float g, out float b, out float a) +{ + r = color.r; + g = color.g; + b = color.b; + a = color.a; +} + +/* ** Combine/Separate HSVA ** */ + +void node_composite_combine_hsva(float h, float s, float v, float a, out vec4 color) +{ + hsv_to_rgb(vec4(h, s, v, a), color); +} + +void node_composite_separate_hsva(vec4 color, out float h, out float s, out float v, out float a) +{ + vec4 hsva; + rgb_to_hsv(color, hsva); + h = hsva.x; + s = hsva.y; + v = hsva.z; + a = hsva.a; +} + +/* ** Combine/Separate HSLA ** */ + +void node_composite_combine_hsla(float h, float s, float l, float a, out vec4 color) +{ + hsl_to_rgb(vec4(h, s, l, a), color); +} + +void node_composite_separate_hsla(vec4 color, out float h, out float s, out float l, out float a) +{ + vec4 hsla; + rgb_to_hsl(color, hsla); + h = hsla.x; + s = hsla.y; + l = hsla.z; + a = hsla.a; +} + +/* ** Combine/Separate YCCA ** */ + +void node_composite_combine_ycca_itu_601(float y, float cb, float cr, float a, out vec4 color) +{ + ycca_to_rgba_itu_601(vec4(y, cb, cr, a), color); +} + +void node_composite_combine_ycca_itu_709(float y, float cb, float cr, float a, out vec4 color) +{ + ycca_to_rgba_itu_709(vec4(y, cb, cr, a), color); +} + +void node_composite_combine_ycca_jpeg(float y, float cb, float cr, float a, out vec4 color) +{ + ycca_to_rgba_jpeg(vec4(y, cb, cr, a), color); +} + +void node_composite_separate_ycca_itu_601( + vec4 color, out float y, out float cb, out float cr, out float a) +{ + vec4 ycca; + rgba_to_ycca_itu_601(color, ycca); + y = ycca.x; + cb = ycca.y; + cr = ycca.z; + a = ycca.a; +} + +void node_composite_separate_ycca_itu_709( + vec4 color, out float y, out float cb, out float cr, out float a) +{ + vec4 ycca; + rgba_to_ycca_itu_709(color, ycca); + y = ycca.x; + cb = ycca.y; + cr = ycca.z; + a = ycca.a; +} + +void node_composite_separate_ycca_jpeg( + vec4 color, out float y, out float cb, out float cr, out float a) +{ + vec4 ycca; + rgba_to_ycca_jpeg(color, ycca); + y = ycca.x; + cb = ycca.y; + cr = ycca.z; + a = ycca.a; +} + +/* ** Combine/Separate YUVA ** */ + +void node_composite_combine_yuva_itu_709(float y, float u, float v, float a, out vec4 color) +{ + yuva_to_rgba_itu_709(vec4(y, u, v, a), color); +} + +void node_composite_separate_yuva_itu_709( + vec4 color, out float y, out float u, out float v, out float a) +{ + vec4 yuva; + rgba_to_yuva_itu_709(color, yuva); + y = yuva.x; + u = yuva.y; + v = yuva.z; + a = yuva.a; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_set_alpha.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_set_alpha.glsl new file mode 100644 index 00000000000..95380d1ed0f --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_set_alpha.glsl @@ -0,0 +1,9 @@ +void node_composite_set_alpha_apply(vec4 color, float alpha, out vec4 result) +{ + result = color * alpha; +} + +void node_composite_set_alpha_replace(vec4 color, float alpha, out vec4 result) +{ + result = vec4(color.rgb, alpha); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_store_output.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_store_output.glsl new file mode 100644 index 00000000000..7fba26907b5 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_store_output.glsl @@ -0,0 +1,26 @@ +/* The following functions are called to store the given value in the output identified by the + * given ID. The ID is an unsigned integer that is encoded in a float, so floatBitsToUint is called + * to get the actual identifier. The functions have an output value as their last argument that is + * used to establish an output link that is then used to track the nodes that contribute to the + * output of the compositor node tree. + * + * The store_[float|vector|color] functions are dynamically generated in + * ShaderOperation::generate_code_for_outputs. */ + +void node_compositor_store_output_float(const float id, float value, out float out_value) +{ + store_float(floatBitsToUint(id), value); + out_value = value; +} + +void node_compositor_store_output_vector(const float id, vec3 vector, out vec3 out_vector) +{ + store_vector(floatBitsToUint(id), vector); + out_vector = vector; +} + +void node_compositor_store_output_color(const float id, vec4 color, out vec4 out_color) +{ + store_color(floatBitsToUint(id), color); + out_color = color; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_texture_utilities.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_texture_utilities.glsl new file mode 100644 index 00000000000..128fc6aeaf5 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_texture_utilities.glsl @@ -0,0 +1,35 @@ +/* A shorthand for 1D textureSize with a zero LOD. */ +int texture_size(sampler1D sampler) +{ + return textureSize(sampler, 0); +} + +/* A shorthand for 1D texelFetch with zero LOD and bounded access clamped to border. */ +vec4 texture_load(sampler1D sampler, int x) +{ + const int texture_bound = texture_size(sampler) - 1; + return texelFetch(sampler, clamp(x, 0, texture_bound), 0); +} + +/* A shorthand for 2D textureSize with a zero LOD. */ +ivec2 texture_size(sampler2D sampler) +{ + return textureSize(sampler, 0); +} + +/* A shorthand for 2D texelFetch with zero LOD and bounded access clamped to border. */ +vec4 texture_load(sampler2D sampler, ivec2 texel) +{ + const ivec2 texture_bounds = texture_size(sampler) - ivec2(1); + return texelFetch(sampler, clamp(texel, ivec2(0), texture_bounds), 0); +} + +/* A shorthand for 2D texelFetch with zero LOD and a fallback value for out-of-bound access. */ +vec4 texture_load(sampler2D sampler, ivec2 texel, vec4 fallback) +{ + const ivec2 texture_bounds = texture_size(sampler) - ivec2(1); + if (any(lessThan(texel, ivec2(0))) || any(greaterThan(texel, texture_bounds))) { + return fallback; + } + return texelFetch(sampler, texel, 0); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_type_conversion.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_type_conversion.glsl new file mode 100644 index 00000000000..75c76fd7341 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_type_conversion.glsl @@ -0,0 +1,29 @@ +float float_from_vec4(vec4 vector) +{ + return dot(vector.rgb, vec3(1.0)) / 3.0; +} + +float float_from_vec3(vec3 vector) +{ + return dot(vector, vec3(1.0)) / 3.0; +} + +vec3 vec3_from_vec4(vec4 vector) +{ + return vector.rgb; +} + +vec3 vec3_from_float(float value) +{ + return vec3(value); +} + +vec4 vec4_from_vec3(vec3 vector) +{ + return vec4(vector, 1.0); +} + +vec4 vec4_from_float(float value) +{ + return vec4(vec3(value), 1.0); +} |