forked from blender/blender
Code improvements + Mix node #30
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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) *
|
||||
|
Loading…
Reference in New Issue
Block a user