1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 CCL_NAMESPACE_BEGIN
18 
svm_mix_blend(float t,float3 col1,float3 col2)19 ccl_device float3 svm_mix_blend(float t, float3 col1, float3 col2)
20 {
21   return interp(col1, col2, t);
22 }
23 
svm_mix_add(float t,float3 col1,float3 col2)24 ccl_device float3 svm_mix_add(float t, float3 col1, float3 col2)
25 {
26   return interp(col1, col1 + col2, t);
27 }
28 
svm_mix_mul(float t,float3 col1,float3 col2)29 ccl_device float3 svm_mix_mul(float t, float3 col1, float3 col2)
30 {
31   return interp(col1, col1 * col2, t);
32 }
33 
svm_mix_screen(float t,float3 col1,float3 col2)34 ccl_device float3 svm_mix_screen(float t, float3 col1, float3 col2)
35 {
36   float tm = 1.0f - t;
37   float3 one = make_float3(1.0f, 1.0f, 1.0f);
38   float3 tm3 = make_float3(tm, tm, tm);
39 
40   return one - (tm3 + t * (one - col2)) * (one - col1);
41 }
42 
svm_mix_overlay(float t,float3 col1,float3 col2)43 ccl_device float3 svm_mix_overlay(float t, float3 col1, float3 col2)
44 {
45   float tm = 1.0f - t;
46 
47   float3 outcol = col1;
48 
49   if (outcol.x < 0.5f)
50     outcol.x *= tm + 2.0f * t * col2.x;
51   else
52     outcol.x = 1.0f - (tm + 2.0f * t * (1.0f - col2.x)) * (1.0f - outcol.x);
53 
54   if (outcol.y < 0.5f)
55     outcol.y *= tm + 2.0f * t * col2.y;
56   else
57     outcol.y = 1.0f - (tm + 2.0f * t * (1.0f - col2.y)) * (1.0f - outcol.y);
58 
59   if (outcol.z < 0.5f)
60     outcol.z *= tm + 2.0f * t * col2.z;
61   else
62     outcol.z = 1.0f - (tm + 2.0f * t * (1.0f - col2.z)) * (1.0f - outcol.z);
63 
64   return outcol;
65 }
66 
svm_mix_sub(float t,float3 col1,float3 col2)67 ccl_device float3 svm_mix_sub(float t, float3 col1, float3 col2)
68 {
69   return interp(col1, col1 - col2, t);
70 }
71 
svm_mix_div(float t,float3 col1,float3 col2)72 ccl_device float3 svm_mix_div(float t, float3 col1, float3 col2)
73 {
74   float tm = 1.0f - t;
75 
76   float3 outcol = col1;
77 
78   if (col2.x != 0.0f)
79     outcol.x = tm * outcol.x + t * outcol.x / col2.x;
80   if (col2.y != 0.0f)
81     outcol.y = tm * outcol.y + t * outcol.y / col2.y;
82   if (col2.z != 0.0f)
83     outcol.z = tm * outcol.z + t * outcol.z / col2.z;
84 
85   return outcol;
86 }
87 
svm_mix_diff(float t,float3 col1,float3 col2)88 ccl_device float3 svm_mix_diff(float t, float3 col1, float3 col2)
89 {
90   return interp(col1, fabs(col1 - col2), t);
91 }
92 
svm_mix_dark(float t,float3 col1,float3 col2)93 ccl_device float3 svm_mix_dark(float t, float3 col1, float3 col2)
94 {
95   return interp(col1, min(col1, col2), t);
96 }
97 
svm_mix_light(float t,float3 col1,float3 col2)98 ccl_device float3 svm_mix_light(float t, float3 col1, float3 col2)
99 {
100   return interp(col1, max(col1, col2), t);
101 }
102 
svm_mix_dodge(float t,float3 col1,float3 col2)103 ccl_device float3 svm_mix_dodge(float t, float3 col1, float3 col2)
104 {
105   float3 outcol = col1;
106 
107   if (outcol.x != 0.0f) {
108     float tmp = 1.0f - t * col2.x;
109     if (tmp <= 0.0f)
110       outcol.x = 1.0f;
111     else if ((tmp = outcol.x / tmp) > 1.0f)
112       outcol.x = 1.0f;
113     else
114       outcol.x = tmp;
115   }
116   if (outcol.y != 0.0f) {
117     float tmp = 1.0f - t * col2.y;
118     if (tmp <= 0.0f)
119       outcol.y = 1.0f;
120     else if ((tmp = outcol.y / tmp) > 1.0f)
121       outcol.y = 1.0f;
122     else
123       outcol.y = tmp;
124   }
125   if (outcol.z != 0.0f) {
126     float tmp = 1.0f - t * col2.z;
127     if (tmp <= 0.0f)
128       outcol.z = 1.0f;
129     else if ((tmp = outcol.z / tmp) > 1.0f)
130       outcol.z = 1.0f;
131     else
132       outcol.z = tmp;
133   }
134 
135   return outcol;
136 }
137 
svm_mix_burn(float t,float3 col1,float3 col2)138 ccl_device float3 svm_mix_burn(float t, float3 col1, float3 col2)
139 {
140   float tmp, tm = 1.0f - t;
141 
142   float3 outcol = col1;
143 
144   tmp = tm + t * col2.x;
145   if (tmp <= 0.0f)
146     outcol.x = 0.0f;
147   else if ((tmp = (1.0f - (1.0f - outcol.x) / tmp)) < 0.0f)
148     outcol.x = 0.0f;
149   else if (tmp > 1.0f)
150     outcol.x = 1.0f;
151   else
152     outcol.x = tmp;
153 
154   tmp = tm + t * col2.y;
155   if (tmp <= 0.0f)
156     outcol.y = 0.0f;
157   else if ((tmp = (1.0f - (1.0f - outcol.y) / tmp)) < 0.0f)
158     outcol.y = 0.0f;
159   else if (tmp > 1.0f)
160     outcol.y = 1.0f;
161   else
162     outcol.y = tmp;
163 
164   tmp = tm + t * col2.z;
165   if (tmp <= 0.0f)
166     outcol.z = 0.0f;
167   else if ((tmp = (1.0f - (1.0f - outcol.z) / tmp)) < 0.0f)
168     outcol.z = 0.0f;
169   else if (tmp > 1.0f)
170     outcol.z = 1.0f;
171   else
172     outcol.z = tmp;
173 
174   return outcol;
175 }
176 
svm_mix_hue(float t,float3 col1,float3 col2)177 ccl_device float3 svm_mix_hue(float t, float3 col1, float3 col2)
178 {
179   float3 outcol = col1;
180 
181   float3 hsv2 = rgb_to_hsv(col2);
182 
183   if (hsv2.y != 0.0f) {
184     float3 hsv = rgb_to_hsv(outcol);
185     hsv.x = hsv2.x;
186     float3 tmp = hsv_to_rgb(hsv);
187 
188     outcol = interp(outcol, tmp, t);
189   }
190 
191   return outcol;
192 }
193 
svm_mix_sat(float t,float3 col1,float3 col2)194 ccl_device float3 svm_mix_sat(float t, float3 col1, float3 col2)
195 {
196   float tm = 1.0f - t;
197 
198   float3 outcol = col1;
199 
200   float3 hsv = rgb_to_hsv(outcol);
201 
202   if (hsv.y != 0.0f) {
203     float3 hsv2 = rgb_to_hsv(col2);
204 
205     hsv.y = tm * hsv.y + t * hsv2.y;
206     outcol = hsv_to_rgb(hsv);
207   }
208 
209   return outcol;
210 }
211 
svm_mix_val(float t,float3 col1,float3 col2)212 ccl_device float3 svm_mix_val(float t, float3 col1, float3 col2)
213 {
214   float tm = 1.0f - t;
215 
216   float3 hsv = rgb_to_hsv(col1);
217   float3 hsv2 = rgb_to_hsv(col2);
218 
219   hsv.z = tm * hsv.z + t * hsv2.z;
220 
221   return hsv_to_rgb(hsv);
222 }
223 
svm_mix_color(float t,float3 col1,float3 col2)224 ccl_device float3 svm_mix_color(float t, float3 col1, float3 col2)
225 {
226   float3 outcol = col1;
227   float3 hsv2 = rgb_to_hsv(col2);
228 
229   if (hsv2.y != 0.0f) {
230     float3 hsv = rgb_to_hsv(outcol);
231     hsv.x = hsv2.x;
232     hsv.y = hsv2.y;
233     float3 tmp = hsv_to_rgb(hsv);
234 
235     outcol = interp(outcol, tmp, t);
236   }
237 
238   return outcol;
239 }
240 
svm_mix_soft(float t,float3 col1,float3 col2)241 ccl_device float3 svm_mix_soft(float t, float3 col1, float3 col2)
242 {
243   float tm = 1.0f - t;
244 
245   float3 one = make_float3(1.0f, 1.0f, 1.0f);
246   float3 scr = one - (one - col2) * (one - col1);
247 
248   return tm * col1 + t * ((one - col1) * col2 * col1 + col1 * scr);
249 }
250 
svm_mix_linear(float t,float3 col1,float3 col2)251 ccl_device float3 svm_mix_linear(float t, float3 col1, float3 col2)
252 {
253   return col1 + t * (2.0f * col2 + make_float3(-1.0f, -1.0f, -1.0f));
254 }
255 
svm_mix_clamp(float3 col)256 ccl_device float3 svm_mix_clamp(float3 col)
257 {
258   return saturate3(col);
259 }
260 
svm_mix(NodeMix type,float fac,float3 c1,float3 c2)261 ccl_device_noinline_cpu float3 svm_mix(NodeMix type, float fac, float3 c1, float3 c2)
262 {
263   float t = saturate(fac);
264 
265   switch (type) {
266     case NODE_MIX_BLEND:
267       return svm_mix_blend(t, c1, c2);
268     case NODE_MIX_ADD:
269       return svm_mix_add(t, c1, c2);
270     case NODE_MIX_MUL:
271       return svm_mix_mul(t, c1, c2);
272     case NODE_MIX_SCREEN:
273       return svm_mix_screen(t, c1, c2);
274     case NODE_MIX_OVERLAY:
275       return svm_mix_overlay(t, c1, c2);
276     case NODE_MIX_SUB:
277       return svm_mix_sub(t, c1, c2);
278     case NODE_MIX_DIV:
279       return svm_mix_div(t, c1, c2);
280     case NODE_MIX_DIFF:
281       return svm_mix_diff(t, c1, c2);
282     case NODE_MIX_DARK:
283       return svm_mix_dark(t, c1, c2);
284     case NODE_MIX_LIGHT:
285       return svm_mix_light(t, c1, c2);
286     case NODE_MIX_DODGE:
287       return svm_mix_dodge(t, c1, c2);
288     case NODE_MIX_BURN:
289       return svm_mix_burn(t, c1, c2);
290     case NODE_MIX_HUE:
291       return svm_mix_hue(t, c1, c2);
292     case NODE_MIX_SAT:
293       return svm_mix_sat(t, c1, c2);
294     case NODE_MIX_VAL:
295       return svm_mix_val(t, c1, c2);
296     case NODE_MIX_COLOR:
297       return svm_mix_color(t, c1, c2);
298     case NODE_MIX_SOFT:
299       return svm_mix_soft(t, c1, c2);
300     case NODE_MIX_LINEAR:
301       return svm_mix_linear(t, c1, c2);
302     case NODE_MIX_CLAMP:
303       return svm_mix_clamp(c1);
304   }
305 
306   return make_float3(0.0f, 0.0f, 0.0f);
307 }
308 
svm_brightness_contrast(float3 color,float brightness,float contrast)309 ccl_device_inline float3 svm_brightness_contrast(float3 color, float brightness, float contrast)
310 {
311   float a = 1.0f + contrast;
312   float b = brightness - contrast * 0.5f;
313 
314   color.x = max(a * color.x + b, 0.0f);
315   color.y = max(a * color.y + b, 0.0f);
316   color.z = max(a * color.z + b, 0.0f);
317 
318   return color;
319 }
320 
321 CCL_NAMESPACE_END
322