This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/gpu/shaders/common/gpu_shader_common_curves.glsl
Omar Emara bdfee6d831 EEVEE: Refactor curve nodes
This patches rewrites the GPU shaders of curve nodes for easier future
development. This is a non-functional change. The new code avoids code
duplication by moving common code into BKE curve mapping functions. It
also avoids ambiguous data embedding into the gradient vectors that are
passed to vectors and reduces the size of uniforms uploaded to the
shader by avoiding redundancies.

This is needed in preparation for the viewport compositor, which will
utilize and extend this implementation.

Reviewed By: fclem

Differential Revision: https://developer.blender.org/D14689
2022-05-06 13:33:23 +02:00

163 lines
6.2 KiB
GLSL

vec4 white_balance(vec4 color, vec4 black_level, vec4 white_level)
{
vec4 range = max(white_level - black_level, vec4(1e-5f));
return (color - black_level) / range;
}
float extrapolate_if_needed(float parameter, float value, float start_slope, float end_slope)
{
if (parameter < 0.0) {
return value + parameter * start_slope;
}
if (parameter > 1.0) {
return value + (parameter - 1.0) * end_slope;
}
return value;
}
/* Same as extrapolate_if_needed but vectorized. */
vec3 extrapolate_if_needed(vec3 parameters, vec3 values, vec3 start_slopes, vec3 end_slopes)
{
vec3 end_or_zero_slopes = mix(vec3(0.0), end_slopes, greaterThan(parameters, vec3(1.0)));
vec3 slopes = mix(end_or_zero_slopes, start_slopes, lessThan(parameters, vec3(0.0)));
parameters = parameters - mix(vec3(0.0), vec3(1.0), greaterThan(parameters, vec3(1.0)));
return values + parameters * slopes;
}
/* 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 curves_combined_rgb(float factor,
vec4 color,
vec4 black_level,
vec4 white_level,
sampler1DArray curve_map,
const float layer,
vec4 range_minimums,
vec4 range_dividers,
vec4 start_slopes,
vec4 end_slopes,
out vec4 result)
{
vec4 balanced = white_balance(color, black_level, white_level);
/* First, evaluate alpha curve map at all channels. The alpha curve is the Combined curve in the
* UI. */
vec3 parameters = NORMALIZE_PARAMETER(balanced.rgb, range_minimums.aaa, range_dividers.aaa);
result.r = texture(curve_map, vec2(parameters.x, layer)).a;
result.g = texture(curve_map, vec2(parameters.y, layer)).a;
result.b = texture(curve_map, vec2(parameters.z, layer)).a;
/* Then, extrapolate if needed. */
result.rgb = extrapolate_if_needed(parameters, result.rgb, start_slopes.aaa, end_slopes.aaa);
/* Then, evaluate each channel on its curve map. */
parameters = NORMALIZE_PARAMETER(result.rgb, range_minimums.rgb, range_dividers.rgb);
result.r = texture(curve_map, vec2(parameters.r, layer)).r;
result.g = texture(curve_map, vec2(parameters.g, layer)).g;
result.b = texture(curve_map, vec2(parameters.b, layer)).b;
/* Then, extrapolate again if needed. */
result.rgb = extrapolate_if_needed(parameters, result.rgb, start_slopes.rgb, end_slopes.rgb);
result.a = color.a;
result = mix(color, result, factor);
}
void curves_combined_only(float factor,
vec4 color,
vec4 black_level,
vec4 white_level,
sampler1DArray curve_map,
const float layer,
float range_minimum,
float range_divider,
float start_slope,
float end_slope,
out vec4 result)
{
vec4 balanced = white_balance(color, black_level, white_level);
/* Evaluate alpha curve map at all channels. The alpha curve is the Combined curve in the
* UI. */
vec3 parameters = NORMALIZE_PARAMETER(balanced.rgb, range_minimum, range_divider);
result.r = texture(curve_map, vec2(parameters.x, layer)).a;
result.g = texture(curve_map, vec2(parameters.y, layer)).a;
result.b = texture(curve_map, vec2(parameters.z, layer)).a;
/* Then, extrapolate if needed. */
result.rgb = extrapolate_if_needed(parameters, result.rgb, vec3(start_slope), vec3(end_slope));
result.a = color.a;
result = mix(color, result, factor);
}
void curves_vector(vec3 vector,
sampler1DArray curve_map,
const float layer,
vec3 range_minimums,
vec3 range_dividers,
vec3 start_slopes,
vec3 end_slopes,
out vec3 result)
{
/* Evaluate each component on its curve map. */
vec3 parameters = NORMALIZE_PARAMETER(vector, range_minimums, range_dividers);
result.x = texture(curve_map, vec2(parameters.x, layer)).x;
result.y = texture(curve_map, vec2(parameters.y, layer)).y;
result.z = texture(curve_map, vec2(parameters.z, layer)).z;
/* Then, extrapolate if needed. */
result = extrapolate_if_needed(parameters, result, start_slopes, end_slopes);
}
void curves_vector_mixed(float factor,
vec3 vector,
sampler1DArray curve_map,
const float layer,
vec3 range_minimums,
vec3 range_dividers,
vec3 start_slopes,
vec3 end_slopes,
out vec3 result)
{
curves_vector(
vector, curve_map, layer, range_minimums, range_dividers, start_slopes, end_slopes, result);
result = mix(vector, result, factor);
}
void curves_float(float value,
sampler1DArray curve_map,
const float layer,
float range_minimum,
float range_divider,
float start_slope,
float end_slope,
out float result)
{
/* Evaluate the normalized value on the first curve map. */
float parameter = NORMALIZE_PARAMETER(value, range_minimum, range_divider);
result = texture(curve_map, vec2(parameter, layer)).x;
/* Then, extrapolate if needed. */
result = extrapolate_if_needed(parameter, result, start_slope, end_slope);
}
void curves_float_mixed(float factor,
float value,
sampler1DArray curve_map,
const float layer,
float range_minimum,
float range_divider,
float start_slope,
float end_slope,
out float result)
{
curves_float(
value, curve_map, layer, range_minimum, range_divider, start_slope, end_slope, result);
result = mix(value, result, factor);
}