MaterialX: Add remaining float/vector math operations
Ref #112864 Pull Request: https://projects.blender.org/blender/blender/pulls/117764
This commit is contained in:
committed by
Brecht Van Lommel
parent
3b1230d318
commit
e5b7768830
@@ -181,15 +181,11 @@ static void sh_node_math_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
NODE_SHADER_MATERIALX_BEGIN
|
||||
#ifdef WITH_MATERIALX
|
||||
{
|
||||
CLG_LogRef *LOG_MATERIALX_SHADER = materialx::LOG_MATERIALX_SHADER;
|
||||
|
||||
/* TODO: finish some math operations */
|
||||
NodeMathOperation op = NodeMathOperation(node_->custom1);
|
||||
NodeItem res = empty();
|
||||
|
||||
/* Single operand operations */
|
||||
NodeItem x = get_input_value(0, NodeItem::Type::Float);
|
||||
/* TODO: Seems we have to use average if Vector or Color are added */
|
||||
|
||||
switch (op) {
|
||||
case NODE_MATH_SINE:
|
||||
@@ -259,6 +255,7 @@ NODE_SHADER_MATERIALX_BEGIN
|
||||
default: {
|
||||
/* 2-operand operations */
|
||||
NodeItem y = get_input_value(1, NodeItem::Type::Float);
|
||||
|
||||
switch (op) {
|
||||
case NODE_MATH_ADD:
|
||||
res = x + y;
|
||||
@@ -297,22 +294,30 @@ NODE_SHADER_MATERIALX_BEGIN
|
||||
res = x.atan2(y);
|
||||
break;
|
||||
case NODE_MATH_SNAP:
|
||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||
res = (x / y).floor() * y;
|
||||
break;
|
||||
case NODE_MATH_PINGPONG:
|
||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||
case NODE_MATH_PINGPONG: {
|
||||
NodeItem fract_part = (x - y) / (y * val(2.0f));
|
||||
NodeItem if_branch = ((fract_part - fract_part.floor()) * y * val(2.0f) - y).abs();
|
||||
res = y.if_else(NodeItem::CompareOp::NotEq, val(0.0f), if_branch, val(0.0f));
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_FLOORED_MODULO:
|
||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||
res = y.if_else(
|
||||
NodeItem::CompareOp::NotEq, val(0.0f), (x - (x / y).floor() * y), val(0.0f));
|
||||
break;
|
||||
|
||||
default: {
|
||||
/* 3-operand operations */
|
||||
NodeItem z = get_input_value(2, NodeItem::Type::Float);
|
||||
|
||||
switch (op) {
|
||||
case NODE_MATH_WRAP:
|
||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||
case NODE_MATH_WRAP: {
|
||||
NodeItem range = (y - z);
|
||||
NodeItem if_branch = x - (range * ((x - z) / range).floor());
|
||||
res = range.if_else(NodeItem::CompareOp::NotEq, val(0.0f), if_branch, z);
|
||||
break;
|
||||
}
|
||||
case NODE_MATH_COMPARE:
|
||||
res = z.if_else(NodeItem::CompareOp::Less, (x - y).abs(), val(1.0f), val(0.0f));
|
||||
break;
|
||||
@@ -320,12 +325,20 @@ NODE_SHADER_MATERIALX_BEGIN
|
||||
res = x * y + z;
|
||||
break;
|
||||
case NODE_MATH_SMOOTH_MIN:
|
||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||
case NODE_MATH_SMOOTH_MAX: {
|
||||
auto make_smoothmin = [&](NodeItem a, NodeItem b, NodeItem k) {
|
||||
NodeItem h = (k - (a - b).abs()).max(val(0.0f)) / k;
|
||||
NodeItem if_branch = a.min(b) - h * h * h * k * val(1.0f / 6.0f);
|
||||
return k.if_else(NodeItem::CompareOp::NotEq, val(0.0f), if_branch, a.min(b));
|
||||
};
|
||||
if (op == NODE_MATH_SMOOTH_MIN) {
|
||||
res = make_smoothmin(x, y, z);
|
||||
}
|
||||
else {
|
||||
res = -make_smoothmin(-x, -y, -z);
|
||||
}
|
||||
break;
|
||||
case NODE_MATH_SMOOTH_MAX:
|
||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||
break;
|
||||
|
||||
}
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
|
||||
@@ -319,14 +319,13 @@ static void sh_node_vector_math_build_multi_function(NodeMultiFunctionBuilder &b
|
||||
NODE_SHADER_MATERIALX_BEGIN
|
||||
#ifdef WITH_MATERIALX
|
||||
{
|
||||
CLG_LogRef *LOG_MATERIALX_SHADER = materialx::LOG_MATERIALX_SHADER;
|
||||
|
||||
/* TODO: finish some math operations */
|
||||
auto op = node_->custom1;
|
||||
NodeItem res = empty();
|
||||
const NodeItem null_vec = val(MaterialX::Vector3(0.0f));
|
||||
|
||||
/* Single operand operations */
|
||||
NodeItem x = get_input_value(0, NodeItem::Type::Vector3);
|
||||
|
||||
switch (op) {
|
||||
case NODE_VECTOR_MATH_SINE:
|
||||
res = x.sin();
|
||||
@@ -350,15 +349,19 @@ NODE_SHADER_MATERIALX_BEGIN
|
||||
res = x % val(1.0f);
|
||||
break;
|
||||
case NODE_VECTOR_MATH_LENGTH:
|
||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||
res = x.length();
|
||||
break;
|
||||
case NODE_VECTOR_MATH_NORMALIZE:
|
||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||
case NODE_VECTOR_MATH_NORMALIZE: {
|
||||
NodeItem length = x.length();
|
||||
res = length.if_else(NodeItem::CompareOp::Eq, val(0.0f), null_vec, x / length);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
/* 2-operand operations */
|
||||
NodeItem y = get_input_value(1, NodeItem::Type::Vector3);
|
||||
NodeItem w = get_input_value(3, NodeItem::Type::Float);
|
||||
|
||||
switch (op) {
|
||||
case NODE_VECTOR_MATH_ADD:
|
||||
res = x + y;
|
||||
@@ -382,44 +385,65 @@ NODE_SHADER_MATERIALX_BEGIN
|
||||
res = x % y;
|
||||
break;
|
||||
case NODE_VECTOR_MATH_SNAP:
|
||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||
res = (x / y).floor() * y;
|
||||
break;
|
||||
case NODE_VECTOR_MATH_CROSS_PRODUCT:
|
||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||
res = create_node("crossproduct", NodeItem::Type::Vector3, {{"in1", x}, {"in2", y}});
|
||||
break;
|
||||
case NODE_VECTOR_MATH_DOT_PRODUCT:
|
||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||
res = x.dotproduct(y);
|
||||
break;
|
||||
case NODE_VECTOR_MATH_PROJECT:
|
||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||
case NODE_VECTOR_MATH_PROJECT: {
|
||||
NodeItem len_sq = y.dotproduct(y);
|
||||
res = len_sq.if_else(
|
||||
NodeItem::CompareOp::NotEq, val(0.0f), (x.dotproduct(y) / len_sq) * y, null_vec);
|
||||
break;
|
||||
}
|
||||
case NODE_VECTOR_MATH_REFLECT:
|
||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||
/* TODO: use <reflect> node in MaterialX 1.38.9 */
|
||||
res = x - val(2.0f) * y.dotproduct(x) * y;
|
||||
break;
|
||||
case NODE_VECTOR_MATH_DISTANCE:
|
||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||
res = (y - x).length();
|
||||
break;
|
||||
case NODE_VECTOR_MATH_SCALE:
|
||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||
res = x * w;
|
||||
break;
|
||||
|
||||
default: {
|
||||
/* 3-operand operations */
|
||||
NodeItem z = get_input_value(2, NodeItem::Type::Vector3);
|
||||
|
||||
switch (op) {
|
||||
case NODE_VECTOR_MATH_MULTIPLY_ADD:
|
||||
res = x * y + z;
|
||||
break;
|
||||
case NODE_VECTOR_MATH_REFRACT:
|
||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||
case NODE_VECTOR_MATH_REFRACT: {
|
||||
/* TODO: use <refract> node in MaterialX 1.38.9 */
|
||||
NodeItem dot_yx = y.dotproduct(x);
|
||||
NodeItem k = val(1.0f) - (w * w * (val(1.0f) - (dot_yx * dot_yx)));
|
||||
NodeItem r = w * x - ((w * dot_yx + k.sqrt()) * y);
|
||||
res = k.if_else(NodeItem::CompareOp::GreaterEq, val(0.0f), r, null_vec);
|
||||
break;
|
||||
case NODE_VECTOR_MATH_FACEFORWARD:
|
||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||
break;
|
||||
case NODE_VECTOR_MATH_WRAP:
|
||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||
}
|
||||
case NODE_VECTOR_MATH_FACEFORWARD: {
|
||||
res = z.dotproduct(y).if_else(NodeItem::CompareOp::GreaterEq, val(0.0f), -x, x);
|
||||
break;
|
||||
}
|
||||
case NODE_VECTOR_MATH_WRAP: {
|
||||
NodeItem range = (y - z);
|
||||
NodeItem if_branch = x - (range * ((x - z) / range).floor());
|
||||
|
||||
res = create_node("combine3", NodeItem::Type::Vector3);
|
||||
std::vector<std::string> inputs = {"in1", "in2", "in3"};
|
||||
|
||||
for (size_t i = 0; i < inputs.size(); ++i) {
|
||||
res.set_input(
|
||||
inputs[i],
|
||||
range[i].if_else(NodeItem::CompareOp::NotEq, val(0.0f), if_branch[i], z[i]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user