Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/intern
diff options
context:
space:
mode:
Diffstat (limited to 'intern')
-rw-r--r--intern/cycles/kernel/shaders/node_math.osl62
-rw-r--r--intern/cycles/kernel/svm/svm_math.h7
-rw-r--r--intern/cycles/kernel/svm/svm_math_util.h34
-rw-r--r--intern/cycles/kernel/svm/svm_types.h16
-rw-r--r--intern/cycles/render/nodes.cpp30
-rw-r--r--intern/cycles/render/nodes.h1
-rw-r--r--intern/cycles/util/util_math.h39
7 files changed, 180 insertions, 9 deletions
diff --git a/intern/cycles/kernel/shaders/node_math.osl b/intern/cycles/kernel/shaders/node_math.osl
index 13e4c91ba10..1eccb56405b 100644
--- a/intern/cycles/kernel/shaders/node_math.osl
+++ b/intern/cycles/kernel/shaders/node_math.osl
@@ -26,6 +26,35 @@ float safe_modulo(float a, float b)
return (b != 0.0) ? fmod(a, b) : 0.0;
}
+float fract(float a)
+{
+ return a - floor(a);
+}
+
+/* Adapted from godotengine math_funcs.h. */
+float wrap(float value, float max, float min)
+{
+ float range = max - min;
+ return (range != 0.0) ? value - (range * floor((value - min) / range)) : min;
+}
+
+/* See: https://www.iquilezles.org/www/articles/smin/smin.htm. */
+float smoothmin(float a, float b, float c)
+{
+ if (c != 0.0) {
+ float h = max(c - abs(a - b), 0.0) / c;
+ return min(a, b) - h * h * h * c * (1.0 / 6.0);
+ }
+ else {
+ return min(a, b);
+ }
+}
+
+float pingpong(float a, float b)
+{
+ return (b != 0.0) ? abs(fract((a - b) / (b * 2.0)) * b * 2.0 - b) : 0.0;
+}
+
float safe_sqrt(float a)
{
return (a > 0.0) ? sqrt(a) : 0.0;
@@ -40,6 +69,7 @@ float safe_log(float a, float b)
shader node_math(string type = "add",
float Value1 = 0.5,
float Value2 = 0.5,
+ float Value3 = 0.5,
output float Value = 0.0)
{
if (type == "add")
@@ -56,8 +86,14 @@ shader node_math(string type = "add",
Value = safe_log(Value1, Value2);
else if (type == "sqrt")
Value = safe_sqrt(Value1);
+ else if (type == "inversesqrt")
+ Value = inversesqrt(Value1);
else if (type == "absolute")
Value = fabs(Value1);
+ else if (type == "radians")
+ Value = radians(Value1);
+ else if (type == "degrees")
+ Value = degrees(Value1);
else if (type == "minimum")
Value = min(Value1, Value2);
else if (type == "maximum")
@@ -76,12 +112,26 @@ shader node_math(string type = "add",
Value = Value1 - floor(Value1);
else if (type == "modulo")
Value = safe_modulo(Value1, Value2);
+ else if (type == "trunc")
+ Value = trunc(Value1);
+ else if (type == "snap")
+ Value = floor(safe_divide(Value1, Value2)) * Value2;
+ else if (type == "wrap")
+ Value = wrap(Value1, Value2, Value3);
+ else if (type == "pingpong")
+ Value = pingpong(Value1, Value2);
else if (type == "sine")
Value = sin(Value1);
else if (type == "cosine")
Value = cos(Value1);
else if (type == "tangent")
Value = tan(Value1);
+ else if (type == "sinh")
+ Value = sinh(Value1);
+ else if (type == "cosh")
+ Value = cosh(Value1);
+ else if (type == "tanh")
+ Value = tanh(Value1);
else if (type == "arcsine")
Value = asin(Value1);
else if (type == "arccosine")
@@ -90,6 +140,18 @@ shader node_math(string type = "add",
Value = atan(Value1);
else if (type == "arctan2")
Value = atan2(Value1, Value2);
+ else if (type == "sign")
+ Value = sign(Value1);
+ else if (type == "exponent")
+ Value = exp(Value1);
+ else if (type == "compare")
+ Value = ((Value1 == Value2) || (abs(Value1 - Value2) <= max(Value3, 1e-5))) ? 1.0 : 0.0;
+ else if (type == "multiply_add")
+ Value = Value1 * Value2 + Value3;
+ else if (type == "smoothmin")
+ Value = smoothmin(Value1, Value2, Value3);
+ else if (type == "smoothmax")
+ Value = -(smoothmin(-Value1, -Value2, Value3));
else
warning("%s", "Unknown math operator!");
}
diff --git a/intern/cycles/kernel/svm/svm_math.h b/intern/cycles/kernel/svm/svm_math.h
index d156dec497c..82cae7bbacf 100644
--- a/intern/cycles/kernel/svm/svm_math.h
+++ b/intern/cycles/kernel/svm/svm_math.h
@@ -24,12 +24,13 @@ ccl_device void svm_node_math(KernelGlobals *kg,
uint result_stack_offset,
int *offset)
{
- uint a_stack_offset, b_stack_offset;
- svm_unpack_node_uchar2(inputs_stack_offsets, &a_stack_offset, &b_stack_offset);
+ uint a_stack_offset, b_stack_offset, c_stack_offset;
+ svm_unpack_node_uchar3(inputs_stack_offsets, &a_stack_offset, &b_stack_offset, &c_stack_offset);
float a = stack_load_float(stack, a_stack_offset);
float b = stack_load_float(stack, b_stack_offset);
- float result = svm_math((NodeMathType)type, a, b);
+ float c = stack_load_float(stack, c_stack_offset);
+ float result = svm_math((NodeMathType)type, a, b, c);
stack_store_float(stack, result_stack_offset, result);
}
diff --git a/intern/cycles/kernel/svm/svm_math_util.h b/intern/cycles/kernel/svm/svm_math_util.h
index c07a1e4ed98..7b9eaaeb710 100644
--- a/intern/cycles/kernel/svm/svm_math_util.h
+++ b/intern/cycles/kernel/svm/svm_math_util.h
@@ -86,7 +86,7 @@ ccl_device void svm_vector_math(
}
}
-ccl_device float svm_math(NodeMathType type, float a, float b)
+ccl_device float svm_math(NodeMathType type, float a, float b, float c)
{
switch (type) {
case NODE_MATH_ADD:
@@ -103,8 +103,14 @@ ccl_device float svm_math(NodeMathType type, float a, float b)
return safe_logf(a, b);
case NODE_MATH_SQRT:
return safe_sqrtf(a);
+ case NODE_MATH_INV_SQRT:
+ return inversesqrtf(a);
case NODE_MATH_ABSOLUTE:
return fabsf(a);
+ case NODE_MATH_RADIANS:
+ return a * (M_PI_F / 180.0f);
+ case NODE_MATH_DEGREES:
+ return a * (180.0f / M_PI_F);
case NODE_MATH_MINIMUM:
return fminf(a, b);
case NODE_MATH_MAXIMUM:
@@ -123,12 +129,26 @@ ccl_device float svm_math(NodeMathType type, float a, float b)
return a - floorf(a);
case NODE_MATH_MODULO:
return safe_modulo(a, b);
+ case NODE_MATH_TRUNC:
+ return a >= 0.0f ? floorf(a) : ceilf(a);
+ case NODE_MATH_SNAP:
+ return floorf(safe_divide(a, b)) * b;
+ case NODE_MATH_WRAP:
+ return wrapf(a, b, c);
+ case NODE_MATH_PINGPONG:
+ return pingpongf(a, b);
case NODE_MATH_SINE:
return sinf(a);
case NODE_MATH_COSINE:
return cosf(a);
case NODE_MATH_TANGENT:
return tanf(a);
+ case NODE_MATH_SINH:
+ return sinhf(a);
+ case NODE_MATH_COSH:
+ return coshf(a);
+ case NODE_MATH_TANH:
+ return tanhf(a);
case NODE_MATH_ARCSINE:
return safe_asinf(a);
case NODE_MATH_ARCCOSINE:
@@ -137,6 +157,18 @@ ccl_device float svm_math(NodeMathType type, float a, float b)
return atanf(a);
case NODE_MATH_ARCTAN2:
return atan2f(a, b);
+ case NODE_MATH_SIGN:
+ return compatible_signf(a);
+ case NODE_MATH_EXPONENT:
+ return expf(a);
+ case NODE_MATH_COMPARE:
+ return ((a == b) || (fabsf(a - b) <= fmaxf(c, FLT_EPSILON))) ? 1.0f : 0.0f;
+ case NODE_MATH_MULTIPLY_ADD:
+ return a * b + c;
+ case NODE_MATH_SMOOTH_MIN:
+ return smoothminf(a, b, c);
+ case NODE_MATH_SMOOTH_MAX:
+ return -smoothminf(-a, -b, c);
default:
return 0.0f;
}
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index aa4dfdca2d1..8e312a515d6 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -281,6 +281,22 @@ typedef enum NodeMathType {
NODE_MATH_CEIL,
NODE_MATH_FRACTION,
NODE_MATH_SQRT,
+ NODE_MATH_INV_SQRT,
+ NODE_MATH_SIGN,
+ NODE_MATH_EXPONENT,
+ NODE_MATH_RADIANS,
+ NODE_MATH_DEGREES,
+ NODE_MATH_SINH,
+ NODE_MATH_COSH,
+ NODE_MATH_TANH,
+ NODE_MATH_TRUNC,
+ NODE_MATH_SNAP,
+ NODE_MATH_WRAP,
+ NODE_MATH_COMPARE,
+ NODE_MATH_MULTIPLY_ADD,
+ NODE_MATH_PINGPONG,
+ NODE_MATH_SMOOTH_MIN,
+ NODE_MATH_SMOOTH_MAX,
} NodeMathType;
typedef enum NodeVectorMathType {
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index f637fbf3b37..c6f1e8409eb 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -5710,9 +5710,13 @@ NODE_DEFINE(MathNode)
type_enum.insert("subtract", NODE_MATH_SUBTRACT);
type_enum.insert("multiply", NODE_MATH_MULTIPLY);
type_enum.insert("divide", NODE_MATH_DIVIDE);
+ type_enum.insert("multiply_add", NODE_MATH_MULTIPLY_ADD);
type_enum.insert("sine", NODE_MATH_SINE);
type_enum.insert("cosine", NODE_MATH_COSINE);
type_enum.insert("tangent", NODE_MATH_TANGENT);
+ type_enum.insert("sinh", NODE_MATH_SINH);
+ type_enum.insert("cosh", NODE_MATH_COSH);
+ type_enum.insert("tanh", NODE_MATH_TANH);
type_enum.insert("arcsine", NODE_MATH_ARCSINE);
type_enum.insert("arccosine", NODE_MATH_ARCCOSINE);
type_enum.insert("arctangent", NODE_MATH_ARCTANGENT);
@@ -5729,13 +5733,26 @@ NODE_DEFINE(MathNode)
type_enum.insert("floor", NODE_MATH_FLOOR);
type_enum.insert("ceil", NODE_MATH_CEIL);
type_enum.insert("fraction", NODE_MATH_FRACTION);
+ type_enum.insert("trunc", NODE_MATH_TRUNC);
+ type_enum.insert("snap", NODE_MATH_SNAP);
+ type_enum.insert("wrap", NODE_MATH_WRAP);
+ type_enum.insert("pingpong", NODE_MATH_PINGPONG);
type_enum.insert("sqrt", NODE_MATH_SQRT);
+ type_enum.insert("inversesqrt", NODE_MATH_INV_SQRT);
+ type_enum.insert("sign", NODE_MATH_SIGN);
+ type_enum.insert("exponent", NODE_MATH_EXPONENT);
+ type_enum.insert("radians", NODE_MATH_RADIANS);
+ type_enum.insert("degrees", NODE_MATH_DEGREES);
+ type_enum.insert("smoothmin", NODE_MATH_SMOOTH_MIN);
+ type_enum.insert("smoothmax", NODE_MATH_SMOOTH_MAX);
+ type_enum.insert("compare", NODE_MATH_COMPARE);
SOCKET_ENUM(type, "Type", type_enum, NODE_MATH_ADD);
SOCKET_BOOLEAN(use_clamp, "Use Clamp", false);
SOCKET_IN_FLOAT(value1, "Value1", 0.5f);
SOCKET_IN_FLOAT(value2, "Value2", 0.5f);
+ SOCKET_IN_FLOAT(value3, "Value3", 0.0f);
SOCKET_OUT_FLOAT(value, "Value");
@@ -5764,7 +5781,7 @@ void MathNode::expand(ShaderGraph *graph)
void MathNode::constant_fold(const ConstantFolder &folder)
{
if (folder.all_inputs_constant()) {
- folder.make_constant(svm_math(type, value1, value2));
+ folder.make_constant(svm_math(type, value1, value2, value3));
}
else {
folder.fold_math(type);
@@ -5775,16 +5792,19 @@ void MathNode::compile(SVMCompiler &compiler)
{
ShaderInput *value1_in = input("Value1");
ShaderInput *value2_in = input("Value2");
+ ShaderInput *value3_in = input("Value3");
ShaderOutput *value_out = output("Value");
int value1_stack_offset = compiler.stack_assign(value1_in);
int value2_stack_offset = compiler.stack_assign(value2_in);
+ int value3_stack_offset = compiler.stack_assign(value3_in);
int value_stack_offset = compiler.stack_assign(value_out);
- compiler.add_node(NODE_MATH,
- type,
- compiler.encode_uchar4(value1_stack_offset, value2_stack_offset),
- value_stack_offset);
+ compiler.add_node(
+ NODE_MATH,
+ type,
+ compiler.encode_uchar4(value1_stack_offset, value2_stack_offset, value3_stack_offset),
+ value_stack_offset);
}
void MathNode::compile(OSLCompiler &compiler)
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 62037b0d381..b8f1328f4b9 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -1324,6 +1324,7 @@ class MathNode : public ShaderNode {
float value1;
float value2;
+ float value3;
NodeMathType type;
bool use_clamp;
};
diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h
index 53e528de66e..dc211d2ed4e 100644
--- a/intern/cycles/util/util_math.h
+++ b/intern/cycles/util/util_math.h
@@ -344,6 +344,29 @@ ccl_device_inline int ceil_to_int(float f)
return float_to_int(ceilf(f));
}
+ccl_device_inline float fractf(float x)
+{
+ return x - floorf(x);
+}
+
+/* Adapted from godotengine math_funcs.h. */
+ccl_device_inline float wrapf(float value, float max, float min)
+{
+ float range = max - min;
+ return (range != 0.0f) ? value - (range * floorf((value - min) / range)) : min;
+}
+
+ccl_device_inline float pingpongf(float a, float b)
+{
+ return (b != 0.0f) ? fabsf(fractf((a - b) / (b * 2.0f)) * b * 2.0f - b) : 0.0f;
+}
+
+ccl_device_inline float smoothminf(float a, float b, float k)
+{
+ float h = fmaxf(k - fabsf(a - b), 0.0f) / k;
+ return fminf(a, b) - h * h * h * k * (1.0f / 6.0f);
+}
+
ccl_device_inline float signf(float f)
{
return (f < 0.0f) ? -1.0f : 1.0f;
@@ -357,6 +380,17 @@ ccl_device_inline float nonzerof(float f, float eps)
return f;
}
+/* Signum function testing for zero. Matches GLSL and OSL functions. */
+ccl_device_inline float compatible_signf(float f)
+{
+ if (f == 0.0f) {
+ return 0.0f;
+ }
+ else {
+ return signf(f);
+ }
+}
+
ccl_device_inline float smoothstepf(float f)
{
float ff = f * f;
@@ -549,6 +583,11 @@ ccl_device_inline float safe_sqrtf(float f)
return sqrtf(max(f, 0.0f));
}
+ccl_device_inline float inversesqrtf(float f)
+{
+ return (f > 0.0f) ? 1.0f / sqrtf(f) : 0.0f;
+}
+
ccl_device float safe_asinf(float a)
{
return asinf(clamp(a, -1.0f, 1.0f));