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:
@@ -615,6 +615,7 @@ void nodeUpdateInternalLinks(struct bNodeTree *ntree, struct bNode *node);
|
||||
|
||||
int nodeSocketIsHidden(struct bNodeSocket *sock);
|
||||
void ntreeTagUsedSockets(struct bNodeTree *ntree);
|
||||
void nodeSetSocketAvailability(struct bNodeSocket *sock, bool is_available);
|
||||
|
||||
/* Node Clipboard */
|
||||
void BKE_node_clipboard_init(struct bNodeTree *ntree);
|
||||
|
||||
@@ -2799,6 +2799,16 @@ int nodeSocketIsHidden(bNodeSocket *sock)
|
||||
return ((sock->flag & (SOCK_HIDDEN | SOCK_UNAVAIL)) != 0);
|
||||
}
|
||||
|
||||
void nodeSetSocketAvailability(bNodeSocket *sock, bool is_available)
|
||||
{
|
||||
if (is_available) {
|
||||
sock->flag &= ~SOCK_UNAVAIL;
|
||||
}
|
||||
else {
|
||||
sock->flag |= SOCK_UNAVAIL;
|
||||
}
|
||||
}
|
||||
|
||||
/* ************** Node Clipboard *********** */
|
||||
|
||||
#define USE_NODE_CB_VALIDATE
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "DNA_color_types.h"
|
||||
@@ -185,7 +186,7 @@ static void square_roughness_node_insert(bNodeTree *ntree)
|
||||
|
||||
/* Add sqrt node. */
|
||||
bNode *node = nodeAddStaticNode(NULL, ntree, SH_NODE_MATH);
|
||||
node->custom1 = NODE_MATH_POW;
|
||||
node->custom1 = NODE_MATH_POWER;
|
||||
node->locx = 0.5f * (fromnode->locx + tonode->locx);
|
||||
node->locy = 0.5f * (fromnode->locy + tonode->locy);
|
||||
|
||||
@@ -385,6 +386,46 @@ static void light_emission_unify(Light *light, const char *engine)
|
||||
}
|
||||
}
|
||||
|
||||
/* The B input of the Math node is no longer used for single-operand operators.
|
||||
* Previously, if the B input was linked and the A input was not, the B input
|
||||
* was used as the input of the operator. To correct this, we move the link
|
||||
* from B to A if B is linked and A is not.
|
||||
*/
|
||||
static void update_math_node_single_operand_operators(bNodeTree *ntree)
|
||||
{
|
||||
bool need_update = false;
|
||||
|
||||
for (bNode *node = ntree->nodes.first; node; node = node->next) {
|
||||
if (node->type == SH_NODE_MATH) {
|
||||
if (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)) {
|
||||
bNodeSocket *sockA = BLI_findlink(&node->inputs, 0);
|
||||
bNodeSocket *sockB = BLI_findlink(&node->inputs, 1);
|
||||
if (!sockA->link && sockB->link) {
|
||||
nodeAddLink(ntree, sockB->link->fromnode, sockB->link->fromsock, node, sockA);
|
||||
nodeRemLink(ntree, sockB->link);
|
||||
need_update = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (need_update) {
|
||||
ntreeUpdateTree(NULL, ntree);
|
||||
}
|
||||
}
|
||||
|
||||
void blo_do_versions_cycles(FileData *UNUSED(fd), Library *UNUSED(lib), Main *bmain)
|
||||
{
|
||||
/* Particle shape shared with Eevee. */
|
||||
@@ -526,4 +567,13 @@ void do_versions_after_linking_cycles(Main *bmain)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 281, 2)) {
|
||||
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
|
||||
if (ntree->type == NTREE_SHADER) {
|
||||
update_math_node_single_operand_operators(ntree);
|
||||
}
|
||||
}
|
||||
FOREACH_NODETREE_END;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,61 +29,61 @@ void MathNode::convertToOperations(NodeConverter &converter,
|
||||
case NODE_MATH_ADD:
|
||||
operation = new MathAddOperation();
|
||||
break;
|
||||
case NODE_MATH_SUB:
|
||||
case NODE_MATH_SUBTRACT:
|
||||
operation = new MathSubtractOperation();
|
||||
break;
|
||||
case NODE_MATH_MUL:
|
||||
case NODE_MATH_MULTIPLY:
|
||||
operation = new MathMultiplyOperation();
|
||||
break;
|
||||
case NODE_MATH_DIVIDE:
|
||||
operation = new MathDivideOperation();
|
||||
break;
|
||||
case NODE_MATH_SIN:
|
||||
case NODE_MATH_SINE:
|
||||
operation = new MathSineOperation();
|
||||
break;
|
||||
case NODE_MATH_COS:
|
||||
case NODE_MATH_COSINE:
|
||||
operation = new MathCosineOperation();
|
||||
break;
|
||||
case NODE_MATH_TAN:
|
||||
case NODE_MATH_TANGENT:
|
||||
operation = new MathTangentOperation();
|
||||
break;
|
||||
case NODE_MATH_ASIN:
|
||||
case NODE_MATH_ARCSINE:
|
||||
operation = new MathArcSineOperation();
|
||||
break;
|
||||
case NODE_MATH_ACOS:
|
||||
case NODE_MATH_ARCCOSINE:
|
||||
operation = new MathArcCosineOperation();
|
||||
break;
|
||||
case NODE_MATH_ATAN:
|
||||
case NODE_MATH_ARCTANGENT:
|
||||
operation = new MathArcTangentOperation();
|
||||
break;
|
||||
case NODE_MATH_POW:
|
||||
case NODE_MATH_POWER:
|
||||
operation = new MathPowerOperation();
|
||||
break;
|
||||
case NODE_MATH_LOG:
|
||||
case NODE_MATH_LOGARITHM:
|
||||
operation = new MathLogarithmOperation();
|
||||
break;
|
||||
case NODE_MATH_MIN:
|
||||
case NODE_MATH_MINIMUM:
|
||||
operation = new MathMinimumOperation();
|
||||
break;
|
||||
case NODE_MATH_MAX:
|
||||
case NODE_MATH_MAXIMUM:
|
||||
operation = new MathMaximumOperation();
|
||||
break;
|
||||
case NODE_MATH_ROUND:
|
||||
operation = new MathRoundOperation();
|
||||
break;
|
||||
case NODE_MATH_LESS:
|
||||
case NODE_MATH_LESS_THAN:
|
||||
operation = new MathLessThanOperation();
|
||||
break;
|
||||
case NODE_MATH_GREATER:
|
||||
case NODE_MATH_GREATER_THAN:
|
||||
operation = new MathGreaterThanOperation();
|
||||
break;
|
||||
case NODE_MATH_MOD:
|
||||
case NODE_MATH_MODULO:
|
||||
operation = new MathModuloOperation();
|
||||
break;
|
||||
case NODE_MATH_ABS:
|
||||
case NODE_MATH_ABSOLUTE:
|
||||
operation = new MathAbsoluteOperation();
|
||||
break;
|
||||
case NODE_MATH_ATAN2:
|
||||
case NODE_MATH_ARCTAN2:
|
||||
operation = new MathArcTan2Operation();
|
||||
break;
|
||||
case NODE_MATH_FLOOR:
|
||||
@@ -92,7 +92,7 @@ void MathNode::convertToOperations(NodeConverter &converter,
|
||||
case NODE_MATH_CEIL:
|
||||
operation = new MathCeilOperation();
|
||||
break;
|
||||
case NODE_MATH_FRACT:
|
||||
case NODE_MATH_FRACTION:
|
||||
operation = new MathFractOperation();
|
||||
break;
|
||||
case NODE_MATH_SQRT:
|
||||
|
||||
@@ -250,178 +250,138 @@ void camera(vec3 co, out vec3 outview, out float outdepth, out float outdist)
|
||||
outview = normalize(co);
|
||||
}
|
||||
|
||||
void math_add(float val1, float val2, out float outval)
|
||||
void math_add(float a, float b, out float result)
|
||||
{
|
||||
outval = val1 + val2;
|
||||
result = a + b;
|
||||
}
|
||||
|
||||
void math_subtract(float val1, float val2, out float outval)
|
||||
void math_subtract(float a, float b, out float result)
|
||||
{
|
||||
outval = val1 - val2;
|
||||
result = a - b;
|
||||
}
|
||||
|
||||
void math_multiply(float val1, float val2, out float outval)
|
||||
void math_multiply(float a, float b, out float result)
|
||||
{
|
||||
outval = val1 * val2;
|
||||
result = a * b;
|
||||
}
|
||||
|
||||
void math_divide(float val1, float val2, out float outval)
|
||||
void math_divide(float a, float b, out float result)
|
||||
{
|
||||
if (val2 == 0.0) {
|
||||
outval = 0.0;
|
||||
result = (b != 0.0) ? a / b : 0.0;
|
||||
}
|
||||
|
||||
void math_power(float a, float b, out float result)
|
||||
{
|
||||
if (a >= 0.0) {
|
||||
result = compatible_pow(a, b);
|
||||
}
|
||||
else {
|
||||
outval = val1 / val2;
|
||||
}
|
||||
}
|
||||
|
||||
void math_sine(float val, out float outval)
|
||||
{
|
||||
outval = sin(val);
|
||||
}
|
||||
|
||||
void math_cosine(float val, out float outval)
|
||||
{
|
||||
outval = cos(val);
|
||||
}
|
||||
|
||||
void math_tangent(float val, out float outval)
|
||||
{
|
||||
outval = tan(val);
|
||||
}
|
||||
|
||||
void math_asin(float val, out float outval)
|
||||
{
|
||||
if (val <= 1.0 && val >= -1.0) {
|
||||
outval = asin(val);
|
||||
}
|
||||
else {
|
||||
outval = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
void math_acos(float val, out float outval)
|
||||
{
|
||||
if (val <= 1.0 && val >= -1.0) {
|
||||
outval = acos(val);
|
||||
}
|
||||
else {
|
||||
outval = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
void math_atan(float val, out float outval)
|
||||
{
|
||||
outval = atan(val);
|
||||
}
|
||||
|
||||
void math_pow(float val1, float val2, out float outval)
|
||||
{
|
||||
if (val1 >= 0.0) {
|
||||
outval = compatible_pow(val1, val2);
|
||||
}
|
||||
else {
|
||||
float val2_mod_1 = mod(abs(val2), 1.0);
|
||||
|
||||
if (val2_mod_1 > 0.999 || val2_mod_1 < 0.001) {
|
||||
outval = compatible_pow(val1, floor(val2 + 0.5));
|
||||
float fraction = mod(abs(b), 1.0);
|
||||
if (fraction > 0.999 || fraction < 0.001) {
|
||||
result = compatible_pow(a, floor(b + 0.5));
|
||||
}
|
||||
else {
|
||||
outval = 0.0;
|
||||
result = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void math_log(float val1, float val2, out float outval)
|
||||
void math_logarithm(float a, float b, out float result)
|
||||
{
|
||||
if (val1 > 0.0 && val2 > 0.0) {
|
||||
outval = log2(val1) / log2(val2);
|
||||
}
|
||||
else {
|
||||
outval = 0.0;
|
||||
}
|
||||
result = (a > 0.0 && b > 0.0) ? log2(a) / log2(b) : 0.0;
|
||||
}
|
||||
|
||||
void math_max(float val1, float val2, out float outval)
|
||||
void math_sqrt(float a, float b, out float result)
|
||||
{
|
||||
outval = max(val1, val2);
|
||||
result = (a > 0.0) ? sqrt(a) : 0.0;
|
||||
}
|
||||
|
||||
void math_min(float val1, float val2, out float outval)
|
||||
void math_absolute(float a, float b, out float result)
|
||||
{
|
||||
outval = min(val1, val2);
|
||||
result = abs(a);
|
||||
}
|
||||
|
||||
void math_round(float val, out float outval)
|
||||
void math_minimum(float a, float b, out float result)
|
||||
{
|
||||
outval = floor(val + 0.5);
|
||||
result = min(a, b);
|
||||
}
|
||||
|
||||
void math_less_than(float val1, float val2, out float outval)
|
||||
void math_maximum(float a, float b, out float result)
|
||||
{
|
||||
if (val1 < val2) {
|
||||
outval = 1.0;
|
||||
}
|
||||
else {
|
||||
outval = 0.0;
|
||||
}
|
||||
result = max(a, b);
|
||||
}
|
||||
|
||||
void math_greater_than(float val1, float val2, out float outval)
|
||||
void math_less_than(float a, float b, out float result)
|
||||
{
|
||||
if (val1 > val2) {
|
||||
outval = 1.0;
|
||||
}
|
||||
else {
|
||||
outval = 0.0;
|
||||
}
|
||||
result = (a < b) ? 1.0 : 0.0;
|
||||
}
|
||||
|
||||
void math_modulo(float val1, float val2, out float outval)
|
||||
void math_greater_than(float a, float b, out float result)
|
||||
{
|
||||
if (val2 == 0.0 || val1 == val2) {
|
||||
outval = 0.0;
|
||||
}
|
||||
else {
|
||||
/* change sign to match C convention, mod in GLSL will take absolute for negative numbers,
|
||||
* see https://www.opengl.org/sdk/docs/man/html/mod.xhtml */
|
||||
outval = sign(val1) * mod(abs(val1), val2);
|
||||
}
|
||||
result = (a > b) ? 1.0 : 0.0;
|
||||
}
|
||||
|
||||
void math_abs(float val1, out float outval)
|
||||
void math_round(float a, float b, out float result)
|
||||
{
|
||||
outval = abs(val1);
|
||||
result = floor(a + 0.5);
|
||||
}
|
||||
|
||||
void math_atan2(float val1, float val2, out float outval)
|
||||
void math_floor(float a, float b, out float result)
|
||||
{
|
||||
outval = atan(val1, val2);
|
||||
result = floor(a);
|
||||
}
|
||||
|
||||
void math_floor(float val, out float outval)
|
||||
void math_ceil(float a, float b, out float result)
|
||||
{
|
||||
outval = floor(val);
|
||||
result = ceil(a);
|
||||
}
|
||||
|
||||
void math_ceil(float val, out float outval)
|
||||
void math_fraction(float a, float b, out float result)
|
||||
{
|
||||
outval = ceil(val);
|
||||
result = a - floor(a);
|
||||
}
|
||||
|
||||
void math_fract(float val, out float outval)
|
||||
/* Change sign to match C convention. mod in GLSL will take absolute for negative numbers.
|
||||
* See https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/mod.xhtml
|
||||
*/
|
||||
void math_modulo(float a, float b, out float result)
|
||||
{
|
||||
outval = val - floor(val);
|
||||
result = (b != 0.0) ? sign(a) * mod(abs(a), b) : 0.0;
|
||||
}
|
||||
|
||||
void math_sqrt(float val, out float outval)
|
||||
void math_sine(float a, float b, out float result)
|
||||
{
|
||||
if (val > 0.0) {
|
||||
outval = sqrt(val);
|
||||
}
|
||||
else {
|
||||
outval = 0.0;
|
||||
}
|
||||
result = sin(a);
|
||||
}
|
||||
|
||||
void math_cosine(float a, float b, out float result)
|
||||
{
|
||||
result = cos(a);
|
||||
}
|
||||
|
||||
void math_tangent(float a, float b, out float result)
|
||||
{
|
||||
result = tan(a);
|
||||
}
|
||||
|
||||
void math_arcsine(float a, float b, out float result)
|
||||
{
|
||||
result = (a <= 1.0 && a >= -1.0) ? asin(a) : 0.0;
|
||||
}
|
||||
|
||||
void math_arccosine(float a, float b, out float result)
|
||||
{
|
||||
result = (a <= 1.0 && a >= -1.0) ? acos(a) : 0.0;
|
||||
}
|
||||
|
||||
void math_arctangent(float a, float b, out float result)
|
||||
{
|
||||
result = atan(a);
|
||||
}
|
||||
|
||||
void math_arctan2(float a, float b, out float result)
|
||||
{
|
||||
result = atan(a, b);
|
||||
}
|
||||
|
||||
void squeeze(float val, float width, float center, out float outval)
|
||||
|
||||
@@ -1167,31 +1167,31 @@ typedef struct NodeDenoise {
|
||||
/* math node clamp */
|
||||
#define SHD_MATH_CLAMP 1
|
||||
|
||||
/* Math node operation/ */
|
||||
/* Math node operations. */
|
||||
enum {
|
||||
NODE_MATH_ADD = 0,
|
||||
NODE_MATH_SUB = 1,
|
||||
NODE_MATH_MUL = 2,
|
||||
NODE_MATH_SUBTRACT = 1,
|
||||
NODE_MATH_MULTIPLY = 2,
|
||||
NODE_MATH_DIVIDE = 3,
|
||||
NODE_MATH_SIN = 4,
|
||||
NODE_MATH_COS = 5,
|
||||
NODE_MATH_TAN = 6,
|
||||
NODE_MATH_ASIN = 7,
|
||||
NODE_MATH_ACOS = 8,
|
||||
NODE_MATH_ATAN = 9,
|
||||
NODE_MATH_POW = 10,
|
||||
NODE_MATH_LOG = 11,
|
||||
NODE_MATH_MIN = 12,
|
||||
NODE_MATH_MAX = 13,
|
||||
NODE_MATH_SINE = 4,
|
||||
NODE_MATH_COSINE = 5,
|
||||
NODE_MATH_TANGENT = 6,
|
||||
NODE_MATH_ARCSINE = 7,
|
||||
NODE_MATH_ARCCOSINE = 8,
|
||||
NODE_MATH_ARCTANGENT = 9,
|
||||
NODE_MATH_POWER = 10,
|
||||
NODE_MATH_LOGARITHM = 11,
|
||||
NODE_MATH_MINIMUM = 12,
|
||||
NODE_MATH_MAXIMUM = 13,
|
||||
NODE_MATH_ROUND = 14,
|
||||
NODE_MATH_LESS = 15,
|
||||
NODE_MATH_GREATER = 16,
|
||||
NODE_MATH_MOD = 17,
|
||||
NODE_MATH_ABS = 18,
|
||||
NODE_MATH_ATAN2 = 19,
|
||||
NODE_MATH_LESS_THAN = 15,
|
||||
NODE_MATH_GREATER_THAN = 16,
|
||||
NODE_MATH_MODULO = 17,
|
||||
NODE_MATH_ABSOLUTE = 18,
|
||||
NODE_MATH_ARCTAN2 = 19,
|
||||
NODE_MATH_FLOOR = 20,
|
||||
NODE_MATH_CEIL = 21,
|
||||
NODE_MATH_FRACT = 22,
|
||||
NODE_MATH_FRACTION = 22,
|
||||
NODE_MATH_SQRT = 23,
|
||||
};
|
||||
|
||||
|
||||
@@ -100,34 +100,38 @@ static const EnumPropertyItem node_chunksize_items[] = {
|
||||
#endif
|
||||
|
||||
const EnumPropertyItem rna_enum_node_math_items[] = {
|
||||
{NODE_MATH_ADD, "ADD", 0, "Add", ""},
|
||||
{NODE_MATH_SUB, "SUBTRACT", 0, "Subtract", ""},
|
||||
{NODE_MATH_MUL, "MULTIPLY", 0, "Multiply", ""},
|
||||
{NODE_MATH_DIVIDE, "DIVIDE", 0, "Divide", ""},
|
||||
{NODE_MATH_ADD, "ADD", 0, "Add", "A + B"},
|
||||
{NODE_MATH_SUBTRACT, "SUBTRACT", 0, "Subtract", "A - B"},
|
||||
{NODE_MATH_MULTIPLY, "MULTIPLY", 0, "Multiply", "A * B"},
|
||||
{NODE_MATH_DIVIDE, "DIVIDE", 0, "Divide", "A / B"},
|
||||
{0, "", ICON_NONE, NULL, NULL},
|
||||
{NODE_MATH_POW, "POWER", 0, "Power", ""},
|
||||
{NODE_MATH_LOG, "LOGARITHM", 0, "Logarithm", ""},
|
||||
{NODE_MATH_SQRT, "SQRT", 0, "Square Root", ""},
|
||||
{NODE_MATH_ABS, "ABSOLUTE", 0, "Absolute", ""},
|
||||
{NODE_MATH_POWER, "POWER", 0, "Power", "A power B"},
|
||||
{NODE_MATH_LOGARITHM, "LOGARITHM", 0, "Logarithm", "Logarithm A base B"},
|
||||
{NODE_MATH_SQRT, "SQRT", 0, "Square Root", "Square root of A"},
|
||||
{NODE_MATH_ABSOLUTE, "ABSOLUTE", 0, "Absolute", "Magnitude of A"},
|
||||
{0, "", ICON_NONE, NULL, NULL},
|
||||
{NODE_MATH_MIN, "MINIMUM", 0, "Minimum", ""},
|
||||
{NODE_MATH_MAX, "MAXIMUM", 0, "Maximum", ""},
|
||||
{NODE_MATH_LESS, "LESS_THAN", 0, "Less Than", ""},
|
||||
{NODE_MATH_GREATER, "GREATER_THAN", 0, "Greater Than", ""},
|
||||
{NODE_MATH_MINIMUM, "MINIMUM", 0, "Minimum", "The minimum from A and B"},
|
||||
{NODE_MATH_MAXIMUM, "MAXIMUM", 0, "Maximum", "The maximum from A and B"},
|
||||
{NODE_MATH_LESS_THAN, "LESS_THAN", 0, "Less Than", "1 if A < B else 0"},
|
||||
{NODE_MATH_GREATER_THAN, "GREATER_THAN", 0, "Greater Than", "1 if A > B else 0"},
|
||||
{0, "", ICON_NONE, NULL, NULL},
|
||||
{NODE_MATH_ROUND, "ROUND", 0, "Round", ""},
|
||||
{NODE_MATH_FLOOR, "FLOOR", 0, "Floor", ""},
|
||||
{NODE_MATH_CEIL, "CEIL", 0, "Ceil", ""},
|
||||
{NODE_MATH_FRACT, "FRACT", 0, "Fract", ""},
|
||||
{NODE_MATH_MOD, "MODULO", 0, "Modulo", ""},
|
||||
{NODE_MATH_ROUND,
|
||||
"ROUND",
|
||||
0,
|
||||
"Round",
|
||||
"Round A to the nearest integer. Round upward if the fraction part is 0.5"},
|
||||
{NODE_MATH_FLOOR, "FLOOR", 0, "Floor", "The largest integer smaller than or equal A"},
|
||||
{NODE_MATH_CEIL, "CEIL", 0, "Ceil", "The smallest integer greater than or equal A"},
|
||||
{NODE_MATH_FRACTION, "FRACT", 0, "Fraction", "The fraction part of A"},
|
||||
{NODE_MATH_MODULO, "MODULO", 0, "Modulo", "A mod B"},
|
||||
{0, "", ICON_NONE, NULL, NULL},
|
||||
{NODE_MATH_SIN, "SINE", 0, "Sine", ""},
|
||||
{NODE_MATH_COS, "COSINE", 0, "Cosine", ""},
|
||||
{NODE_MATH_TAN, "TANGENT", 0, "Tangent", ""},
|
||||
{NODE_MATH_ASIN, "ARCSINE", 0, "Arcsine", ""},
|
||||
{NODE_MATH_ACOS, "ARCCOSINE", 0, "Arccosine", ""},
|
||||
{NODE_MATH_ATAN, "ARCTANGENT", 0, "Arctangent", ""},
|
||||
{NODE_MATH_ATAN2, "ARCTAN2", 0, "Arctan2", ""},
|
||||
{NODE_MATH_SINE, "SINE", 0, "Sine", "sin(A)"},
|
||||
{NODE_MATH_COSINE, "COSINE", 0, "Cosine", "cos(A)"},
|
||||
{NODE_MATH_TANGENT, "TANGENT", 0, "Tangent", "tan(A)"},
|
||||
{NODE_MATH_ARCSINE, "ARCSINE", 0, "Arcsine", "arcsin(A)"},
|
||||
{NODE_MATH_ARCCOSINE, "ARCCOSINE", 0, "Arccosine", "arccos(A)"},
|
||||
{NODE_MATH_ARCTANGENT, "ARCTANGENT", 0, "Arctangent", "arctan(A)"},
|
||||
{NODE_MATH_ARCTAN2, "ARCTAN2", 0, "Arctan2", "The signed angle arctan(A / B)"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
@@ -3852,7 +3856,7 @@ static void def_math(StructRNA *srna)
|
||||
RNA_def_property_enum_sdna(prop, NULL, "custom1");
|
||||
RNA_def_property_enum_items(prop, rna_enum_node_math_items);
|
||||
RNA_def_property_ui_text(prop, "Operation", "");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_clamp", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "custom2", SHD_MATH_CLAMP);
|
||||
|
||||
@@ -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