diff options
author | Charlie Jolly <charlie> | 2022-08-30 13:05:46 +0300 |
---|---|---|
committer | Charlie Jolly <mistajolly@gmail.com> | 2022-08-31 02:13:57 +0300 |
commit | bfa0ee13d5395fa2cf622b6808e93d0a7cd4f3ea (patch) | |
tree | 60a8fece4797903560d7892d6e388030a3566a2b /intern/cycles/kernel | |
parent | 0331a8c67c8035c29ac6b7655cb4e4d837ddabba (diff) |
Node: Mix node
This patch is a response to T92588 and is implemented
as a Function/Shader node.
This node has support for Float, Vector and Color data types.
For Vector it supports uniform and non-uniform mixing.
For Color it now has the option to remove factor clamping.
It replaces the Mix RGB for Shader and Geometry node trees.
As discussed in T96219, this patch converts existing nodes
in .blend files. The old node is still available in the
Python API but hidden from the menus.
Reviewed By: HooglyBoogly, JacquesLucke, simonthommes, brecht
Maniphest Tasks: T92588
Differential Revision: https://developer.blender.org/D13749
Diffstat (limited to 'intern/cycles/kernel')
-rw-r--r-- | intern/cycles/kernel/osl/shaders/CMakeLists.txt | 5 | ||||
-rw-r--r-- | intern/cycles/kernel/osl/shaders/node_color_blend.h | 264 | ||||
-rw-r--r-- | intern/cycles/kernel/osl/shaders/node_mix_color.osl | 57 | ||||
-rw-r--r-- | intern/cycles/kernel/osl/shaders/node_mix_float.osl | 11 | ||||
-rw-r--r-- | intern/cycles/kernel/osl/shaders/node_mix_vector.osl | 14 | ||||
-rw-r--r-- | intern/cycles/kernel/osl/shaders/node_mix_vector_non_uniform.osl | 14 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/color_util.h | 12 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/mix.h | 86 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/node_types_template.h | 4 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm.h | 12 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/types.h | 2 |
11 files changed, 475 insertions, 6 deletions
diff --git a/intern/cycles/kernel/osl/shaders/CMakeLists.txt b/intern/cycles/kernel/osl/shaders/CMakeLists.txt index 741bce7c399..c79af3f6112 100644 --- a/intern/cycles/kernel/osl/shaders/CMakeLists.txt +++ b/intern/cycles/kernel/osl/shaders/CMakeLists.txt @@ -57,6 +57,10 @@ set(SRC_OSL node_math.osl node_mix.osl node_mix_closure.osl + node_mix_color.osl + node_mix_float.osl + node_mix_vector.osl + node_mix_vector_non_uniform.osl node_musgrave_texture.osl node_noise_texture.osl node_normal.osl @@ -109,6 +113,7 @@ file(GLOB SRC_OSL_HEADER_DIST ${OSL_SHADER_DIR}/*.h) set(SRC_OSL_HEADERS node_color.h + node_color_blend.h node_fresnel.h node_hash.h node_math.h diff --git a/intern/cycles/kernel/osl/shaders/node_color_blend.h b/intern/cycles/kernel/osl/shaders/node_color_blend.h new file mode 100644 index 00000000000..ab4b4809a97 --- /dev/null +++ b/intern/cycles/kernel/osl/shaders/node_color_blend.h @@ -0,0 +1,264 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright 2011-2022 Blender Foundation */ + +color node_mix_blend(float t, color col1, color col2) +{ + return mix(col1, col2, t); +} + +color node_mix_add(float t, color col1, color col2) +{ + return mix(col1, col1 + col2, t); +} + +color node_mix_mul(float t, color col1, color col2) +{ + return mix(col1, col1 * col2, t); +} + +color node_mix_screen(float t, color col1, color col2) +{ + float tm = 1.0 - t; + + return color(1.0) - (color(tm) + t * (color(1.0) - col2)) * (color(1.0) - col1); +} + +color node_mix_overlay(float t, color col1, color col2) +{ + float tm = 1.0 - t; + + color outcol = col1; + + if (outcol[0] < 0.5) + outcol[0] *= tm + 2.0 * t * col2[0]; + else + outcol[0] = 1.0 - (tm + 2.0 * t * (1.0 - col2[0])) * (1.0 - outcol[0]); + + if (outcol[1] < 0.5) + outcol[1] *= tm + 2.0 * t * col2[1]; + else + outcol[1] = 1.0 - (tm + 2.0 * t * (1.0 - col2[1])) * (1.0 - outcol[1]); + + if (outcol[2] < 0.5) + outcol[2] *= tm + 2.0 * t * col2[2]; + else + outcol[2] = 1.0 - (tm + 2.0 * t * (1.0 - col2[2])) * (1.0 - outcol[2]); + + return outcol; +} + +color node_mix_sub(float t, color col1, color col2) +{ + return mix(col1, col1 - col2, t); +} + +color node_mix_div(float t, color col1, color col2) +{ + float tm = 1.0 - t; + + color outcol = col1; + + if (col2[0] != 0.0) + outcol[0] = tm * outcol[0] + t * outcol[0] / col2[0]; + if (col2[1] != 0.0) + outcol[1] = tm * outcol[1] + t * outcol[1] / col2[1]; + if (col2[2] != 0.0) + outcol[2] = tm * outcol[2] + t * outcol[2] / col2[2]; + + return outcol; +} + +color node_mix_diff(float t, color col1, color col2) +{ + return mix(col1, abs(col1 - col2), t); +} + +color node_mix_dark(float t, color col1, color col2) +{ + return mix(col1, min(col1, col2), t); +} + +color node_mix_light(float t, color col1, color col2) +{ + return mix(col1, max(col1, col2), t); +} + +color node_mix_dodge(float t, color col1, color col2) +{ + color outcol = col1; + + if (outcol[0] != 0.0) { + float tmp = 1.0 - t * col2[0]; + if (tmp <= 0.0) + outcol[0] = 1.0; + else if ((tmp = outcol[0] / tmp) > 1.0) + outcol[0] = 1.0; + else + outcol[0] = tmp; + } + if (outcol[1] != 0.0) { + float tmp = 1.0 - t * col2[1]; + if (tmp <= 0.0) + outcol[1] = 1.0; + else if ((tmp = outcol[1] / tmp) > 1.0) + outcol[1] = 1.0; + else + outcol[1] = tmp; + } + if (outcol[2] != 0.0) { + float tmp = 1.0 - t * col2[2]; + if (tmp <= 0.0) + outcol[2] = 1.0; + else if ((tmp = outcol[2] / tmp) > 1.0) + outcol[2] = 1.0; + else + outcol[2] = tmp; + } + + return outcol; +} + +color node_mix_burn(float t, color col1, color col2) +{ + float tmp, tm = 1.0 - t; + + color outcol = col1; + + tmp = tm + t * col2[0]; + if (tmp <= 0.0) + outcol[0] = 0.0; + else if ((tmp = (1.0 - (1.0 - outcol[0]) / tmp)) < 0.0) + outcol[0] = 0.0; + else if (tmp > 1.0) + outcol[0] = 1.0; + else + outcol[0] = tmp; + + tmp = tm + t * col2[1]; + if (tmp <= 0.0) + outcol[1] = 0.0; + else if ((tmp = (1.0 - (1.0 - outcol[1]) / tmp)) < 0.0) + outcol[1] = 0.0; + else if (tmp > 1.0) + outcol[1] = 1.0; + else + outcol[1] = tmp; + + tmp = tm + t * col2[2]; + if (tmp <= 0.0) + outcol[2] = 0.0; + else if ((tmp = (1.0 - (1.0 - outcol[2]) / tmp)) < 0.0) + outcol[2] = 0.0; + else if (tmp > 1.0) + outcol[2] = 1.0; + else + outcol[2] = tmp; + + return outcol; +} + +color node_mix_hue(float t, color col1, color col2) +{ + color outcol = col1; + color hsv2 = rgb_to_hsv(col2); + + if (hsv2[1] != 0.0) { + color hsv = rgb_to_hsv(outcol); + hsv[0] = hsv2[0]; + color tmp = hsv_to_rgb(hsv); + + outcol = mix(outcol, tmp, t); + } + + return outcol; +} + +color node_mix_sat(float t, color col1, color col2) +{ + float tm = 1.0 - t; + + color outcol = col1; + + color hsv = rgb_to_hsv(outcol); + + if (hsv[1] != 0.0) { + color hsv2 = rgb_to_hsv(col2); + + hsv[1] = tm * hsv[1] + t * hsv2[1]; + outcol = hsv_to_rgb(hsv); + } + + return outcol; +} + +color node_mix_val(float t, color col1, color col2) +{ + float tm = 1.0 - t; + + color hsv = rgb_to_hsv(col1); + color hsv2 = rgb_to_hsv(col2); + + hsv[2] = tm * hsv[2] + t * hsv2[2]; + + return hsv_to_rgb(hsv); +} + +color node_mix_color(float t, color col1, color col2) +{ + color outcol = col1; + color hsv2 = rgb_to_hsv(col2); + + if (hsv2[1] != 0.0) { + color hsv = rgb_to_hsv(outcol); + hsv[0] = hsv2[0]; + hsv[1] = hsv2[1]; + color tmp = hsv_to_rgb(hsv); + + outcol = mix(outcol, tmp, t); + } + + return outcol; +} + +color node_mix_soft(float t, color col1, color col2) +{ + float tm = 1.0 - t; + + color one = color(1.0); + color scr = one - (one - col2) * (one - col1); + + return tm * col1 + t * ((one - col1) * col2 * col1 + col1 * scr); +} + +color node_mix_linear(float t, color col1, color col2) +{ + color outcol = col1; + + if (col2[0] > 0.5) + outcol[0] = col1[0] + t * (2.0 * (col2[0] - 0.5)); + else + outcol[0] = col1[0] + t * (2.0 * (col2[0]) - 1.0); + + if (col2[1] > 0.5) + outcol[1] = col1[1] + t * (2.0 * (col2[1] - 0.5)); + else + outcol[1] = col1[1] + t * (2.0 * (col2[1]) - 1.0); + + if (col2[2] > 0.5) + outcol[2] = col1[2] + t * (2.0 * (col2[2] - 0.5)); + else + outcol[2] = col1[2] + t * (2.0 * (col2[2]) - 1.0); + + return outcol; +} + +color node_mix_clamp(color col) +{ + color outcol = col; + + outcol[0] = clamp(col[0], 0.0, 1.0); + outcol[1] = clamp(col[1], 0.0, 1.0); + outcol[2] = clamp(col[2], 0.0, 1.0); + + return outcol; +} diff --git a/intern/cycles/kernel/osl/shaders/node_mix_color.osl b/intern/cycles/kernel/osl/shaders/node_mix_color.osl new file mode 100644 index 00000000000..3ddd89ed306 --- /dev/null +++ b/intern/cycles/kernel/osl/shaders/node_mix_color.osl @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright 2011-2022 Blender Foundation */ + +#include "node_color.h" +#include "node_color_blend.h" +#include "stdcycles.h" + +shader node_mix_color(string blend_type = "mix", + int use_clamp = 0, + int use_clamp_result = 0, + float Factor = 0.5, + color A = 0.0, + color B = 0.0, + output color Result = 0.0) +{ + float t = (use_clamp) ? clamp(Factor, 0.0, 1.0) : Factor; + + if (blend_type == "mix") + Result = mix(A, B, t); + if (blend_type == "add") + Result = node_mix_add(t, A, B); + if (blend_type == "multiply") + Result = node_mix_mul(t, A, B); + if (blend_type == "screen") + Result = node_mix_screen(t, A, B); + if (blend_type == "overlay") + Result = node_mix_overlay(t, A, B); + if (blend_type == "subtract") + Result = node_mix_sub(t, A, B); + if (blend_type == "divide") + Result = node_mix_div(t, A, B); + if (blend_type == "difference") + Result = node_mix_diff(t, A, B); + if (blend_type == "darken") + Result = node_mix_dark(t, A, B); + if (blend_type == "lighten") + Result = node_mix_light(t, A, B); + if (blend_type == "dodge") + Result = node_mix_dodge(t, A, B); + if (blend_type == "burn") + Result = node_mix_burn(t, A, B); + if (blend_type == "hue") + Result = node_mix_hue(t, A, B); + if (blend_type == "saturation") + Result = node_mix_sat(t, A, B); + if (blend_type == "value") + Result = node_mix_val(t, A, B); + if (blend_type == "color") + Result = node_mix_color(t, A, B); + if (blend_type == "soft_light") + Result = node_mix_soft(t, A, B); + if (blend_type == "linear_light") + Result = node_mix_linear(t, A, B); + + if (use_clamp_result) + Result = clamp(Result, 0.0, 1.0); +} diff --git a/intern/cycles/kernel/osl/shaders/node_mix_float.osl b/intern/cycles/kernel/osl/shaders/node_mix_float.osl new file mode 100644 index 00000000000..fdc7b4eff6e --- /dev/null +++ b/intern/cycles/kernel/osl/shaders/node_mix_float.osl @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright 2011-2022 Blender Foundation */ + +#include "stdcycles.h" + +shader node_mix_float( + int use_clamp = 0, float Factor = 0.5, float A = 0.0, float B = 0.0, output float Result = 0.0) +{ + float t = (use_clamp) ? clamp(Factor, 0.0, 1.0) : Factor; + Result = mix(A, B, t); +} diff --git a/intern/cycles/kernel/osl/shaders/node_mix_vector.osl b/intern/cycles/kernel/osl/shaders/node_mix_vector.osl new file mode 100644 index 00000000000..d76396afb0d --- /dev/null +++ b/intern/cycles/kernel/osl/shaders/node_mix_vector.osl @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright 2011-2022 Blender Foundation */ + +#include "stdcycles.h" + +shader node_mix_vector(int use_clamp = 0, + float Factor = 0.5, + vector A = 0.0, + vector B = 0.0, + output vector Result = 0.0) +{ + float t = (use_clamp) ? clamp(Factor, 0.0, 1.0) : Factor; + Result = mix(A, B, t); +} diff --git a/intern/cycles/kernel/osl/shaders/node_mix_vector_non_uniform.osl b/intern/cycles/kernel/osl/shaders/node_mix_vector_non_uniform.osl new file mode 100644 index 00000000000..217856bcf2a --- /dev/null +++ b/intern/cycles/kernel/osl/shaders/node_mix_vector_non_uniform.osl @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright 2011-2022 Blender Foundation */ + +#include "stdcycles.h" + +shader node_mix_vector_non_uniform(int use_clamp = 0, + vector Factor = 0.5, + vector A = 0.0, + vector B = 0.0, + output vector Result = 0.0) +{ + vector t = (use_clamp) ? clamp(Factor, 0.0, 1.0) : Factor; + Result = mix(A, B, t); +} diff --git a/intern/cycles/kernel/svm/color_util.h b/intern/cycles/kernel/svm/color_util.h index 41f44378ff0..96adb6fd64c 100644 --- a/intern/cycles/kernel/svm/color_util.h +++ b/intern/cycles/kernel/svm/color_util.h @@ -247,10 +247,8 @@ ccl_device float3 svm_mix_clamp(float3 col) return saturate(col); } -ccl_device_noinline_cpu float3 svm_mix(NodeMix type, float fac, float3 c1, float3 c2) +ccl_device_noinline_cpu float3 svm_mix(NodeMix type, float t, float3 c1, float3 c2) { - float t = saturatef(fac); - switch (type) { case NODE_MIX_BLEND: return svm_mix_blend(t, c1, c2); @@ -282,7 +280,7 @@ ccl_device_noinline_cpu float3 svm_mix(NodeMix type, float fac, float3 c1, float return svm_mix_sat(t, c1, c2); case NODE_MIX_VAL: return svm_mix_val(t, c1, c2); - case NODE_MIX_COLOR: + case NODE_MIX_COL: return svm_mix_color(t, c1, c2); case NODE_MIX_SOFT: return svm_mix_soft(t, c1, c2); @@ -295,6 +293,12 @@ ccl_device_noinline_cpu float3 svm_mix(NodeMix type, float fac, float3 c1, float return make_float3(0.0f, 0.0f, 0.0f); } +ccl_device_noinline_cpu float3 svm_mix_clamped_factor(NodeMix type, float t, float3 c1, float3 c2) +{ + float fac = saturatef(t); + return svm_mix(type, fac, c1, c2); +} + ccl_device_inline float3 svm_brightness_contrast(float3 color, float brightness, float contrast) { float a = 1.0f + contrast; diff --git a/intern/cycles/kernel/svm/mix.h b/intern/cycles/kernel/svm/mix.h index a9796096410..ead2fc44685 100644 --- a/intern/cycles/kernel/svm/mix.h +++ b/intern/cycles/kernel/svm/mix.h @@ -21,10 +21,94 @@ ccl_device_noinline int svm_node_mix(KernelGlobals kg, float fac = stack_load_float(stack, fac_offset); float3 c1 = stack_load_float3(stack, c1_offset); float3 c2 = stack_load_float3(stack, c2_offset); - float3 result = svm_mix((NodeMix)node1.y, fac, c1, c2); + float3 result = svm_mix_clamped_factor((NodeMix)node1.y, fac, c1, c2); stack_store_float3(stack, node1.z, result); return offset; } +ccl_device_noinline void svm_node_mix_color(ccl_private ShaderData *sd, + ccl_private float *stack, + uint options, + uint input_offset, + uint result_offset) +{ + uint use_clamp, blend_type, use_clamp_result; + uint fac_in_stack_offset, a_in_stack_offset, b_in_stack_offset; + svm_unpack_node_uchar3(options, &use_clamp, &blend_type, &use_clamp_result); + svm_unpack_node_uchar3( + input_offset, &fac_in_stack_offset, &a_in_stack_offset, &b_in_stack_offset); + + float t = stack_load_float(stack, fac_in_stack_offset); + if (use_clamp > 0) { + t = saturatef(t); + } + float3 a = stack_load_float3(stack, a_in_stack_offset); + float3 b = stack_load_float3(stack, b_in_stack_offset); + float3 result = svm_mix((NodeMix)blend_type, t, a, b); + if (use_clamp_result) { + result = saturate(result); + } + stack_store_float3(stack, result_offset, result); +} + +ccl_device_noinline void svm_node_mix_float(ccl_private ShaderData *sd, + ccl_private float *stack, + uint use_clamp, + uint input_offset, + uint result_offset) +{ + uint fac_in_stack_offset, a_in_stack_offset, b_in_stack_offset; + svm_unpack_node_uchar3( + input_offset, &fac_in_stack_offset, &a_in_stack_offset, &b_in_stack_offset); + + float t = stack_load_float(stack, fac_in_stack_offset); + if (use_clamp > 0) { + t = saturatef(t); + } + float a = stack_load_float(stack, a_in_stack_offset); + float b = stack_load_float(stack, b_in_stack_offset); + float result = a * (1 - t) + b * t; + + stack_store_float(stack, result_offset, result); +} + +ccl_device_noinline void svm_node_mix_vector(ccl_private ShaderData *sd, + ccl_private float *stack, + uint input_offset, + uint result_offset) +{ + uint use_clamp, fac_in_stack_offset, a_in_stack_offset, b_in_stack_offset; + svm_unpack_node_uchar4( + input_offset, &use_clamp, &fac_in_stack_offset, &a_in_stack_offset, &b_in_stack_offset); + + float t = stack_load_float(stack, fac_in_stack_offset); + if (use_clamp > 0) { + t = saturatef(t); + } + float3 a = stack_load_float3(stack, a_in_stack_offset); + float3 b = stack_load_float3(stack, b_in_stack_offset); + float3 result = a * (one_float3() - t) + b * t; + stack_store_float3(stack, result_offset, result); +} + +ccl_device_noinline void svm_node_mix_vector_non_uniform(ccl_private ShaderData *sd, + ccl_private float *stack, + uint input_offset, + uint result_offset) +{ + uint use_clamp, fac_in_stack_offset, a_in_stack_offset, b_in_stack_offset; + svm_unpack_node_uchar4( + input_offset, &use_clamp, &fac_in_stack_offset, &a_in_stack_offset, &b_in_stack_offset); + + float3 t = stack_load_float3(stack, fac_in_stack_offset); + if (use_clamp > 0) { + t = saturate(t); + } + float3 a = stack_load_float3(stack, a_in_stack_offset); + float3 b = stack_load_float3(stack, b_in_stack_offset); + float3 result = a * (one_float3() - t) + b * t; + stack_store_float3(stack, result_offset, result); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/node_types_template.h b/intern/cycles/kernel/svm/node_types_template.h index 39d279be4cb..aab9b9f1158 100644 --- a/intern/cycles/kernel/svm/node_types_template.h +++ b/intern/cycles/kernel/svm/node_types_template.h @@ -103,6 +103,10 @@ SHADER_NODE_TYPE(NODE_AOV_START) SHADER_NODE_TYPE(NODE_AOV_COLOR) SHADER_NODE_TYPE(NODE_AOV_VALUE) SHADER_NODE_TYPE(NODE_FLOAT_CURVE) +SHADER_NODE_TYPE(NODE_MIX_COLOR) +SHADER_NODE_TYPE(NODE_MIX_FLOAT) +SHADER_NODE_TYPE(NODE_MIX_VECTOR) +SHADER_NODE_TYPE(NODE_MIX_VECTOR_NON_UNIFORM) /* Padding for struct alignment. */ SHADER_NODE_TYPE(NODE_PAD1) diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index 9d6d3e9222c..3ca632c5f0b 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -585,6 +585,18 @@ ccl_device void svm_eval_nodes(KernelGlobals kg, SVM_CASE(NODE_AOV_VALUE) svm_node_aov_value<node_feature_mask>(kg, state, sd, stack, node, render_buffer); break; + SVM_CASE(NODE_MIX_COLOR) + svm_node_mix_color(sd, stack, node.y, node.z, node.w); + break; + SVM_CASE(NODE_MIX_FLOAT) + svm_node_mix_float(sd, stack, node.y, node.z, node.w); + break; + SVM_CASE(NODE_MIX_VECTOR) + svm_node_mix_vector(sd, stack, node.y, node.z); + break; + SVM_CASE(NODE_MIX_VECTOR_NON_UNIFORM) + svm_node_mix_vector_non_uniform(sd, stack, node.y, node.z); + break; default: kernel_assert(!"Unknown node type was passed to the SVM machine"); return; diff --git a/intern/cycles/kernel/svm/types.h b/intern/cycles/kernel/svm/types.h index 98dfe6a4375..9dd8f196e0f 100644 --- a/intern/cycles/kernel/svm/types.h +++ b/intern/cycles/kernel/svm/types.h @@ -133,7 +133,7 @@ typedef enum NodeMix { NODE_MIX_HUE, NODE_MIX_SAT, NODE_MIX_VAL, - NODE_MIX_COLOR, + NODE_MIX_COL, NODE_MIX_SOFT, NODE_MIX_LINEAR, NODE_MIX_CLAMP /* used for the clamp UI option */ |