Shading: Add Clamp node to Cycles and EEVEE.

This patch adds a new node that clamps a value between a maximum and
a minimum values.

Reviewers: brecht

Differential Revision: https://developer.blender.org/D5476
This commit is contained in:
OmarSquircleArt 2019-08-13 22:22:15 +02:00
parent 42798a5ca1
commit 313b789289
Notes: blender-bot 2023-02-14 01:14:32 +01:00
Referenced by issue #68630, Cant select oblects in the viewport or the scene outliner
18 changed files with 200 additions and 3 deletions

View File

@ -318,6 +318,9 @@ static ShaderNode *add_node(Scene *scene,
else if (b_node.is_a(&RNA_ShaderNodeMapRange)) {
node = new MapRangeNode();
}
else if (b_node.is_a(&RNA_ShaderNodeClamp)) {
node = new ClampNode();
}
else if (b_node.is_a(&RNA_ShaderNodeMath)) {
BL::ShaderNodeMath b_math_node(b_node);
MathNode *math = new MathNode();

View File

@ -179,6 +179,7 @@ set(SRC_SVM_HEADERS
svm/svm_blackbody.h
svm/svm_bump.h
svm/svm_camera.h
svm/svm_clamp.h
svm/svm_closure.h
svm/svm_convert.h
svm/svm_checker.h

View File

@ -13,6 +13,7 @@ set(SRC_OSL
node_bump.osl
node_camera.osl
node_checker_texture.osl
node_clamp.osl
node_combine_rgb.osl
node_combine_hsv.osl
node_combine_xyz.osl

View File

@ -0,0 +1,23 @@
/*
* 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_clamp(float Value = 1.0, float Min = 0.0, float Max = 1.0,
output float Result = 0.0)
{
Result = clamp(Value, Min, Max);
}

View File

@ -193,6 +193,7 @@ CCL_NAMESPACE_END
#include "kernel/svm/svm_voxel.h"
#include "kernel/svm/svm_bump.h"
#include "kernel/svm/svm_map_range.h"
#include "kernel/svm/svm_clamp.h"
#ifdef __SHADER_RAYTRACE__
# include "kernel/svm/svm_ao.h"
@ -490,6 +491,9 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg,
case NODE_MAP_RANGE:
svm_node_map_range(kg, sd, stack, node.y, node.z, node.w, &offset);
break;
case NODE_CLAMP:
svm_node_clamp(kg, sd, stack, node.y, node.z, node.w, &offset);
break;
# endif /* __EXTRA_NODES__ */
# if NODES_FEATURE(NODE_FEATURE_VOLUME)
case NODE_TEX_VOXEL:

View File

@ -0,0 +1,41 @@
/*
* 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
/* Clamp Node */
ccl_device void svm_node_clamp(KernelGlobals *kg,
ShaderData *sd,
float *stack,
uint value_stack_offset,
uint parameters_stack_offsets,
uint result_stack_offset,
int *offset)
{
uint min_stack_offset, max_stack_offset;
decode_node_uchar4(parameters_stack_offsets, &min_stack_offset, &max_stack_offset, NULL, NULL);
uint4 defaults = read_node(kg, offset);
float value = stack_load_float(stack, value_stack_offset);
float min = stack_load_float_default(stack, min_stack_offset, defaults.x);
float max = stack_load_float_default(stack, max_stack_offset, defaults.y);
stack_store_float(stack, result_stack_offset, clamp(value, min, max));
}
CCL_NAMESPACE_END

View File

@ -139,6 +139,7 @@ typedef enum ShaderNodeType {
NODE_PRINCIPLED_VOLUME,
NODE_IES,
NODE_MAP_RANGE,
NODE_CLAMP,
} ShaderNodeType;
typedef enum NodeAttributeType {

View File

@ -5328,6 +5328,56 @@ void MapRangeNode::compile(OSLCompiler &compiler)
compiler.add(this, "node_map_range");
}
/* Clamp Node */
NODE_DEFINE(ClampNode)
{
NodeType *type = NodeType::add("clamp", create, NodeType::SHADER);
SOCKET_IN_FLOAT(value, "Value", 1.0f);
SOCKET_IN_FLOAT(min, "Min", 0.0f);
SOCKET_IN_FLOAT(max, "Max", 1.0f);
SOCKET_OUT_FLOAT(result, "Result");
return type;
}
ClampNode::ClampNode() : ShaderNode(node_type)
{
}
void ClampNode::constant_fold(const ConstantFolder &folder)
{
if (folder.all_inputs_constant()) {
folder.make_constant(clamp(value, min, max));
}
}
void ClampNode::compile(SVMCompiler &compiler)
{
ShaderInput *value_in = input("Value");
ShaderInput *min_in = input("Min");
ShaderInput *max_in = input("Max");
ShaderOutput *result_out = output("Result");
int value_stack_offset = compiler.stack_assign(value_in);
int min_stack_offset = compiler.stack_assign(min_in);
int max_stack_offset = compiler.stack_assign(max_in);
int result_stack_offset = compiler.stack_assign(result_out);
compiler.add_node(NODE_CLAMP,
value_stack_offset,
compiler.encode_uchar4(min_stack_offset, max_stack_offset),
result_stack_offset);
compiler.add_node(__float_as_int(min), __float_as_int(max));
}
void ClampNode::compile(OSLCompiler &compiler)
{
compiler.add(this, "node_clamp");
}
/* Math */
NODE_DEFINE(MathNode)

View File

@ -1239,6 +1239,17 @@ class MapRangeNode : public ShaderNode {
float value, from_min, from_max, to_min, to_max;
};
class ClampNode : public ShaderNode {
public:
SHADER_NODE_CLASS(ClampNode)
void constant_fold(const ConstantFolder &folder);
virtual int get_group()
{
return NODE_GROUP_LEVEL_3;
}
float value, min, max;
};
class MathNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MathNode)

View File

@ -259,6 +259,7 @@ shader_node_categories = [
]),
ShaderNodeCategory("SH_NEW_CONVERTOR", "Converter", items=[
NodeItem("ShaderNodeMapRange"),
NodeItem("ShaderNodeClamp"),
NodeItem("ShaderNodeMath"),
NodeItem("ShaderNodeValToRGB"),
NodeItem("ShaderNodeRGBToBW"),

View File

@ -977,6 +977,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree,
/* 201..700 occupied by other node types, continue from 701 */
#define SH_NODE_BSDF_HAIR_PRINCIPLED 701
#define SH_NODE_MAP_RANGE 702
#define SH_NODE_CLAMP 703
/* custom defines options for Material node */
#define SH_NODE_MAT_DIFF 1

View File

@ -3857,6 +3857,7 @@ static void registerShaderNodes(void)
register_node_type_sh_curve_vec();
register_node_type_sh_curve_rgb();
register_node_type_sh_map_range();
register_node_type_sh_clamp();
register_node_type_sh_math();
register_node_type_sh_vect_math();
register_node_type_sh_vect_transform();

View File

@ -971,9 +971,9 @@ void clamp_vec3(vec3 vec, vec3 min, vec3 max, out vec3 out_vec)
out_vec = clamp(vec, min, max);
}
void clamp_val(float value, float min, float max, out float out_value)
void clamp_value(float value, float min, float max, out float result)
{
out_value = clamp(value, min, max);
result = clamp(value, min, max);
}
void hue_sat(float hue, float sat, float value, float fac, vec4 col, out vec4 outcol)

View File

@ -147,6 +147,7 @@ set(SRC
shader/nodes/node_shader_bsdf_velvet.c
shader/nodes/node_shader_bump.c
shader/nodes/node_shader_camera.c
shader/nodes/node_shader_clamp.c
shader/nodes/node_shader_common.c
shader/nodes/node_shader_curves.c
shader/nodes/node_shader_displacement.c

View File

@ -49,6 +49,7 @@ 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_clamp(void);
void register_node_type_sh_math(void);
void register_node_type_sh_vect_math(void);
void register_node_type_sh_squeeze(void);

View File

@ -51,6 +51,7 @@ DefNode(ShaderNode, SH_NODE_CURVE_VEC, def_vector_curve, "CURVE_
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_CLAMP, 0, "CLAMP", Clamp, "Clamp", "" )
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", "" )

View File

@ -0,0 +1,56 @@
/*
* 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"
/* **************** Clamp ******************** */
static bNodeSocketTemplate sh_node_clamp_in[] = {
{SOCK_FLOAT, 1, N_("Value"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE},
{SOCK_FLOAT, 1, N_("Min"), 0.0f, 1.0f, 1.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE},
{SOCK_FLOAT, 1, N_("Max"), 1.0f, 1.0f, 1.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE},
{-1, 0, ""},
};
static bNodeSocketTemplate sh_node_clamp_out[] = {
{SOCK_FLOAT, 0, N_("Result")},
{-1, 0, ""},
};
static int gpu_shader_clamp(GPUMaterial *mat,
bNode *node,
bNodeExecData *UNUSED(execdata),
GPUNodeStack *in,
GPUNodeStack *out)
{
return GPU_stack_link(mat, node, "clamp_value", in, out);
}
void register_node_type_sh_clamp(void)
{
static bNodeType ntype;
sh_node_type_base(&ntype, SH_NODE_CLAMP, "Clamp", NODE_CLASS_CONVERTOR, 0);
node_type_socket_templates(&ntype, sh_node_clamp_in, sh_node_clamp_out);
node_type_gpu(&ntype, gpu_shader_clamp);
nodeRegisterType(&ntype);
}

View File

@ -360,7 +360,7 @@ static int gpu_shader_math(GPUMaterial *mat,
if (node->custom2 & SHD_MATH_CLAMP) {
float min[3] = {0.0f, 0.0f, 0.0f};
float max[3] = {1.0f, 1.0f, 1.0f};
GPU_link(mat, "clamp_val", out[0].link, GPU_constant(min), GPU_constant(max), &out[0].link);
GPU_link(mat, "clamp_value", out[0].link, GPU_constant(min), GPU_constant(max), &out[0].link);
}
return 1;