Shading: Refactor Math node and use dynamic inputs.
- Implement dynamic inputs. The second input is now unavailable in single operand math operators. - Reimplemenet the clamp option using graph expansion for Cycles. - Clean up code and unify naming between Blender and Cycles. - Remove unused code. Reviewers: brecht Differential Revision: https://developer.blender.org/D5481
This commit is contained in:
@@ -31,272 +31,6 @@ static bNodeSocketTemplate sh_node_math_in[] = {
|
||||
|
||||
static bNodeSocketTemplate sh_node_math_out[] = {{SOCK_FLOAT, 0, N_("Value")}, {-1, 0, ""}};
|
||||
|
||||
static void node_shader_exec_math(void *UNUSED(data),
|
||||
int UNUSED(thread),
|
||||
bNode *node,
|
||||
bNodeExecData *UNUSED(execdata),
|
||||
bNodeStack **in,
|
||||
bNodeStack **out)
|
||||
{
|
||||
float a, b, r = 0.0f;
|
||||
|
||||
nodestack_get_vec(&a, SOCK_FLOAT, in[0]);
|
||||
nodestack_get_vec(&b, SOCK_FLOAT, in[1]);
|
||||
|
||||
switch (node->custom1) {
|
||||
|
||||
case NODE_MATH_ADD:
|
||||
r = a + b;
|
||||
break;
|
||||
case NODE_MATH_SUB:
|
||||
r = a - b;
|
||||
break;
|
||||
case NODE_MATH_MUL:
|
||||
r = a * b;
|
||||
break;
|
||||
case NODE_MATH_DIVIDE: {
|
||||
if (b == 0) { /* We don't want to divide by zero. */
|
||||
r = 0.0;
|
||||
}
|
||||
else {
|
||||
r = a / b;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_SIN: {
|
||||
/* This one only takes one input, so we've got to choose. */
|
||||
if (in[0]->hasinput || !in[1]->hasinput) {
|
||||
r = sinf(a);
|
||||
}
|
||||
else {
|
||||
r = sinf(b);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_COS: {
|
||||
/* This one only takes one input, so we've got to choose. */
|
||||
if (in[0]->hasinput || !in[1]->hasinput) {
|
||||
r = cosf(a);
|
||||
}
|
||||
else {
|
||||
r = cosf(b);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_TAN: {
|
||||
/* This one only takes one input, so we've got to choose. */
|
||||
if (in[0]->hasinput || !in[1]->hasinput) {
|
||||
r = tanf(a);
|
||||
}
|
||||
else {
|
||||
r = tanf(b);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_ASIN: {
|
||||
/* This one only takes one input, so we've got to choose. */
|
||||
if (in[0]->hasinput || !in[1]->hasinput) {
|
||||
/* Can't do the impossible... */
|
||||
if (a <= 1 && a >= -1) {
|
||||
r = asinf(a);
|
||||
}
|
||||
else {
|
||||
r = 0.0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Can't do the impossible... */
|
||||
if (b <= 1 && b >= -1) {
|
||||
r = asinf(b);
|
||||
}
|
||||
else {
|
||||
r = 0.0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_ACOS: {
|
||||
/* This one only takes one input, so we've got to choose. */
|
||||
if (in[0]->hasinput || !in[1]->hasinput) {
|
||||
/* Can't do the impossible... */
|
||||
if (a <= 1 && a >= -1) {
|
||||
r = acosf(a);
|
||||
}
|
||||
else {
|
||||
r = 0.0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Can't do the impossible... */
|
||||
if (b <= 1 && b >= -1) {
|
||||
r = acosf(b);
|
||||
}
|
||||
else {
|
||||
r = 0.0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_ATAN: {
|
||||
/* This one only takes one input, so we've got to choose. */
|
||||
if (in[0]->hasinput || !in[1]->hasinput) {
|
||||
r = atan(a);
|
||||
}
|
||||
else {
|
||||
r = atan(b);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_POW: {
|
||||
/* Only raise negative numbers by full integers */
|
||||
if (a >= 0) {
|
||||
r = pow(a, b);
|
||||
}
|
||||
else {
|
||||
float y_mod_1 = fabsf(fmodf(b, 1.0f));
|
||||
|
||||
/* if input value is not nearly an integer,
|
||||
* fall back to zero, nicer than straight rounding. */
|
||||
if (y_mod_1 > 0.999f || y_mod_1 < 0.001f) {
|
||||
r = powf(a, floorf(b + 0.5f));
|
||||
}
|
||||
else {
|
||||
r = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_LOG: {
|
||||
/* Don't want any imaginary numbers... */
|
||||
if (a > 0 && b > 0) {
|
||||
r = log(a) / log(b);
|
||||
}
|
||||
else {
|
||||
r = 0.0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_MIN: {
|
||||
if (a < b) {
|
||||
r = a;
|
||||
}
|
||||
else {
|
||||
r = b;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_MAX: {
|
||||
if (a > b) {
|
||||
r = a;
|
||||
}
|
||||
else {
|
||||
r = b;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_ROUND: {
|
||||
/* This one only takes one input, so we've got to choose. */
|
||||
if (in[0]->hasinput || !in[1]->hasinput) {
|
||||
r = (a < 0) ? (int)(a - 0.5f) : (int)(a + 0.5f);
|
||||
}
|
||||
else {
|
||||
r = (b < 0) ? (int)(b - 0.5f) : (int)(b + 0.5f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_LESS: {
|
||||
if (a < b) {
|
||||
r = 1.0f;
|
||||
}
|
||||
else {
|
||||
r = 0.0f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_GREATER: {
|
||||
if (a > b) {
|
||||
r = 1.0f;
|
||||
}
|
||||
else {
|
||||
r = 0.0f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_MOD: {
|
||||
if (b == 0.0f) {
|
||||
r = 0.0f;
|
||||
}
|
||||
else {
|
||||
r = fmod(a, b);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_ABS: {
|
||||
r = fabsf(a);
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_ATAN2: {
|
||||
r = atan2(a, b);
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_FLOOR: {
|
||||
/* This one only takes one input, so we've got to choose. */
|
||||
if (in[0]->hasinput || !in[1]->hasinput) {
|
||||
r = floorf(a);
|
||||
}
|
||||
else {
|
||||
r = floorf(b);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_CEIL: {
|
||||
/* This one only takes one input, so we've got to choose. */
|
||||
if (in[0]->hasinput || !in[1]->hasinput) {
|
||||
r = ceilf(a);
|
||||
}
|
||||
else {
|
||||
r = ceilf(b);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_FRACT: {
|
||||
/* This one only takes one input, so we've got to choose. */
|
||||
if (in[0]->hasinput || !in[1]->hasinput) {
|
||||
r = a - floorf(a);
|
||||
}
|
||||
else {
|
||||
r = b - floorf(b);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_SQRT: {
|
||||
/* This one only takes one input, so we've got to choose. */
|
||||
if (in[0]->hasinput || !in[1]->hasinput) {
|
||||
if (a > 0) {
|
||||
r = sqrt(a);
|
||||
}
|
||||
else {
|
||||
r = 0.0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (b > 0) {
|
||||
r = sqrt(b);
|
||||
}
|
||||
else {
|
||||
r = 0.0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (node->custom2 & SHD_MATH_CLAMP) {
|
||||
CLAMP(r, 0.0f, 1.0f);
|
||||
}
|
||||
out[0]->vec[0] = r;
|
||||
}
|
||||
|
||||
static int gpu_shader_math(GPUMaterial *mat,
|
||||
bNode *node,
|
||||
bNodeExecData *UNUSED(execdata),
|
||||
@@ -304,68 +38,65 @@ static int gpu_shader_math(GPUMaterial *mat,
|
||||
GPUNodeStack *out)
|
||||
{
|
||||
static const char *names[] = {
|
||||
"math_add", "math_subtract", "math_multiply", "math_divide", "math_sine",
|
||||
"math_cosine", "math_tangent", "math_asin", "math_acos", "math_atan",
|
||||
"math_pow", "math_log", "math_min", "math_max", "math_round",
|
||||
"math_less_than", "math_greater_than", "math_modulo", "math_abs", "math_atan2",
|
||||
"math_floor", "math_ceil", "math_fract", "math_sqrt",
|
||||
[NODE_MATH_ADD] = "math_add",
|
||||
[NODE_MATH_SUBTRACT] = "math_subtract",
|
||||
[NODE_MATH_MULTIPLY] = "math_multiply",
|
||||
[NODE_MATH_DIVIDE] = "math_divide",
|
||||
|
||||
[NODE_MATH_POWER] = "math_power",
|
||||
[NODE_MATH_LOGARITHM] = "math_logarithm",
|
||||
[NODE_MATH_SQRT] = "math_sqrt",
|
||||
[NODE_MATH_ABSOLUTE] = "math_absolute",
|
||||
|
||||
[NODE_MATH_MINIMUM] = "math_minimum",
|
||||
[NODE_MATH_MAXIMUM] = "math_maximum",
|
||||
[NODE_MATH_LESS_THAN] = "math_less_than",
|
||||
[NODE_MATH_GREATER_THAN] = "math_greater_than",
|
||||
|
||||
[NODE_MATH_ROUND] = "math_round",
|
||||
[NODE_MATH_FLOOR] = "math_floor",
|
||||
[NODE_MATH_CEIL] = "math_ceil",
|
||||
[NODE_MATH_FRACTION] = "math_fraction",
|
||||
[NODE_MATH_MODULO] = "math_modulo",
|
||||
|
||||
[NODE_MATH_SINE] = "math_sine",
|
||||
[NODE_MATH_COSINE] = "math_cosine",
|
||||
[NODE_MATH_TANGENT] = "math_tangent",
|
||||
[NODE_MATH_ARCSINE] = "math_arcsine",
|
||||
[NODE_MATH_ARCCOSINE] = "math_arccosine",
|
||||
[NODE_MATH_ARCTANGENT] = "math_arctangent",
|
||||
[NODE_MATH_ARCTAN2] = "math_arctan2",
|
||||
};
|
||||
|
||||
switch (node->custom1) {
|
||||
case NODE_MATH_ADD:
|
||||
case NODE_MATH_SUB:
|
||||
case NODE_MATH_MUL:
|
||||
case NODE_MATH_DIVIDE:
|
||||
case NODE_MATH_POW:
|
||||
case NODE_MATH_LOG:
|
||||
case NODE_MATH_MIN:
|
||||
case NODE_MATH_MAX:
|
||||
case NODE_MATH_LESS:
|
||||
case NODE_MATH_GREATER:
|
||||
case NODE_MATH_MOD:
|
||||
case NODE_MATH_ATAN2:
|
||||
GPU_stack_link(mat, node, names[node->custom1], in, out);
|
||||
break;
|
||||
case NODE_MATH_SIN:
|
||||
case NODE_MATH_COS:
|
||||
case NODE_MATH_TAN:
|
||||
case NODE_MATH_ASIN:
|
||||
case NODE_MATH_ACOS:
|
||||
case NODE_MATH_ATAN:
|
||||
case NODE_MATH_ROUND:
|
||||
case NODE_MATH_ABS:
|
||||
case NODE_MATH_FLOOR:
|
||||
case NODE_MATH_FRACT:
|
||||
case NODE_MATH_CEIL:
|
||||
case NODE_MATH_SQRT:
|
||||
if (in[0].hasinput || !in[1].hasinput) {
|
||||
/* use only first item and terminator */
|
||||
GPUNodeStack tmp_in[2];
|
||||
memcpy(&tmp_in[0], &in[0], sizeof(GPUNodeStack));
|
||||
memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack));
|
||||
GPU_stack_link(mat, node, names[node->custom1], tmp_in, out);
|
||||
}
|
||||
else {
|
||||
/* use only second item and terminator */
|
||||
GPUNodeStack tmp_in[2];
|
||||
memcpy(&tmp_in[0], &in[1], sizeof(GPUNodeStack));
|
||||
memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack));
|
||||
GPU_stack_link(mat, node, names[node->custom1], tmp_in, out);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
GPU_stack_link(mat, node, names[node->custom1], in, out);
|
||||
|
||||
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_value", out[0].link, GPU_constant(min), GPU_constant(max), &out[0].link);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void node_shader_update_math(bNodeTree *UNUSED(ntree), bNode *node)
|
||||
{
|
||||
bNodeSocket *sock = BLI_findlink(&node->inputs, 1);
|
||||
nodeSetSocketAvailability(sock,
|
||||
!ELEM(node->custom1,
|
||||
NODE_MATH_SQRT,
|
||||
NODE_MATH_CEIL,
|
||||
NODE_MATH_SINE,
|
||||
NODE_MATH_ROUND,
|
||||
NODE_MATH_FLOOR,
|
||||
NODE_MATH_COSINE,
|
||||
NODE_MATH_ARCSINE,
|
||||
NODE_MATH_TANGENT,
|
||||
NODE_MATH_ABSOLUTE,
|
||||
NODE_MATH_FRACTION,
|
||||
NODE_MATH_ARCCOSINE,
|
||||
NODE_MATH_ARCTANGENT));
|
||||
}
|
||||
|
||||
void register_node_type_sh_math(void)
|
||||
{
|
||||
static bNodeType ntype;
|
||||
@@ -373,9 +104,8 @@ void register_node_type_sh_math(void)
|
||||
sh_node_type_base(&ntype, SH_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, 0);
|
||||
node_type_socket_templates(&ntype, sh_node_math_in, sh_node_math_out);
|
||||
node_type_label(&ntype, node_math_label);
|
||||
node_type_storage(&ntype, "", NULL, NULL);
|
||||
node_type_exec(&ntype, NULL, NULL, node_shader_exec_math);
|
||||
node_type_gpu(&ntype, gpu_shader_math);
|
||||
node_type_update(&ntype, node_shader_update_math);
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
|
||||
@@ -46,10 +46,10 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
|
||||
case NODE_MATH_ADD:
|
||||
*out = in0 + in1;
|
||||
break;
|
||||
case NODE_MATH_SUB:
|
||||
case NODE_MATH_SUBTRACT:
|
||||
*out = in0 - in1;
|
||||
break;
|
||||
case NODE_MATH_MUL:
|
||||
case NODE_MATH_MULTIPLY:
|
||||
*out = in0 * in1;
|
||||
break;
|
||||
case NODE_MATH_DIVIDE: {
|
||||
@@ -62,19 +62,19 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_SIN: {
|
||||
case NODE_MATH_SINE: {
|
||||
*out = sinf(in0);
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_COS: {
|
||||
case NODE_MATH_COSINE: {
|
||||
*out = cosf(in0);
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_TAN: {
|
||||
case NODE_MATH_TANGENT: {
|
||||
*out = tanf(in0);
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_ASIN: {
|
||||
case NODE_MATH_ARCSINE: {
|
||||
/* Can't do the impossible... */
|
||||
if (in0 <= 1 && in0 >= -1) {
|
||||
*out = asinf(in0);
|
||||
@@ -84,7 +84,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_ACOS: {
|
||||
case NODE_MATH_ARCCOSINE: {
|
||||
/* Can't do the impossible... */
|
||||
if (in0 <= 1 && in0 >= -1) {
|
||||
*out = acosf(in0);
|
||||
@@ -94,11 +94,11 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_ATAN: {
|
||||
case NODE_MATH_ARCTANGENT: {
|
||||
*out = atan(in0);
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_POW: {
|
||||
case NODE_MATH_POWER: {
|
||||
/* Only raise negative numbers by full integers */
|
||||
if (in0 >= 0) {
|
||||
out[0] = pow(in0, in1);
|
||||
@@ -114,7 +114,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_LOG: {
|
||||
case NODE_MATH_LOGARITHM: {
|
||||
/* Don't want any imaginary numbers... */
|
||||
if (in0 > 0 && in1 > 0) {
|
||||
*out = log(in0) / log(in1);
|
||||
@@ -124,7 +124,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_MIN: {
|
||||
case NODE_MATH_MINIMUM: {
|
||||
if (in0 < in1) {
|
||||
*out = in0;
|
||||
}
|
||||
@@ -133,7 +133,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_MAX: {
|
||||
case NODE_MATH_MAXIMUM: {
|
||||
if (in0 > in1) {
|
||||
*out = in0;
|
||||
}
|
||||
@@ -147,7 +147,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_LESS: {
|
||||
case NODE_MATH_LESS_THAN: {
|
||||
if (in0 < in1) {
|
||||
*out = 1.0f;
|
||||
}
|
||||
@@ -157,7 +157,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_GREATER: {
|
||||
case NODE_MATH_GREATER_THAN: {
|
||||
if (in0 > in1) {
|
||||
*out = 1.0f;
|
||||
}
|
||||
@@ -167,7 +167,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_MOD: {
|
||||
case NODE_MATH_MODULO: {
|
||||
if (in1 == 0.0f) {
|
||||
*out = 0.0f;
|
||||
}
|
||||
@@ -177,12 +177,12 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_ABS: {
|
||||
case NODE_MATH_ABSOLUTE: {
|
||||
*out = fabsf(in0);
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_ATAN2: {
|
||||
case NODE_MATH_ARCTAN2: {
|
||||
*out = atan2(in0, in1);
|
||||
break;
|
||||
}
|
||||
@@ -197,7 +197,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_FRACT: {
|
||||
case NODE_MATH_FRACTION: {
|
||||
*out = in0 - floorf(in0);
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user