forked from bartvdbraak/blender
Shader Nodes: Add Interpolation modes to Map Range node
Modes: Linear interpolation (default), stepped linear, smoothstep and smootherstep. This also includes an additional option for the **Clamp node** to switch between **Min Max** (default) and **Range** mode. This was needed to allow clamping when **To Max** is less than **To Min**. Reviewed By: JacquesLucke, brecht Differential Revision: https://developer.blender.org/D5827
This commit is contained in:
parent
0406eb1103
commit
958d0d4236
@ -301,10 +301,14 @@ static ShaderNode *add_node(Scene *scene,
|
||||
BL::ShaderNodeMapRange b_map_range_node(b_node);
|
||||
MapRangeNode *map_range_node = new MapRangeNode();
|
||||
map_range_node->clamp = b_map_range_node.clamp();
|
||||
map_range_node->type = (NodeMapRangeType)b_map_range_node.interpolation_type();
|
||||
node = map_range_node;
|
||||
}
|
||||
else if (b_node.is_a(&RNA_ShaderNodeClamp)) {
|
||||
node = new ClampNode();
|
||||
BL::ShaderNodeClamp b_clamp_node(b_node);
|
||||
ClampNode *clamp_node = new ClampNode();
|
||||
clamp_node->type = (NodeClampType)b_clamp_node.clamp_type();
|
||||
node = clamp_node;
|
||||
}
|
||||
else if (b_node.is_a(&RNA_ShaderNodeMath)) {
|
||||
BL::ShaderNodeMath b_math_node(b_node);
|
||||
|
@ -16,7 +16,11 @@
|
||||
|
||||
#include "stdosl.h"
|
||||
|
||||
shader node_clamp(float Value = 1.0, float Min = 0.0, float Max = 1.0, output float Result = 0.0)
|
||||
shader node_clamp(string type = "minmax",
|
||||
float Value = 1.0,
|
||||
float Min = 0.0,
|
||||
float Max = 1.0,
|
||||
output float Result = 0.0)
|
||||
{
|
||||
Result = clamp(Value, Min, Max);
|
||||
Result = (type == "range" && (Min > Max)) ? clamp(Value, Max, Min) : clamp(Value, Min, Max);
|
||||
}
|
||||
|
@ -16,14 +16,43 @@
|
||||
|
||||
#include "stdosl.h"
|
||||
|
||||
shader node_map_range(float Value = 1.0,
|
||||
float safe_divide(float a, float b)
|
||||
{
|
||||
return (b != 0.0) ? a / b : 0.0;
|
||||
}
|
||||
|
||||
float smootherstep(float edge0, float edge1, float x)
|
||||
{
|
||||
float t = clamp(safe_divide((x - edge0), (edge1 - edge0)), 0.0, 1.0);
|
||||
return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);
|
||||
}
|
||||
|
||||
shader node_map_range(string type = "linear",
|
||||
float Value = 1.0,
|
||||
float FromMin = 0.0,
|
||||
float FromMax = 1.0,
|
||||
float ToMin = 0.0,
|
||||
float ToMax = 1.0,
|
||||
float Steps = 4.0,
|
||||
output float Result = 0.0)
|
||||
{
|
||||
if (FromMax != FromMin) {
|
||||
Result = ToMin + ((Value - FromMin) / (FromMax - FromMin)) * (ToMax - ToMin);
|
||||
float Factor = Value;
|
||||
if (type == "stepped") {
|
||||
Factor = (Value - FromMin) / (FromMax - FromMin);
|
||||
Factor = (Steps > 0) ? floor(Factor * (Steps + 1.0)) / Steps : 0.0;
|
||||
}
|
||||
else if (type == "smoothstep") {
|
||||
Factor = (FromMin > FromMax) ? 1.0 - smoothstep(FromMax, FromMin, Value) :
|
||||
smoothstep(FromMin, FromMax, Value);
|
||||
}
|
||||
else if (type == "smootherstep") {
|
||||
Factor = (FromMin > FromMax) ? 1.0 - smootherstep(FromMax, FromMin, Value) :
|
||||
smootherstep(FromMin, FromMax, Value);
|
||||
}
|
||||
else {
|
||||
Factor = (Value - FromMin) / (FromMax - FromMin);
|
||||
}
|
||||
Result = ToMin + Factor * (ToMax - ToMin);
|
||||
}
|
||||
}
|
||||
|
@ -26,8 +26,8 @@ ccl_device void svm_node_clamp(KernelGlobals *kg,
|
||||
uint result_stack_offset,
|
||||
int *offset)
|
||||
{
|
||||
uint min_stack_offset, max_stack_offset;
|
||||
svm_unpack_node_uchar2(parameters_stack_offsets, &min_stack_offset, &max_stack_offset);
|
||||
uint min_stack_offset, max_stack_offset, type;
|
||||
svm_unpack_node_uchar3(parameters_stack_offsets, &min_stack_offset, &max_stack_offset, &type);
|
||||
|
||||
uint4 defaults = read_node(kg, offset);
|
||||
|
||||
@ -35,7 +35,12 @@ ccl_device void svm_node_clamp(KernelGlobals *kg,
|
||||
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));
|
||||
if (type == NODE_CLAMP_RANGE && (min > max)) {
|
||||
stack_store_float(stack, result_stack_offset, clamp(value, max, min));
|
||||
}
|
||||
else {
|
||||
stack_store_float(stack, result_stack_offset, clamp(value, min, max));
|
||||
}
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@ -18,32 +18,66 @@ CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Map Range Node */
|
||||
|
||||
ccl_device_inline float smootherstep(float edge0, float edge1, float x)
|
||||
{
|
||||
x = clamp(safe_divide((x - edge0), (edge1 - edge0)), 0.0f, 1.0f);
|
||||
return x * x * x * (x * (x * 6.0f - 15.0f) + 10.0f);
|
||||
}
|
||||
|
||||
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,
|
||||
uint results_stack_offsets,
|
||||
int *offset)
|
||||
{
|
||||
uint from_min_stack_offset, from_max_stack_offset, to_min_stack_offset, to_max_stack_offset;
|
||||
uint type_stack_offset, steps_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_uchar3(
|
||||
results_stack_offsets, &type_stack_offset, &steps_stack_offset, &result_stack_offset);
|
||||
|
||||
uint4 defaults = read_node(kg, offset);
|
||||
uint4 defaults2 = 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 steps = stack_load_float_default(stack, steps_stack_offset, defaults2.x);
|
||||
|
||||
float result;
|
||||
|
||||
if (from_max != from_min) {
|
||||
result = to_min + ((value - from_min) / (from_max - from_min)) * (to_max - to_min);
|
||||
float factor = value;
|
||||
switch (type_stack_offset) {
|
||||
default:
|
||||
case NODE_MAP_RANGE_LINEAR:
|
||||
factor = (value - from_min) / (from_max - from_min);
|
||||
break;
|
||||
case NODE_MAP_RANGE_STEPPED: {
|
||||
factor = (value - from_min) / (from_max - from_min);
|
||||
factor = (steps > 0.0f) ? floorf(factor * (steps + 1.0f)) / steps : 0.0f;
|
||||
break;
|
||||
}
|
||||
case NODE_MAP_RANGE_SMOOTHSTEP: {
|
||||
factor = (from_min > from_max) ? 1.0f - smoothstep(from_max, from_min, factor) :
|
||||
smoothstep(from_min, from_max, factor);
|
||||
break;
|
||||
}
|
||||
case NODE_MAP_RANGE_SMOOTHERSTEP: {
|
||||
factor = (from_min > from_max) ? 1.0f - smootherstep(from_max, from_min, factor) :
|
||||
smootherstep(from_min, from_max, factor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
result = to_min + factor * (to_max - to_min);
|
||||
}
|
||||
else {
|
||||
result = 0.0f;
|
||||
|
@ -325,6 +325,18 @@ typedef enum NodeVectorMathType {
|
||||
NODE_VECTOR_MATH_MAXIMUM,
|
||||
} NodeVectorMathType;
|
||||
|
||||
typedef enum NodeClampType {
|
||||
NODE_CLAMP_MINMAX,
|
||||
NODE_CLAMP_RANGE,
|
||||
} NodeClampType;
|
||||
|
||||
typedef enum NodeMapRangeType {
|
||||
NODE_MAP_RANGE_LINEAR,
|
||||
NODE_MAP_RANGE_STEPPED,
|
||||
NODE_MAP_RANGE_SMOOTHSTEP,
|
||||
NODE_MAP_RANGE_SMOOTHERSTEP,
|
||||
} NodeMapRangeType;
|
||||
|
||||
typedef enum NodeMappingType {
|
||||
NODE_MAPPING_TYPE_POINT,
|
||||
NODE_MAPPING_TYPE_TEXTURE,
|
||||
|
@ -5561,11 +5561,19 @@ NODE_DEFINE(MapRangeNode)
|
||||
{
|
||||
NodeType *type = NodeType::add("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(type, "Type", type_enum, NODE_MAP_RANGE_LINEAR);
|
||||
|
||||
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_IN_FLOAT(steps, "Steps", 4.0f);
|
||||
|
||||
SOCKET_OUT_FLOAT(result, "Result");
|
||||
|
||||
@ -5582,6 +5590,7 @@ void MapRangeNode::expand(ShaderGraph *graph)
|
||||
ShaderOutput *result_out = output("Result");
|
||||
if (!result_out->links.empty()) {
|
||||
ClampNode *clamp_node = new ClampNode();
|
||||
clamp_node->type = NODE_CLAMP_RANGE;
|
||||
graph->add(clamp_node);
|
||||
graph->relink(result_out, clamp_node->output("Result"));
|
||||
graph->connect(result_out, clamp_node->input("Value"));
|
||||
@ -5601,20 +5610,6 @@ void MapRangeNode::expand(ShaderGraph *graph)
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
@ -5622,6 +5617,7 @@ void MapRangeNode::compile(SVMCompiler &compiler)
|
||||
ShaderInput *from_max_in = input("From Max");
|
||||
ShaderInput *to_min_in = input("To Min");
|
||||
ShaderInput *to_max_in = input("To Max");
|
||||
ShaderInput *steps_in = input("Steps");
|
||||
ShaderOutput *result_out = output("Result");
|
||||
|
||||
int value_stack_offset = compiler.stack_assign(value_in);
|
||||
@ -5629,6 +5625,7 @@ void MapRangeNode::compile(SVMCompiler &compiler)
|
||||
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 steps_stack_offset = compiler.stack_assign(steps_in);
|
||||
int result_stack_offset = compiler.stack_assign(result_out);
|
||||
|
||||
compiler.add_node(
|
||||
@ -5636,16 +5633,18 @@ void MapRangeNode::compile(SVMCompiler &compiler)
|
||||
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.encode_uchar4(type, steps_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));
|
||||
compiler.add_node(__float_as_int(steps));
|
||||
}
|
||||
|
||||
void MapRangeNode::compile(OSLCompiler &compiler)
|
||||
{
|
||||
compiler.parameter(this, "type");
|
||||
compiler.add(this, "node_map_range");
|
||||
}
|
||||
|
||||
@ -5655,6 +5654,11 @@ NODE_DEFINE(ClampNode)
|
||||
{
|
||||
NodeType *type = NodeType::add("clamp", create, NodeType::SHADER);
|
||||
|
||||
static NodeEnum type_enum;
|
||||
type_enum.insert("minmax", NODE_CLAMP_MINMAX);
|
||||
type_enum.insert("range", NODE_CLAMP_RANGE);
|
||||
SOCKET_ENUM(type, "Type", type_enum, NODE_CLAMP_MINMAX);
|
||||
|
||||
SOCKET_IN_FLOAT(value, "Value", 1.0f);
|
||||
SOCKET_IN_FLOAT(min, "Min", 0.0f);
|
||||
SOCKET_IN_FLOAT(max, "Max", 1.0f);
|
||||
@ -5671,7 +5675,12 @@ ClampNode::ClampNode() : ShaderNode(node_type)
|
||||
void ClampNode::constant_fold(const ConstantFolder &folder)
|
||||
{
|
||||
if (folder.all_inputs_constant()) {
|
||||
folder.make_constant(clamp(value, min, max));
|
||||
if (type == NODE_CLAMP_RANGE && (min > max)) {
|
||||
folder.make_constant(clamp(value, max, min));
|
||||
}
|
||||
else {
|
||||
folder.make_constant(clamp(value, min, max));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5689,13 +5698,14 @@ void ClampNode::compile(SVMCompiler &compiler)
|
||||
|
||||
compiler.add_node(NODE_CLAMP,
|
||||
value_stack_offset,
|
||||
compiler.encode_uchar4(min_stack_offset, max_stack_offset),
|
||||
compiler.encode_uchar4(min_stack_offset, max_stack_offset, type),
|
||||
result_stack_offset);
|
||||
compiler.add_node(__float_as_int(min), __float_as_int(max));
|
||||
}
|
||||
|
||||
void ClampNode::compile(OSLCompiler &compiler)
|
||||
{
|
||||
compiler.parameter(this, "type");
|
||||
compiler.add(this, "node_clamp");
|
||||
}
|
||||
|
||||
@ -5769,6 +5779,7 @@ void MathNode::expand(ShaderGraph *graph)
|
||||
ShaderOutput *result_out = output("Value");
|
||||
if (!result_out->links.empty()) {
|
||||
ClampNode *clamp_node = new ClampNode();
|
||||
clamp_node->type = NODE_CLAMP_MINMAX;
|
||||
clamp_node->min = 0.0f;
|
||||
clamp_node->max = 1.0f;
|
||||
graph->add(clamp_node);
|
||||
|
@ -1290,14 +1290,14 @@ class BlackbodyNode : public ShaderNode {
|
||||
class MapRangeNode : public ShaderNode {
|
||||
public:
|
||||
SHADER_NODE_CLASS(MapRangeNode)
|
||||
void constant_fold(const ConstantFolder &folder);
|
||||
virtual int get_group()
|
||||
{
|
||||
return NODE_GROUP_LEVEL_3;
|
||||
}
|
||||
void expand(ShaderGraph *graph);
|
||||
|
||||
float value, from_min, from_max, to_min, to_max;
|
||||
float value, from_min, from_max, to_min, to_max, steps;
|
||||
NodeMapRangeType type;
|
||||
bool clamp;
|
||||
};
|
||||
|
||||
@ -1310,6 +1310,7 @@ class ClampNode : public ShaderNode {
|
||||
return NODE_GROUP_LEVEL_3;
|
||||
}
|
||||
float value, min, max;
|
||||
NodeClampType type;
|
||||
};
|
||||
|
||||
class MathNode : public ShaderNode {
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 2f425cc128b8b709cc1ebf2c96ad372778f4aeda
|
||||
Subproject commit 1470f353c65034db91131d21ab9c782d029a2ee9
|
@ -1 +1 @@
|
||||
Subproject commit b52e7760ff6ccbcca73d2bbccc77f70ca2eaf98f
|
||||
Subproject commit ffbaca558a27bab4716bcd51ca7ea1df8e4f4b14
|
@ -250,9 +250,19 @@ static void node_buts_texture(uiLayout *layout, bContext *UNUSED(C), PointerRNA
|
||||
}
|
||||
}
|
||||
|
||||
static void node_buts_map_range(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
|
||||
static void node_shader_buts_clamp(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
|
||||
{
|
||||
uiItemR(layout, ptr, "clamp", 0, NULL, ICON_NONE);
|
||||
uiItemR(layout, ptr, "clamp_type", 0, "", ICON_NONE);
|
||||
}
|
||||
|
||||
static void node_shader_buts_map_range(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
|
||||
{
|
||||
uiItemR(layout, ptr, "interpolation_type", 0, "", ICON_NONE);
|
||||
if (!ELEM(RNA_enum_get(ptr, "interpolation_type"),
|
||||
NODE_MAP_RANGE_SMOOTHSTEP,
|
||||
NODE_MAP_RANGE_SMOOTHERSTEP)) {
|
||||
uiItemR(layout, ptr, "clamp", 0, NULL, ICON_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
static void node_buts_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
|
||||
@ -1172,8 +1182,11 @@ static void node_shader_set_butfunc(bNodeType *ntype)
|
||||
case SH_NODE_VALTORGB:
|
||||
ntype->draw_buttons = node_buts_colorramp;
|
||||
break;
|
||||
case SH_NODE_CLAMP:
|
||||
ntype->draw_buttons = node_shader_buts_clamp;
|
||||
break;
|
||||
case SH_NODE_MAP_RANGE:
|
||||
ntype->draw_buttons = node_buts_map_range;
|
||||
ntype->draw_buttons = node_shader_buts_map_range;
|
||||
break;
|
||||
case SH_NODE_MATH:
|
||||
ntype->draw_buttons = node_buts_math;
|
||||
|
@ -316,7 +316,7 @@ static GPUMaterialLibrary gpu_shader_material_mapping_library = {
|
||||
|
||||
static GPUMaterialLibrary gpu_shader_material_map_range_library = {
|
||||
.code = datatoc_gpu_shader_material_map_range_glsl,
|
||||
.dependencies = {NULL},
|
||||
.dependencies = {&gpu_shader_material_math_util_library, NULL},
|
||||
};
|
||||
|
||||
static GPUMaterialLibrary gpu_shader_material_math_library = {
|
||||
|
@ -2,3 +2,8 @@ void clamp_value(float value, float min, float max, out float result)
|
||||
{
|
||||
result = clamp(value, min, max);
|
||||
}
|
||||
|
||||
void clamp_range(float value, float min, float max, out float result)
|
||||
{
|
||||
result = (max > min) ? clamp(value, min, max) : clamp(value, max, min);
|
||||
}
|
||||
|
@ -1,5 +1,16 @@
|
||||
void map_range(
|
||||
float value, float fromMin, float fromMax, float toMin, float toMax, out float result)
|
||||
float smootherstep(float edge0, float edge1, float x)
|
||||
{
|
||||
x = clamp(safe_divide((x - edge0), (edge1 - edge0)), 0.0, 1.0);
|
||||
return x * x * x * (x * (x * 6.0 - 15.0) + 10.0);
|
||||
}
|
||||
|
||||
void map_range_linear(float value,
|
||||
float fromMin,
|
||||
float fromMax,
|
||||
float toMin,
|
||||
float toMax,
|
||||
float steps,
|
||||
out float result)
|
||||
{
|
||||
if (fromMax != fromMin) {
|
||||
result = toMin + ((value - fromMin) / (fromMax - fromMin)) * (toMax - toMin);
|
||||
@ -8,3 +19,57 @@ void map_range(
|
||||
result = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
void map_range_stepped(float value,
|
||||
float fromMin,
|
||||
float fromMax,
|
||||
float toMin,
|
||||
float toMax,
|
||||
float steps,
|
||||
out float result)
|
||||
{
|
||||
if (fromMax != fromMin) {
|
||||
float factor = (value - fromMin) / (fromMax - fromMin);
|
||||
factor = (steps > 0.0) ? floor(factor * (steps + 1.0)) / steps : 0.0;
|
||||
result = toMin + factor * (toMax - toMin);
|
||||
}
|
||||
else {
|
||||
result = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
void map_range_smoothstep(float value,
|
||||
float fromMin,
|
||||
float fromMax,
|
||||
float toMin,
|
||||
float toMax,
|
||||
float steps,
|
||||
out float result)
|
||||
{
|
||||
if (fromMax != fromMin) {
|
||||
float factor = (fromMin > fromMax) ? 1.0 - smoothstep(fromMax, fromMin, value) :
|
||||
smoothstep(fromMin, fromMax, value);
|
||||
result = toMin + factor * (toMax - toMin);
|
||||
}
|
||||
else {
|
||||
result = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
void map_range_smootherstep(float value,
|
||||
float fromMin,
|
||||
float fromMax,
|
||||
float toMin,
|
||||
float toMax,
|
||||
float steps,
|
||||
out float result)
|
||||
{
|
||||
if (fromMax != fromMin) {
|
||||
float factor = (fromMin > fromMax) ? 1.0 - smootherstep(fromMax, fromMin, value) :
|
||||
smootherstep(fromMin, fromMax, value);
|
||||
result = toMin + factor * (toMax - toMin);
|
||||
}
|
||||
else {
|
||||
result = 0.0;
|
||||
}
|
||||
}
|
||||
|
@ -1260,6 +1260,20 @@ enum {
|
||||
NODE_VECTOR_MATH_MAXIMUM = 19,
|
||||
};
|
||||
|
||||
/* Clamp node types. */
|
||||
enum {
|
||||
NODE_CLAMP_MINMAX = 0,
|
||||
NODE_CLAMP_RANGE = 1,
|
||||
};
|
||||
|
||||
/* Map range node types. */
|
||||
enum {
|
||||
NODE_MAP_RANGE_LINEAR = 0,
|
||||
NODE_MAP_RANGE_STEPPED = 1,
|
||||
NODE_MAP_RANGE_SMOOTHSTEP = 2,
|
||||
NODE_MAP_RANGE_SMOOTHERSTEP = 3,
|
||||
};
|
||||
|
||||
/* mix rgb node flags */
|
||||
#define SHD_MIXRGB_USE_ALPHA 1
|
||||
#define SHD_MIXRGB_CLAMP 2
|
||||
|
@ -188,6 +188,8 @@ extern const EnumPropertyItem rna_enum_node_math_items[];
|
||||
extern const EnumPropertyItem rna_enum_mapping_type_items[];
|
||||
extern const EnumPropertyItem rna_enum_node_vec_math_items[];
|
||||
extern const EnumPropertyItem rna_enum_node_filter_items[];
|
||||
extern const EnumPropertyItem rna_enum_node_map_range_items[];
|
||||
extern const EnumPropertyItem rna_enum_node_clamp_items[];
|
||||
|
||||
extern const EnumPropertyItem rna_enum_ramp_blend_items[];
|
||||
|
||||
|
@ -226,6 +226,36 @@ const EnumPropertyItem rna_enum_node_vec_math_items[] = {
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
const EnumPropertyItem rna_enum_node_map_range_items[] = {
|
||||
{NODE_MAP_RANGE_LINEAR,
|
||||
"LINEAR",
|
||||
0,
|
||||
"Linear",
|
||||
"Linear interpolation between From Min and From Max values"},
|
||||
{NODE_MAP_RANGE_STEPPED,
|
||||
"STEPPED",
|
||||
0,
|
||||
"Stepped Linear",
|
||||
"Stepped linear interpolation between From Min and From Max values"},
|
||||
{NODE_MAP_RANGE_SMOOTHSTEP,
|
||||
"SMOOTHSTEP",
|
||||
0,
|
||||
"Smoothstep",
|
||||
"Smooth hermite edge interpolation between From Min and From Max values"},
|
||||
{NODE_MAP_RANGE_SMOOTHERSTEP,
|
||||
"SMOOTHERSTEP",
|
||||
0,
|
||||
"Smootherstep",
|
||||
"Smoother hermite edge interpolation between From Min and From Max values"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
const EnumPropertyItem rna_enum_node_clamp_items[] = {
|
||||
{NODE_CLAMP_MINMAX, "MINMAX", 0, "Min Max", "Clamp values using Min and Max values"},
|
||||
{NODE_CLAMP_RANGE, "RANGE", 0, "Range", "Clamp values between Min and Max range"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
static const EnumPropertyItem rna_enum_node_tex_dimensions_items[] = {
|
||||
{1, "1D", 0, "1D", "Use the scalar value W as input"},
|
||||
{2, "2D", 0, "2D", "Use the 2D vector (x, y) as input. The z component is ignored"},
|
||||
@ -3921,6 +3951,17 @@ static void def_frame(StructRNA *srna)
|
||||
RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL);
|
||||
}
|
||||
|
||||
static void def_clamp(StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
prop = RNA_def_property(srna, "clamp_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "custom1");
|
||||
RNA_def_property_enum_items(prop, rna_enum_node_clamp_items);
|
||||
RNA_def_property_ui_text(prop, "Clamp Type", "");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update");
|
||||
}
|
||||
|
||||
static void def_map_range(StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
@ -3929,6 +3970,12 @@ static void def_map_range(StructRNA *srna)
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "custom1", 1);
|
||||
RNA_def_property_ui_text(prop, "Clamp", "Clamp the result to the target range [To Min, To Max]");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
|
||||
prop = RNA_def_property(srna, "interpolation_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "custom2");
|
||||
RNA_def_property_enum_items(prop, rna_enum_node_map_range_items);
|
||||
RNA_def_property_ui_text(prop, "Interpolation Type", "");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update");
|
||||
}
|
||||
|
||||
static void def_math(StructRNA *srna)
|
||||
|
@ -51,7 +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, def_map_range, "MAP_RANGE", MapRange, "Map Range", "" )
|
||||
DefNode(ShaderNode, SH_NODE_CLAMP, 0, "CLAMP", Clamp, "Clamp", "" )
|
||||
DefNode(ShaderNode, SH_NODE_CLAMP, def_clamp, "CLAMP", Clamp, "Clamp", "" )
|
||||
DefNode(ShaderNode, SH_NODE_MATH, def_math, "MATH", Math, "Math", "" )
|
||||
DefNode(ShaderNode, SH_NODE_VECTOR_MATH, def_vector_math, "VECT_MATH", VectorMath, "Vector Math", "" )
|
||||
DefNode(ShaderNode, SH_NODE_SQUEEZE, 0, "SQUEEZE", Squeeze, "Squeeze Value", "" )
|
||||
|
@ -35,13 +35,19 @@ static bNodeSocketTemplate sh_node_clamp_out[] = {
|
||||
{-1, 0, ""},
|
||||
};
|
||||
|
||||
static void node_shader_init_clamp(bNodeTree *UNUSED(ntree), bNode *node)
|
||||
{
|
||||
node->custom1 = NODE_CLAMP_MINMAX; /* clamp type */
|
||||
}
|
||||
|
||||
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);
|
||||
return (node->custom1 == NODE_CLAMP_MINMAX) ? GPU_stack_link(mat, node, "clamp_value", in, out) :
|
||||
GPU_stack_link(mat, node, "clamp_range", in, out);
|
||||
}
|
||||
|
||||
void register_node_type_sh_clamp(void)
|
||||
@ -50,6 +56,7 @@ void register_node_type_sh_clamp(void)
|
||||
|
||||
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_init(&ntype, node_shader_init_clamp);
|
||||
node_type_gpu(&ntype, gpu_shader_clamp);
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
|
@ -30,6 +30,7 @@ static bNodeSocketTemplate sh_node_map_range_in[] = {
|
||||
{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},
|
||||
{SOCK_FLOAT, 1, N_("Steps"), 4.0f, 1.0f, 1.0f, 1.0f, 0.0f, 10000.0f, PROP_NONE},
|
||||
{-1, 0, ""},
|
||||
};
|
||||
static bNodeSocketTemplate sh_node_map_range_out[] = {
|
||||
@ -37,9 +38,16 @@ static bNodeSocketTemplate sh_node_map_range_out[] = {
|
||||
{-1, 0, ""},
|
||||
};
|
||||
|
||||
static void node_shader_update_map_range(bNodeTree *UNUSED(ntree), bNode *node)
|
||||
{
|
||||
bNodeSocket *sockSteps = nodeFindSocket(node, SOCK_IN, "Steps");
|
||||
nodeSetSocketAvailability(sockSteps, node->custom2 == NODE_MAP_RANGE_STEPPED);
|
||||
}
|
||||
|
||||
static void node_shader_init_map_range(bNodeTree *UNUSED(ntree), bNode *node)
|
||||
{
|
||||
node->custom1 = true;
|
||||
node->custom1 = true; /* use_clamp */
|
||||
node->custom2 = NODE_MAP_RANGE_LINEAR; /* interpolation */
|
||||
}
|
||||
|
||||
static int gpu_shader_map_range(GPUMaterial *mat,
|
||||
@ -48,11 +56,25 @@ static int gpu_shader_map_range(GPUMaterial *mat,
|
||||
GPUNodeStack *in,
|
||||
GPUNodeStack *out)
|
||||
{
|
||||
GPU_stack_link(mat, node, "map_range", in, out);
|
||||
if (node->custom1) {
|
||||
GPU_link(mat, "clamp_value", out[0].link, in[3].link, in[4].link, &out[0].link);
|
||||
static const char *names[] = {
|
||||
[NODE_MAP_RANGE_LINEAR] = "map_range_linear",
|
||||
[NODE_MAP_RANGE_STEPPED] = "map_range_stepped",
|
||||
[NODE_MAP_RANGE_SMOOTHSTEP] = "map_range_smoothstep",
|
||||
[NODE_MAP_RANGE_SMOOTHERSTEP] = "map_range_smootherstep",
|
||||
};
|
||||
|
||||
int ret = 0;
|
||||
if (node->custom2 < ARRAY_SIZE(names) && names[node->custom2]) {
|
||||
ret = GPU_stack_link(mat, node, names[node->custom2], in, out);
|
||||
}
|
||||
return 1;
|
||||
else {
|
||||
ret = GPU_stack_link(mat, node, "map_range_linear", in, out);
|
||||
}
|
||||
if (ret && node->custom1 &&
|
||||
!ELEM(node->custom2, NODE_MAP_RANGE_SMOOTHSTEP, NODE_MAP_RANGE_SMOOTHERSTEP)) {
|
||||
GPU_link(mat, "clamp_range", out[0].link, in[3].link, in[4].link, &out[0].link);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void register_node_type_sh_map_range(void)
|
||||
@ -62,6 +84,7 @@ void register_node_type_sh_map_range(void)
|
||||
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_init(&ntype, node_shader_init_map_range);
|
||||
node_type_update(&ntype, node_shader_update_map_range);
|
||||
node_type_gpu(&ntype, gpu_shader_map_range);
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
|
Loading…
Reference in New Issue
Block a user