diff options
Diffstat (limited to 'intern')
-rw-r--r-- | intern/cycles/blender/shader.cpp | 17 | ||||
-rw-r--r-- | intern/cycles/kernel/osl/shaders/CMakeLists.txt | 1 | ||||
-rw-r--r-- | intern/cycles/kernel/osl/shaders/node_vector_map_range.osl | 74 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/map_range.h | 74 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm.h | 3 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/types.h | 1 | ||||
-rw-r--r-- | intern/cycles/scene/shader_nodes.cpp | 67 | ||||
-rw-r--r-- | intern/cycles/scene/shader_nodes.h | 15 |
8 files changed, 248 insertions, 4 deletions
diff --git a/intern/cycles/blender/shader.cpp b/intern/cycles/blender/shader.cpp index 0f17834906d..70acfce6891 100644 --- a/intern/cycles/blender/shader.cpp +++ b/intern/cycles/blender/shader.cpp @@ -378,10 +378,19 @@ static ShaderNode *add_node(Scene *scene, } else if (b_node.is_a(&RNA_ShaderNodeMapRange)) { BL::ShaderNodeMapRange b_map_range_node(b_node); - MapRangeNode *map_range_node = graph->create_node<MapRangeNode>(); - map_range_node->set_clamp(b_map_range_node.clamp()); - map_range_node->set_range_type((NodeMapRangeType)b_map_range_node.interpolation_type()); - node = map_range_node; + if (b_map_range_node.data_type() == BL::ShaderNodeMapRange::data_type_FLOAT_VECTOR) { + VectorMapRangeNode *vector_map_range_node = graph->create_node<VectorMapRangeNode>(); + vector_map_range_node->set_use_clamp(b_map_range_node.clamp()); + vector_map_range_node->set_range_type( + (NodeMapRangeType)b_map_range_node.interpolation_type()); + node = vector_map_range_node; + } + else { + MapRangeNode *map_range_node = graph->create_node<MapRangeNode>(); + map_range_node->set_clamp(b_map_range_node.clamp()); + map_range_node->set_range_type((NodeMapRangeType)b_map_range_node.interpolation_type()); + node = map_range_node; + } } else if (b_node.is_a(&RNA_ShaderNodeClamp)) { BL::ShaderNodeClamp b_clamp_node(b_node); diff --git a/intern/cycles/kernel/osl/shaders/CMakeLists.txt b/intern/cycles/kernel/osl/shaders/CMakeLists.txt index 6b62e7bb52f..4cafdb2a6d7 100644 --- a/intern/cycles/kernel/osl/shaders/CMakeLists.txt +++ b/intern/cycles/kernel/osl/shaders/CMakeLists.txt @@ -92,6 +92,7 @@ set(SRC_OSL node_value.osl node_vector_curves.osl node_vector_math.osl + node_vector_map_range.osl node_vector_rotate.osl node_vector_transform.osl node_velvet_bsdf.osl diff --git a/intern/cycles/kernel/osl/shaders/node_vector_map_range.osl b/intern/cycles/kernel/osl/shaders/node_vector_map_range.osl new file mode 100644 index 00000000000..1a59691fc45 --- /dev/null +++ b/intern/cycles/kernel/osl/shaders/node_vector_map_range.osl @@ -0,0 +1,74 @@ +/* + * Copyright 2011-2021 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "stdcycles.h" + +float safe_divide(float a, float b) +{ + return (b != 0.0) ? a / b : 0.0; +} + +point safe_divide(point a, point b) +{ + return point(safe_divide(a.x, b.x), safe_divide(a.y, b.y), safe_divide(a.z, b.z)); +} + +shader node_vector_map_range(string range_type = "linear", + int use_clamp = 0, + point VectorIn = point(1.0, 1.0, 1.0), + point From_Min_FLOAT3 = point(0.0, 0.0, 0.0), + point From_Max_FLOAT3 = point(1.0, 1.0, 1.0), + point To_Min_FLOAT3 = point(0.0, 0.0, 0.0), + point To_Max_FLOAT3 = point(1.0, 1.0, 1.0), + point Steps_FLOAT3 = point(4.0, 4.0, 4.0), + output point VectorOut = point(0.0, 0.0, 0.0)) +{ + point factor = VectorIn; + point from_min = From_Min_FLOAT3; + point from_max = From_Max_FLOAT3; + point to_min = To_Min_FLOAT3; + point to_max = To_Max_FLOAT3; + point steps = Steps_FLOAT3; + + if (range_type == "stepped") { + factor = safe_divide((factor - from_min), (from_max - from_min)); + factor = point((steps.x > 0.0) ? floor(factor.x * (steps.x + 1.0)) / steps.x : 0.0, + (steps.y > 0.0) ? floor(factor.y * (steps.y + 1.0)) / steps.y : 0.0, + (steps.z > 0.0) ? floor(factor.z * (steps.z + 1.0)) / steps.z : 0.0); + } + else if (range_type == "smoothstep") { + factor = safe_divide((factor - from_min), (from_max - from_min)); + factor = clamp(factor, 0.0, 1.0); + factor = (3.0 - 2.0 * factor) * (factor * factor); + } + else if (range_type == "smootherstep") { + factor = safe_divide((factor - from_min), (from_max - from_min)); + factor = clamp(factor, 0.0, 1.0); + factor = factor * factor * factor * (factor * (factor * 6.0 - 15.0) + 10.0); + } + else { + factor = safe_divide((factor - from_min), (from_max - from_min)); + } + VectorOut = to_min + factor * (to_max - to_min); + if (use_clamp > 0) { + VectorOut.x = (to_min.x > to_max.x) ? clamp(VectorOut.x, to_max.x, to_min.x) : + clamp(VectorOut.x, to_min.x, to_max.x); + VectorOut.y = (to_min.y > to_max.y) ? clamp(VectorOut.y, to_max.y, to_min.y) : + clamp(VectorOut.y, to_min.y, to_max.y); + VectorOut.z = (to_min.z > to_max.z) ? clamp(VectorOut.z, to_max.z, to_min.z) : + clamp(VectorOut.z, to_min.z, to_max.z); + } +} diff --git a/intern/cycles/kernel/svm/map_range.h b/intern/cycles/kernel/svm/map_range.h index fdbfc6531c4..bc5dcbd0238 100644 --- a/intern/cycles/kernel/svm/map_range.h +++ b/intern/cycles/kernel/svm/map_range.h @@ -88,4 +88,78 @@ ccl_device_noinline int svm_node_map_range(KernelGlobals kg, return offset; } +ccl_device_noinline int svm_node_vector_map_range(KernelGlobals kg, + ccl_private ShaderData *sd, + ccl_private float *stack, + uint value_stack_offset, + uint parameters_stack_offsets, + uint results_stack_offsets, + int offset) +{ + uint from_min_stack_offset, from_max_stack_offset, to_min_stack_offset, to_max_stack_offset; + uint steps_stack_offset, clamp_stack_offset, range_type_stack_offset, result_stack_offset; + svm_unpack_node_uchar4(parameters_stack_offsets, + &from_min_stack_offset, + &from_max_stack_offset, + &to_min_stack_offset, + &to_max_stack_offset); + svm_unpack_node_uchar4(results_stack_offsets, + &steps_stack_offset, + &clamp_stack_offset, + &range_type_stack_offset, + &result_stack_offset); + + float3 value = stack_load_float3(stack, value_stack_offset); + float3 from_min = stack_load_float3(stack, from_min_stack_offset); + float3 from_max = stack_load_float3(stack, from_max_stack_offset); + float3 to_min = stack_load_float3(stack, to_min_stack_offset); + float3 to_max = stack_load_float3(stack, to_max_stack_offset); + float3 steps = stack_load_float3(stack, steps_stack_offset); + + int type = range_type_stack_offset; + int use_clamp = (type == NODE_MAP_RANGE_SMOOTHSTEP || type == NODE_MAP_RANGE_SMOOTHERSTEP) ? + 0 : + clamp_stack_offset; + float3 result; + float3 factor = value; + switch (range_type_stack_offset) { + default: + case NODE_MAP_RANGE_LINEAR: + factor = safe_divide_float3_float3((value - from_min), (from_max - from_min)); + break; + case NODE_MAP_RANGE_STEPPED: { + factor = safe_divide_float3_float3((value - from_min), (from_max - from_min)); + factor = make_float3((steps.x > 0.0f) ? floorf(factor.x * (steps.x + 1.0f)) / steps.x : 0.0f, + (steps.y > 0.0f) ? floorf(factor.y * (steps.y + 1.0f)) / steps.y : 0.0f, + (steps.z > 0.0f) ? floorf(factor.z * (steps.z + 1.0f)) / steps.z : + 0.0f); + break; + } + case NODE_MAP_RANGE_SMOOTHSTEP: { + factor = safe_divide_float3_float3((value - from_min), (from_max - from_min)); + factor = clamp(factor, zero_float3(), one_float3()); + factor = (make_float3(3.0f) - 2.0f * factor) * (factor * factor); + break; + } + case NODE_MAP_RANGE_SMOOTHERSTEP: { + factor = safe_divide_float3_float3((value - from_min), (from_max - from_min)); + factor = clamp(factor, zero_float3(), one_float3()); + factor = factor * factor * factor * (factor * (factor * 6.0f - 15.0f) + 10.0f); + break; + } + } + result = to_min + factor * (to_max - to_min); + if (use_clamp > 0) { + result.x = (to_min.x > to_max.x) ? clamp(result.x, to_max.x, to_min.x) : + clamp(result.x, to_min.x, to_max.x); + result.y = (to_min.y > to_max.y) ? clamp(result.y, to_max.y, to_min.y) : + clamp(result.y, to_min.y, to_max.y); + result.z = (to_min.z > to_max.z) ? clamp(result.z, to_max.z, to_min.z) : + clamp(result.z, to_min.z, to_max.z); + } + + stack_store_float3(stack, result_stack_offset, result); + return offset; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index ce32e1a520f..b226bc66771 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -562,6 +562,9 @@ ccl_device void svm_eval_nodes(KernelGlobals kg, case NODE_MAP_RANGE: offset = svm_node_map_range(kg, sd, stack, node.y, node.z, node.w, offset); break; + case NODE_VECTOR_MAP_RANGE: + offset = svm_node_vector_map_range(kg, sd, stack, node.y, node.z, node.w, offset); + break; case NODE_CLAMP: offset = svm_node_clamp(kg, sd, stack, node.y, node.z, node.w, offset); break; diff --git a/intern/cycles/kernel/svm/types.h b/intern/cycles/kernel/svm/types.h index 8c95c571815..384549b7f09 100644 --- a/intern/cycles/kernel/svm/types.h +++ b/intern/cycles/kernel/svm/types.h @@ -114,6 +114,7 @@ typedef enum ShaderNodeType { NODE_WAVELENGTH, NODE_BLACKBODY, NODE_MAP_RANGE, + NODE_VECTOR_MAP_RANGE, NODE_CLAMP, NODE_BEVEL, NODE_AMBIENT_OCCLUSION, diff --git a/intern/cycles/scene/shader_nodes.cpp b/intern/cycles/scene/shader_nodes.cpp index 0ffeddc9f13..c345d5bbc9a 100644 --- a/intern/cycles/scene/shader_nodes.cpp +++ b/intern/cycles/scene/shader_nodes.cpp @@ -5871,6 +5871,73 @@ void MapRangeNode::compile(OSLCompiler &compiler) compiler.add(this, "node_map_range"); } +/* Vector Map Range Node */ + +NODE_DEFINE(VectorMapRangeNode) +{ + NodeType *type = NodeType::add("vector_map_range", create, NodeType::SHADER); + + static NodeEnum type_enum; + type_enum.insert("linear", NODE_MAP_RANGE_LINEAR); + type_enum.insert("stepped", NODE_MAP_RANGE_STEPPED); + type_enum.insert("smoothstep", NODE_MAP_RANGE_SMOOTHSTEP); + type_enum.insert("smootherstep", NODE_MAP_RANGE_SMOOTHERSTEP); + SOCKET_ENUM(range_type, "Type", type_enum, NODE_MAP_RANGE_LINEAR); + + SOCKET_IN_VECTOR(vector, "Vector", zero_float3()); + SOCKET_IN_VECTOR(from_min, "From_Min_FLOAT3", zero_float3()); + SOCKET_IN_VECTOR(from_max, "From_Max_FLOAT3", one_float3()); + SOCKET_IN_VECTOR(to_min, "To_Min_FLOAT3", zero_float3()); + SOCKET_IN_VECTOR(to_max, "To_Max_FLOAT3", one_float3()); + SOCKET_IN_VECTOR(steps, "Steps_FLOAT3", make_float3(4.0f)); + SOCKET_BOOLEAN(use_clamp, "Use Clamp", false); + + SOCKET_OUT_VECTOR(vector, "Vector"); + + return type; +} + +VectorMapRangeNode::VectorMapRangeNode() : ShaderNode(get_node_type()) +{ +} + +void VectorMapRangeNode::expand(ShaderGraph *graph) +{ +} + +void VectorMapRangeNode::compile(SVMCompiler &compiler) +{ + ShaderInput *vector_in = input("Vector"); + ShaderInput *from_min_in = input("From_Min_FLOAT3"); + ShaderInput *from_max_in = input("From_Max_FLOAT3"); + ShaderInput *to_min_in = input("To_Min_FLOAT3"); + ShaderInput *to_max_in = input("To_Max_FLOAT3"); + ShaderInput *steps_in = input("Steps_FLOAT3"); + ShaderOutput *vector_out = output("Vector"); + + int value_stack_offset = compiler.stack_assign(vector_in); + int from_min_stack_offset = compiler.stack_assign(from_min_in); + int from_max_stack_offset = compiler.stack_assign(from_max_in); + int to_min_stack_offset = compiler.stack_assign(to_min_in); + int to_max_stack_offset = compiler.stack_assign(to_max_in); + int steps_stack_offset = compiler.stack_assign(steps_in); + int result_stack_offset = compiler.stack_assign(vector_out); + + compiler.add_node( + NODE_VECTOR_MAP_RANGE, + value_stack_offset, + compiler.encode_uchar4( + from_min_stack_offset, from_max_stack_offset, to_min_stack_offset, to_max_stack_offset), + compiler.encode_uchar4(steps_stack_offset, use_clamp, range_type, result_stack_offset)); +} + +void VectorMapRangeNode::compile(OSLCompiler &compiler) +{ + compiler.parameter(this, "range_type"); + compiler.parameter(this, "use_clamp"); + compiler.add(this, "node_vector_map_range"); +} + /* Clamp Node */ NODE_DEFINE(ClampNode) diff --git a/intern/cycles/scene/shader_nodes.h b/intern/cycles/scene/shader_nodes.h index 64a2b1c7843..0faefd3041f 100644 --- a/intern/cycles/scene/shader_nodes.h +++ b/intern/cycles/scene/shader_nodes.h @@ -1263,6 +1263,21 @@ class BlackbodyNode : public ShaderNode { NODE_SOCKET_API(float, temperature) }; +class VectorMapRangeNode : public ShaderNode { + public: + SHADER_NODE_CLASS(VectorMapRangeNode) + void expand(ShaderGraph *graph); + + NODE_SOCKET_API(float3, vector) + NODE_SOCKET_API(float3, from_min) + NODE_SOCKET_API(float3, from_max) + NODE_SOCKET_API(float3, to_min) + NODE_SOCKET_API(float3, to_max) + NODE_SOCKET_API(float3, steps) + NODE_SOCKET_API(NodeMapRangeType, range_type) + NODE_SOCKET_API(bool, use_clamp) +}; + class MapRangeNode : public ShaderNode { public: SHADER_NODE_CLASS(MapRangeNode) |