Shading: Add Map Range node to Cycles and EEVEE.
This patch adds a new Map Range node that linearly remaps an input value from a range to another. This node is similar to the compositor's Map Range node. Reviewers: brecht, JacquesLucke Differential Revision: https://developer.blender.org/D5471
This commit is contained in:
parent
aef08fda3a
commit
71641ab56d
|
@ -315,6 +315,9 @@ static ShaderNode *add_node(Scene *scene,
|
|||
else if (b_node.is_a(&RNA_ShaderNodeRGBToBW)) {
|
||||
node = new RGBToBWNode();
|
||||
}
|
||||
else if (b_node.is_a(&RNA_ShaderNodeMapRange)) {
|
||||
node = new MapRangeNode();
|
||||
}
|
||||
else if (b_node.is_a(&RNA_ShaderNodeMath)) {
|
||||
BL::ShaderNodeMath b_math_node(b_node);
|
||||
MathNode *math = new MathNode();
|
||||
|
|
|
@ -198,6 +198,7 @@ set(SRC_SVM_HEADERS
|
|||
svm/svm_invert.h
|
||||
svm/svm_light_path.h
|
||||
svm/svm_magic.h
|
||||
svm/svm_map_range.h
|
||||
svm/svm_mapping.h
|
||||
svm/svm_math.h
|
||||
svm/svm_math_util.h
|
||||
|
|
|
@ -46,6 +46,7 @@ set(SRC_OSL
|
|||
node_light_falloff.osl
|
||||
node_light_path.osl
|
||||
node_magic_texture.osl
|
||||
node_map_range.osl
|
||||
node_mapping.osl
|
||||
node_math.osl
|
||||
node_mix.osl
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright 2011-2013 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 "stdosl.h"
|
||||
|
||||
shader node_map_range(float Value = 1.0, float FromMin = 0.0, float FromMax = 1.0,
|
||||
float ToMin = 0.0, float ToMax = 1.0, output float Result = 0.0)
|
||||
{
|
||||
if (FromMax != FromMin) {
|
||||
Result = ToMin + ((Value - FromMin) / (FromMax - FromMin)) * (ToMax - ToMin);
|
||||
}
|
||||
}
|
|
@ -192,6 +192,7 @@ CCL_NAMESPACE_END
|
|||
#include "kernel/svm/svm_vector_transform.h"
|
||||
#include "kernel/svm/svm_voxel.h"
|
||||
#include "kernel/svm/svm_bump.h"
|
||||
#include "kernel/svm/svm_map_range.h"
|
||||
|
||||
#ifdef __SHADER_RAYTRACE__
|
||||
# include "kernel/svm/svm_ao.h"
|
||||
|
@ -486,6 +487,9 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg,
|
|||
case NODE_BLACKBODY:
|
||||
svm_node_blackbody(kg, sd, stack, node.y, node.z);
|
||||
break;
|
||||
case NODE_MAP_RANGE:
|
||||
svm_node_map_range(kg, sd, stack, node.y, node.z, node.w, &offset);
|
||||
break;
|
||||
# endif /* __EXTRA_NODES__ */
|
||||
# if NODES_FEATURE(NODE_FEATURE_VOLUME)
|
||||
case NODE_TEX_VOXEL:
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright 2011-2013 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.
|
||||
*/
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Map Range Node */
|
||||
|
||||
ccl_device void svm_node_map_range(KernelGlobals *kg,
|
||||
ShaderData *sd,
|
||||
float *stack,
|
||||
uint value_stack_offset,
|
||||
uint parameters_stack_offsets,
|
||||
uint result_stack_offset,
|
||||
int *offset)
|
||||
{
|
||||
uint from_min_stack_offset, from_max_stack_offset, to_min_stack_offset, to_max_stack_offset;
|
||||
decode_node_uchar4(parameters_stack_offsets,
|
||||
&from_min_stack_offset,
|
||||
&from_max_stack_offset,
|
||||
&to_min_stack_offset,
|
||||
&to_max_stack_offset);
|
||||
|
||||
uint4 defaults = read_node(kg, offset);
|
||||
|
||||
float value = stack_load_float(stack, value_stack_offset);
|
||||
float from_min = stack_load_float_default(stack, from_min_stack_offset, defaults.x);
|
||||
float from_max = stack_load_float_default(stack, from_max_stack_offset, defaults.y);
|
||||
float to_min = stack_load_float_default(stack, to_min_stack_offset, defaults.z);
|
||||
float to_max = stack_load_float_default(stack, to_max_stack_offset, defaults.w);
|
||||
|
||||
float result;
|
||||
if (from_max != from_min) {
|
||||
result = to_min + ((value - from_min) / (from_max - from_min)) * (to_max - to_min);
|
||||
}
|
||||
else {
|
||||
result = 0.0f;
|
||||
}
|
||||
stack_store_float(stack, result_stack_offset, result);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
|
@ -138,6 +138,7 @@ typedef enum ShaderNodeType {
|
|||
NODE_VECTOR_DISPLACEMENT,
|
||||
NODE_PRINCIPLED_VOLUME,
|
||||
NODE_IES,
|
||||
NODE_MAP_RANGE,
|
||||
} ShaderNodeType;
|
||||
|
||||
typedef enum NodeAttributeType {
|
||||
|
|
|
@ -5259,6 +5259,75 @@ void OutputNode::compile(OSLCompiler &compiler)
|
|||
compiler.add(this, "node_output_displacement");
|
||||
}
|
||||
|
||||
/* Map Range Node */
|
||||
|
||||
NODE_DEFINE(MapRangeNode)
|
||||
{
|
||||
NodeType *type = NodeType::add("map_range", create, NodeType::SHADER);
|
||||
|
||||
SOCKET_IN_FLOAT(value, "Value", 1.0f);
|
||||
SOCKET_IN_FLOAT(from_min, "From Min", 0.0f);
|
||||
SOCKET_IN_FLOAT(from_max, "From Max", 1.0f);
|
||||
SOCKET_IN_FLOAT(to_min, "To Min", 0.0f);
|
||||
SOCKET_IN_FLOAT(to_max, "To Max", 1.0f);
|
||||
|
||||
SOCKET_OUT_FLOAT(result, "Result");
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
MapRangeNode::MapRangeNode() : ShaderNode(node_type)
|
||||
{
|
||||
}
|
||||
|
||||
void MapRangeNode::constant_fold(const ConstantFolder &folder)
|
||||
{
|
||||
if (folder.all_inputs_constant()) {
|
||||
float result;
|
||||
if (from_max != from_min) {
|
||||
result = to_min + ((value - from_min) / (from_max - from_min)) * (to_max - to_min);
|
||||
}
|
||||
else {
|
||||
result = 0.0f;
|
||||
}
|
||||
folder.make_constant(result);
|
||||
}
|
||||
}
|
||||
|
||||
void MapRangeNode::compile(SVMCompiler &compiler)
|
||||
{
|
||||
ShaderInput *value_in = input("Value");
|
||||
ShaderInput *from_min_in = input("From Min");
|
||||
ShaderInput *from_max_in = input("From Max");
|
||||
ShaderInput *to_min_in = input("To Min");
|
||||
ShaderInput *to_max_in = input("To Max");
|
||||
ShaderOutput *result_out = output("Result");
|
||||
|
||||
int value_stack_offset = compiler.stack_assign(value_in);
|
||||
int from_min_stack_offset = compiler.stack_assign_if_linked(from_min_in);
|
||||
int from_max_stack_offset = compiler.stack_assign_if_linked(from_max_in);
|
||||
int to_min_stack_offset = compiler.stack_assign_if_linked(to_min_in);
|
||||
int to_max_stack_offset = compiler.stack_assign_if_linked(to_max_in);
|
||||
int result_stack_offset = compiler.stack_assign(result_out);
|
||||
|
||||
compiler.add_node(
|
||||
NODE_MAP_RANGE,
|
||||
value_stack_offset,
|
||||
compiler.encode_uchar4(
|
||||
from_min_stack_offset, from_max_stack_offset, to_min_stack_offset, to_max_stack_offset),
|
||||
result_stack_offset);
|
||||
|
||||
compiler.add_node(__float_as_int(from_min),
|
||||
__float_as_int(from_max),
|
||||
__float_as_int(to_min),
|
||||
__float_as_int(to_max));
|
||||
}
|
||||
|
||||
void MapRangeNode::compile(OSLCompiler &compiler)
|
||||
{
|
||||
compiler.add(this, "node_map_range");
|
||||
}
|
||||
|
||||
/* Math */
|
||||
|
||||
NODE_DEFINE(MathNode)
|
||||
|
|
|
@ -1228,6 +1228,17 @@ class BlackbodyNode : public ShaderNode {
|
|||
float temperature;
|
||||
};
|
||||
|
||||
class MapRangeNode : public ShaderNode {
|
||||
public:
|
||||
SHADER_NODE_CLASS(MapRangeNode)
|
||||
void constant_fold(const ConstantFolder &folder);
|
||||
virtual int get_group()
|
||||
{
|
||||
return NODE_GROUP_LEVEL_3;
|
||||
}
|
||||
float value, from_min, from_max, to_min, to_max;
|
||||
};
|
||||
|
||||
class MathNode : public ShaderNode {
|
||||
public:
|
||||
SHADER_NODE_CLASS(MathNode)
|
||||
|
|
|
@ -258,6 +258,7 @@ shader_node_categories = [
|
|||
NodeItem("ShaderNodeVectorTransform"),
|
||||
]),
|
||||
ShaderNodeCategory("SH_NEW_CONVERTOR", "Converter", items=[
|
||||
NodeItem("ShaderNodeMapRange"),
|
||||
NodeItem("ShaderNodeMath"),
|
||||
NodeItem("ShaderNodeValToRGB"),
|
||||
NodeItem("ShaderNodeRGBToBW"),
|
||||
|
|
|
@ -976,6 +976,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree,
|
|||
#define SH_NODE_VOLUME_PRINCIPLED 200
|
||||
/* 201..700 occupied by other node types, continue from 701 */
|
||||
#define SH_NODE_BSDF_HAIR_PRINCIPLED 701
|
||||
#define SH_NODE_MAP_RANGE 702
|
||||
|
||||
/* custom defines options for Material node */
|
||||
#define SH_NODE_MAT_DIFF 1
|
||||
|
|
|
@ -3856,6 +3856,7 @@ static void registerShaderNodes(void)
|
|||
register_node_type_sh_mapping();
|
||||
register_node_type_sh_curve_vec();
|
||||
register_node_type_sh_curve_rgb();
|
||||
register_node_type_sh_map_range();
|
||||
register_node_type_sh_math();
|
||||
register_node_type_sh_vect_math();
|
||||
register_node_type_sh_vect_transform();
|
||||
|
|
|
@ -429,6 +429,17 @@ void squeeze(float val, float width, float center, out float outval)
|
|||
outval = 1.0 / (1.0 + pow(2.71828183, -((val - center) * width)));
|
||||
}
|
||||
|
||||
void map_range(
|
||||
float value, float fromMin, float fromMax, float toMin, float toMax, out float result)
|
||||
{
|
||||
if (fromMax != fromMin) {
|
||||
result = toMin + ((value - fromMin) / (fromMax - fromMin)) * (toMax - toMin);
|
||||
}
|
||||
else {
|
||||
result = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
void vec_math_add(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
|
||||
{
|
||||
outvec = v1 + v2;
|
||||
|
|
|
@ -163,6 +163,7 @@ set(SRC
|
|||
shader/nodes/node_shader_layer_weight.c
|
||||
shader/nodes/node_shader_light_falloff.c
|
||||
shader/nodes/node_shader_light_path.c
|
||||
shader/nodes/node_shader_map_range.c
|
||||
shader/nodes/node_shader_mapping.c
|
||||
shader/nodes/node_shader_math.c
|
||||
shader/nodes/node_shader_mixRgb.c
|
||||
|
|
|
@ -48,6 +48,7 @@ void register_node_type_sh_brightcontrast(void);
|
|||
void register_node_type_sh_mapping(void);
|
||||
void register_node_type_sh_curve_vec(void);
|
||||
void register_node_type_sh_curve_rgb(void);
|
||||
void register_node_type_sh_map_range(void);
|
||||
void register_node_type_sh_math(void);
|
||||
void register_node_type_sh_vect_math(void);
|
||||
void register_node_type_sh_squeeze(void);
|
||||
|
|
|
@ -50,6 +50,7 @@ DefNode(ShaderNode, SH_NODE_MAPPING, def_sh_mapping, "MAPPIN
|
|||
DefNode(ShaderNode, SH_NODE_CURVE_VEC, def_vector_curve, "CURVE_VEC", VectorCurve, "Vector Curves", "" )
|
||||
DefNode(ShaderNode, SH_NODE_CURVE_RGB, def_rgb_curve, "CURVE_RGB", RGBCurve, "RGB Curves", "" )
|
||||
DefNode(ShaderNode, SH_NODE_CAMERA, 0, "CAMERA", CameraData, "Camera Data", "" )
|
||||
DefNode(ShaderNode, SH_NODE_MAP_RANGE, 0, "MAP_RANGE", MapRange, "Map Range", "" )
|
||||
DefNode(ShaderNode, SH_NODE_MATH, def_math, "MATH", Math, "Math", "" )
|
||||
DefNode(ShaderNode, SH_NODE_VECT_MATH, def_vector_math, "VECT_MATH", VectorMath, "Vector Math", "" )
|
||||
DefNode(ShaderNode, SH_NODE_SQUEEZE, 0, "SQUEEZE", Squeeze, "Squeeze Value", "" )
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2005 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup shdnodes
|
||||
*/
|
||||
|
||||
#include "node_shader_util.h"
|
||||
|
||||
/* **************** Map Range ******************** */
|
||||
static bNodeSocketTemplate sh_node_map_range_in[] = {
|
||||
{SOCK_FLOAT, 1, N_("Value"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE},
|
||||
{SOCK_FLOAT, 1, N_("From Min"), 0.0f, 1.0f, 1.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE},
|
||||
{SOCK_FLOAT, 1, N_("From Max"), 1.0f, 1.0f, 1.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE},
|
||||
{SOCK_FLOAT, 1, N_("To Min"), 0.0f, 1.0f, 1.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE},
|
||||
{SOCK_FLOAT, 1, N_("To Max"), 1.0f, 1.0f, 1.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE},
|
||||
{-1, 0, ""},
|
||||
};
|
||||
static bNodeSocketTemplate sh_node_map_range_out[] = {
|
||||
{SOCK_FLOAT, 0, N_("Result")},
|
||||
{-1, 0, ""},
|
||||
};
|
||||
|
||||
static int gpu_shader_map_range(GPUMaterial *mat,
|
||||
bNode *node,
|
||||
bNodeExecData *UNUSED(execdata),
|
||||
GPUNodeStack *in,
|
||||
GPUNodeStack *out)
|
||||
{
|
||||
return GPU_stack_link(mat, node, "map_range", in, out);
|
||||
}
|
||||
|
||||
void register_node_type_sh_map_range(void)
|
||||
{
|
||||
static bNodeType ntype;
|
||||
|
||||
sh_node_type_base(&ntype, SH_NODE_MAP_RANGE, "Map Range", NODE_CLASS_CONVERTOR, 0);
|
||||
node_type_socket_templates(&ntype, sh_node_map_range_in, sh_node_map_range_out);
|
||||
node_type_gpu(&ntype, gpu_shader_map_range);
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
Loading…
Reference in New Issue