Code improvements + Mix node #30

Merged
Bogdan Nagirniak merged 18 commits from BogdanNagirniak/blender:matx-code-improvements into matx-export-material 2023-09-22 18:23:13 +02:00
8 changed files with 80 additions and 57 deletions
Showing only changes of commit 01d67d34fe - Show all commits

View File

@ -82,7 +82,7 @@ void MaterialData::init()
scene_delegate_->depsgraph, (Material *)id);
pxr::UsdMtlxRead(doc, stage);
/* Logging stage: creating lambda stage_str() for not to call stage->ExportToString()
/* Logging stage: creating lambda stage_str() to not call stage->ExportToString()
* if log won't be printed. */
auto stage_str = [&stage]() {
std::string str;

View File

@ -184,6 +184,8 @@ NodeItem NodeItem::operator^(const NodeItem &other) const
NodeItem NodeItem::operator[](int index) const
{
BLI_assert(is_arithmetic(type()));
if (value) {
float v = 0.0f;
switch (type()) {
@ -264,6 +266,14 @@ NodeItem NodeItem::length() const
return create_node("magnitude", Type::Float, {{"in", to_vector()}});
}
NodeItem NodeItem::normalize() const
{
if (value) {
return *this / length();
}
return create_node("normalize", Type::Vector3, {{"in", to_vector()}});
}
NodeItem NodeItem::min(const NodeItem &other) const
{
return arithmetic(other, "min", [](float a, float b) { return std::min(a, b); });
@ -363,6 +373,34 @@ NodeItem NodeItem::clamp(float min_val, float max_val) const
return clamp(val(min_val), val(max_val));
}
NodeItem NodeItem::rotate(const NodeItem &angle, const NodeItem &axis)
{
BLI_assert(type() == Type::Vector3);
BLI_assert(angle.type() == Type::Float);
BLI_assert(axis.type() == Type::Vector3);
return create_node(
"rotate3d",
NodeItem::Type::Vector3,
{{"in", *this}, {"amount", angle * val(float(180.0f / M_PI))}, {"axis", axis}});
}
NodeItem NodeItem::rotate(const NodeItem &angle_xyz, bool invert)
{
NodeItem angle = angle_xyz * val(float(180.0f / M_PI));
NodeItem x = angle[0];
NodeItem y = angle[1];
NodeItem z = angle[2];
if (invert) {
return rotate(z, val(MaterialX::Vector3(0.0f, 0.0f, 1.0f)))
.rotate(y, val(MaterialX::Vector3(0.0f, 1.0f, 0.0f)))
.rotate(x, val(MaterialX::Vector3(1.0f, 0.0f, 0.0f)));
}
return rotate(x, val(MaterialX::Vector3(1.0f, 0.0f, 0.0f)))
.rotate(y, val(MaterialX::Vector3(0.0f, 1.0f, 0.0f)))
.rotate(z, val(MaterialX::Vector3(0.0f, 0.0f, 1.0f)));
}
NodeItem NodeItem::sin() const
{
return to_vector().arithmetic("sin", [](float a) { return std::sinf(a); });
@ -706,23 +744,6 @@ NodeItem NodeItem::empty() const
return NodeItem(graph_);
}
NodeItem NodeItem::rotate3d(NodeItem rotation, bool invert)
{
NodeItem res = *this;
if (res.type() == Type::Vector3 && rotation.type() == Type::Vector3) {
for (int i = 0; i <= 2; i++) {
int j = invert ? 2 - i : i;
MaterialX::Vector3 axis_vector = MaterialX::Vector3();
axis_vector[j] = 1.0f;
res = create_node(
"rotate3d",
NodeItem::Type::Vector3,
{{"in", res}, {"amount", rotation.extract(j)}, {"axis", val(axis_vector)}});
}
}
return res;
}
NodeItem::Type NodeItem::type() const
{
if (value) {
@ -882,9 +903,7 @@ NodeItem NodeItem::arithmetic(const std::string &category, std::function<float(f
{
NodeItem res = empty();
Type type = this->type();
if (!is_arithmetic(type)) {
return res;
}
BLI_assert(is_arithmetic(type));
if (value) {
switch (type) {

View File

@ -10,9 +10,11 @@
namespace blender::nodes::materialx {
/* This class serves as abstraction from MateralX API. It implements arithmetic operations,
/**
* This class serves as abstraction from MateralX API. It implements arithmetic operations,
* convertions between different types, adding new nodes, setting inputs, etc.
* All work should be done via this class instead of using MaterialX API directly. */
* All work should be done via this class instead of using MaterialX API directly.
*/
class NodeItem {
public:
using Inputs = std::vector<std::pair<std::string, NodeItem>>;
@ -21,22 +23,22 @@ class NodeItem {
Any = 0,
Empty,
Multioutput,
/* Value types */
String,
Filename,
Boolean,
Integer,
/* Block of arithmetic types. Ordered by type cast */
/* Arithmetic types. NOTE: Ordered by type cast */
Float,
Vector2,
Vector3,
Color3,
Vector4,
Color4,
/* End of arithmetic types */
/* Shader types
* NOTE: There are only supported types */
/* Shader types. NOTE: There are only supported types */
BSDF,
EDF,
Displacementshader,
@ -83,12 +85,15 @@ class NodeItem {
NodeItem floor() const;
NodeItem ceil() const;
NodeItem length() const;
NodeItem normalize() const;
NodeItem min(const NodeItem &other) const;
NodeItem max(const NodeItem &other) const;
NodeItem dotproduct(const NodeItem &other) const;
NodeItem mix(const NodeItem &val1, const NodeItem &val2) const;
NodeItem clamp(const NodeItem &min_val, const NodeItem &max_val) const;
NodeItem clamp(float min_val = 0.0f, float max_val = 1.0f) const;
NodeItem rotate(const NodeItem &angle, const NodeItem &axis);
NodeItem rotate(const NodeItem &angle_xyz, bool invert = false);
NodeItem sin() const;
NodeItem cos() const;
NodeItem tan() const;
@ -112,7 +117,6 @@ class NodeItem {
/* Useful functions */
NodeItem empty() const;
NodeItem rotate3d(NodeItem rotation, bool invert = false);
template<class T> NodeItem val(const T &data) const;
Type type() const;

View File

@ -18,6 +18,10 @@ extern struct CLG_LogRef *LOG_MATERIALX_SHADER;
class GroupNodeParser;
/**
* This is base abstraction class for parsing Blender nodes into MaterialX nodes.
* NodeParser::compute() should be overrides in child classes.
*/
class NodeParser {
protected:
MaterialX::GraphElement *graph_;
@ -72,8 +76,21 @@ template<class T> NodeItem NodeParser::val(const T &data) const
return empty().val(data);
}
/*
/**
* Defines for including MaterialX node parsing code into node_shader_<name>.cc
*
* Example:
* \code{.c}
* NODE_SHADER_MATERIALX_BEGIN
* #ifdef WITH_MATERIALX
* {
* NodeItem color = get_input_value("Color", NodeItem::Type::Color4);
* NodeItem gamma = get_input_value("Gamma", NodeItem::Type::Float);
* return color ^ gamma;
* }
* #endif
* NODE_SHADER_MATERIALX_END
* \endcode
*/
struct NodeParserData {
MaterialX::GraphElement *graph;

View File

@ -348,14 +348,7 @@ NODE_SHADER_MATERIALX_BEGIN
NodeItem n_main_tangent = empty();
if (tangent && normal) {
NodeItem n_tangent_rotate = create_node(
"rotate3d",
NodeItem::Type::Vector3,
{{"in", tangent}, {"amount", rotation * val(360.0f)}, {"axis", normal}});
NodeItem n_tangent_rotate_normalize = create_node(
"normalize", NodeItem::Type::Vector3, {{"in", n_tangent_rotate}});
NodeItem n_tangent_rotate_normalize = tangent.rotate(rotation, normal).normalize();
n_main_tangent = anisotropy.if_else(
NodeItem::CompareOp::Greater, val(0.0f), n_tangent_rotate_normalize, tangent);
}
@ -375,14 +368,8 @@ NODE_SHADER_MATERIALX_BEGIN
{"normal", coat_normal}});
if (tangent && coat_normal) {
NodeItem n_coat_tangent_rotate = create_node(
"rotate3d",
NodeItem::Type::Vector3,
{{"in", tangent}, {"amount", rotation * val(360.0f)}, {"axis", coat_normal}});
NodeItem n_coat_tangent_rotate_normalize = create_node(
"normalize", NodeItem::Type::Vector3, {{"in", n_coat_tangent_rotate}});
NodeItem n_coat_tangent_rotate_normalize =
tangent.rotate(rotation, coat_normal).normalize();
NodeItem n_coat_tangent = anisotropy.if_else(
NodeItem::CompareOp::Greater, val(0.0f), n_coat_tangent_rotate_normalize, tangent);

View File

@ -22,6 +22,7 @@ static int node_shader_gpu_gamma(GPUMaterial *mat,
{
return GPU_stack_link(mat, node, "node_gamma", in, out);
}
NODE_SHADER_MATERIALX_BEGIN
#ifdef WITH_MATERIALX
{

View File

@ -79,34 +79,30 @@ NODE_SHADER_MATERIALX_BEGIN
{
NodeItem res = empty();
NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector3);
if (!vector) {
return res;
return empty();
}
NodeItem scale = get_input_value("Scale", NodeItem::Type::Vector3);
NodeItem location = get_input_value("Location", NodeItem::Type::Vector3);
NodeItem rotation = (get_input_value("Rotation", NodeItem::Type::Vector3) *
val(float(180.0f / M_PI)));
NodeItem rotation = get_input_value("Rotation", NodeItem::Type::Vector3);
switch (node_->custom1) {
case NODE_MAPPING_TYPE_POINT:
res = (vector * scale).rotate3d(rotation) + location;
return (vector * scale).rotate(rotation) + location;
break;
case NODE_MAPPING_TYPE_TEXTURE:
res = (vector - location).rotate3d(rotation, true) / scale;
res = (vector - location).rotate(rotation, true) / scale;
break;
case NODE_MAPPING_TYPE_VECTOR:
res = (vector * scale).rotate3d(rotation * val(MaterialX::Vector3(1.0f, 1.0f, -1.0f)));
res = (vector * scale).rotate(rotation * val(MaterialX::Vector3(1.0f, 1.0f, -1.0f)));
break;
case NODE_MAPPING_TYPE_NORMAL:
res = create_node(
"normalize", NodeItem::Type::Vector3, {{"in", (vector / scale).rotate3d(rotation)}});
res = (vector / scale).rotate(rotation).normalize();
break;
default:
BLI_assert_unreachable();
}
return res;
}
#endif

View File

@ -237,12 +237,11 @@ NODE_SHADER_MATERIALX_BEGIN
angle = get_input_value("Angle", NodeItem::Type::Float);
}
angle = angle * val(float(180.0f / M_PI));
angle = invert ? angle * val(-1.0f) : angle;
switch (mode) {
case NODE_VECTOR_ROTATE_TYPE_EULER_XYZ: {
return res.rotate3d(angle, invert) + center;
return res.rotate(angle, invert) + center;
}
case NODE_VECTOR_ROTATE_TYPE_AXIS: {
axis = get_input_value("Axis", NodeItem::Type::Vector3) *