Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gpu_shader_common_curves.glsl « common « shaders « gpu « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 8948ed775579b200ff1a4cd2dc36169ddedf2c8f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
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);
}