MaterialX: Add remaining float/vector math operations

Ref #112864

Pull Request: https://projects.blender.org/blender/blender/pulls/117764
This commit is contained in:
Pablo Delgado Krämer
2024-02-05 12:28:22 +01:00
committed by Brecht Van Lommel
parent 3b1230d318
commit e5b7768830
2 changed files with 73 additions and 36 deletions

View File

@@ -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();
}

View File

@@ -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();
}