Move the MaterialX export code into the existing shader node files #18

Merged
Bogdan Nagirniak merged 14 commits from BogdanNagirniak/blender:matx-move-code into matx-export-material 2023-09-12 13:55:27 +02:00
45 changed files with 6 additions and 1401 deletions
Showing only changes of commit f3ebde0f7b - Show all commits

View File

@ -147,14 +147,12 @@ set(LIB
if(WITH_MATERIALX)
list(APPEND SRC
materialx/material.cc
materialx/nodes/node_item.cc
materialx/nodes/node_parser.cc
materialx/nodes/output_material.cc
materialx/node_item.cc
materialx/node_parser.cc
materialx/material.h
materialx/nodes/node_item.h
materialx/nodes/node_parser.h
materialx/nodes/output_material.h
materialx/node_item.h
materialx/node_parser.h
)
list(APPEND LIB
MaterialXCore

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "material.h"
#include "nodes/output_material.h"
#include "node_parser.h"
#include <MaterialXFormat/XmlIo.h>

View File

@ -3,7 +3,6 @@
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_item.h"
#include "../material.h"
#include "BLI_assert.h"
#include "BLI_utildefines.h"

View File

@ -3,7 +3,6 @@
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
#include "../material.h"
#include "BKE_node_runtime.hh"

View File

@ -1,42 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem AddShaderNodeParser::compute()
{
NodeItem res = empty();
switch (to_type_) {
case NodeItem::Type::BSDF:
case NodeItem::Type::EDF: {
NodeItem shader1 = get_input_shader(0, to_type_);
NodeItem shader2 = get_input_shader(1, to_type_);
if (shader1 && !shader2) {
res = shader1;
}
else if (!shader1 && shader2) {
res = shader2;
}
else if (shader1 && shader2) {
res = shader1 + shader2;
}
break;
}
case NodeItem::Type::SurfaceShader: {
res = get_input_shader(0, to_type_);
if (!res) {
res = get_input_shader(1, to_type_);
}
break;
}
default:
BLI_assert_unreachable();
}
return res;
}
} // namespace blender::nodes::materialx

View File

@ -1,22 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem BlackbodyNodeParser::compute()
{
/* This node doesn't have an implementation in MaterialX 1.38.6.
* It's added in MaterialX 1.38.8. Uncomment this code after switching to 1.38.8.
*
* NodeItem temperature = get_input_value("Temperature", NodeItem::Type::Float);
* NodeItem res = create_node("blackbody", NodeItem::Type::Color3);
* res.set_input("temperature", temperature);
* return res; */
return empty();
}
} // namespace blender::nodes::materialx

View File

@ -1,19 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem BrightContrastNodeParser::compute()
{
NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
NodeItem bright = get_input_value("Bright", NodeItem::Type::Float);
NodeItem contrast = get_input_value("Contrast", NodeItem::Type::Float);
/* This formula was given from OSL shader code in Cycles. */
return (bright + color * (contrast + val(1.0f)) - contrast * val(0.5f)).max(val(0.0f));
}
} // namespace blender::nodes::materialx

View File

@ -1,28 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem BSDFDiffuseNodeParser::compute()
{
if (to_type_ != NodeItem::Type::BSDF) {
return empty();
}
NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
NodeItem roughness = get_input_value("Roughness", NodeItem::Type::Float);
NodeItem normal = get_input_link("Normal", NodeItem::Type::Vector3);
NodeItem res = create_node("oren_nayar_diffuse_bsdf", NodeItem::Type::BSDF);
res.set_input("color", color);
res.set_input("roughness", roughness);
if (normal) {
res.set_input("normal", normal);
}
return res;
}
} // namespace blender::nodes::materialx

View File

@ -1,15 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem BSDFGlassNodeParser::compute()
{
/* TODO: implement */
return empty();
}
} // namespace blender::nodes::materialx

View File

@ -1,15 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem BSDFGlossyNodeParser::compute()
{
/* TODO: implement */
return empty();
}
} // namespace blender::nodes::materialx

View File

@ -1,101 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem BSDFPrincipledNodeParser::compute()
{
if (to_type_ != NodeItem::Type::SurfaceShader) {
/* TODO: implement for BSDF and EDF */
return empty();
}
NodeItem base_color = get_input_value("Base Color", NodeItem::Type::Color3);
NodeItem subsurface = get_input_value("Subsurface", NodeItem::Type::Float);
NodeItem subsurface_radius = get_input_value("Subsurface Radius", NodeItem::Type::Color3);
NodeItem subsurface_color = get_input_value("Subsurface Color", NodeItem::Type::Color3);
NodeItem metallic = get_input_value("Metallic", NodeItem::Type::Float);
NodeItem specular = get_input_value("Specular", NodeItem::Type::Float);
// NodeItem specular_tint = get_input_value("Specular Tint");
NodeItem roughness = get_input_value("Roughness", NodeItem::Type::Float);
/* TODO: use Specular Tint input */
NodeItem anisotropic = get_input_value("Anisotropic", NodeItem::Type::Float);
NodeItem anisotropic_rotation = get_input_value("Anisotropic Rotation", NodeItem::Type::Float);
// anisotropic_rotation = 0.5 - (anisotropic_rotation % 1.0)
NodeItem sheen = get_input_value("Sheen", NodeItem::Type::Float);
// sheen_tint = get_input_value("Sheen Tint");
NodeItem clearcoat = get_input_value("Clearcoat", NodeItem::Type::Float);
NodeItem clearcoat_roughness = get_input_value("Clearcoat Roughness", NodeItem::Type::Float);
NodeItem ior = get_input_value("IOR", NodeItem::Type::Float);
NodeItem transmission = get_input_value("Transmission", NodeItem::Type::Float);
NodeItem emission = get_input_value("Emission", NodeItem::Type::Color3);
NodeItem emission_strength = get_input_value("Emission Strength", NodeItem::Type::Float);
NodeItem alpha = get_input_value("Alpha", NodeItem::Type::Float);
// transparency = 1.0 - alpha
NodeItem normal = get_input_link("Normal", NodeItem::Type::Vector3);
NodeItem clearcoat_normal = get_input_link("Clearcoat Normal", NodeItem::Type::Vector3);
NodeItem tangent = get_input_link("Tangent", NodeItem::Type::Vector3);
/* Creating standard_surface */
NodeItem res = create_node("standard_surface", NodeItem::Type::SurfaceShader);
res.set_input("base", val(1.0f));
res.set_input("base_color", base_color);
res.set_input("diffuse_roughness", roughness);
if (normal) {
res.set_input("normal", normal);
}
if (tangent) {
res.set_input("tangent", tangent);
}
res.set_input("metalness", metallic);
res.set_input("specular", specular);
res.set_input("specular_color", base_color);
res.set_input("specular_roughness", roughness);
res.set_input("specular_IOR", ior);
res.set_input("specular_anisotropy", anisotropic);
res.set_input("specular_rotation", anisotropic_rotation);
res.set_input("transmission", transmission);
res.set_input("transmission_color", base_color);
res.set_input("transmission_extra_roughness", roughness);
res.set_input("subsurface", subsurface);
res.set_input("subsurface_color", subsurface_color);
res.set_input("subsurface_radius", subsurface_radius);
res.set_input("subsurface_anisotropy", anisotropic);
res.set_input("sheen", sheen);
res.set_input("sheen_color", base_color);
res.set_input("sheen_roughness", roughness);
res.set_input("coat", clearcoat);
res.set_input("coat_color", base_color);
res.set_input("coat_roughness", clearcoat_roughness);
res.set_input("coat_IOR", ior);
res.set_input("coat_anisotropy", anisotropic);
res.set_input("coat_rotation", anisotropic_rotation);
if (clearcoat_normal) {
res.set_input("coat_normal", clearcoat_normal);
}
res.set_input("emission", emission_strength);
res.set_input("emission_color", emission);
return res;
}
} // namespace blender::nodes::materialx

View File

@ -1,15 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem BSDFRefractionNodeParser::compute()
{
/* TODO: implement */
return empty();
}
} // namespace blender::nodes::materialx

View File

@ -1,15 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem BSDFSheenNodeParser::compute()
{
/* TODO: implement */
return empty();
}
} // namespace blender::nodes::materialx

View File

@ -1,15 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem BSDFToonNodeParser::compute()
{
/* TODO: implement */
return empty();
}
} // namespace blender::nodes::materialx

View File

@ -1,15 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem BSDFTranslucentNodeParser::compute()
{
/* TODO: implement */
return empty();
}
} // namespace blender::nodes::materialx

View File

@ -1,15 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem BSDFTransparentNodeParser::compute()
{
/* TODO: implement */
return empty();
}
} // namespace blender::nodes::materialx

View File

@ -1,27 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem ClampNodeParser::compute()
{
auto type = node_->custom1;
NodeItem value = get_input_value("Value", NodeItem::Type::Float);
NodeItem min = get_input_value("Min", NodeItem::Type::Float);
NodeItem max = get_input_value("Max", NodeItem::Type::Float);
NodeItem res = empty();
if (type == NODE_CLAMP_RANGE) {
res = min.if_else(
NodeItem::CompareOp::Less, max, value.clamp(min, max), value.clamp(max, min));
}
else {
res = value.clamp(min, max);
}
return res;
}
} // namespace blender::nodes::materialx

View File

@ -1,15 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem ColorRampNodeParser::compute()
{
/* TODO: implement */
return empty();
}
} // namespace blender::nodes::materialx

View File

@ -1,21 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem CurvesRGBNodeParser::compute()
{
/* TODO: implement */
return get_input_value("Color", NodeItem::Type::Color4);
}
NodeItem CurvesFloatNodeParser::compute()
{
/* TODO: implement */
return get_input_value("Value", NodeItem::Type::Float);
}
} // namespace blender::nodes::materialx

View File

@ -1,23 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem EmissionNodeParser::compute()
{
if (to_type_ != NodeItem::Type::EDF) {
return empty();
}
NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
NodeItem strength = get_input_value("Strength", NodeItem::Type::Float);
NodeItem res = create_node("uniform_edf", NodeItem::Type::EDF);
res.set_input("color", color * strength);
return res;
}
} // namespace blender::nodes::materialx

View File

@ -1,17 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem GammaNodeParser::compute()
{
NodeItem color = get_input_value("Color", NodeItem::Type::Color4);
NodeItem gamma = get_input_value("Gamma", NodeItem::Type::Float);
return color ^ gamma;
}
} // namespace blender::nodes::materialx

View File

@ -1,33 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem HueSatValNodeParser::compute()
{
/* TODO: implement fac, see do_hue_sat_fac in
* source\blender\nodes\texture\nodes\node_texture_hueSatVal.cc */
NodeItem hue = get_input_value("Hue", NodeItem::Type::Float);
NodeItem saturation = get_input_value("Saturation", NodeItem::Type::Float);
NodeItem value = get_input_value("Value", NodeItem::Type::Float);
NodeItem fac = get_input_value("Fac", NodeItem::Type::Float);
NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
/* Modifier to follow Cycles result */
hue = hue - val(0.5f);
NodeItem combine = create_node("combine3", NodeItem::Type::Vector3);
combine.set_input("in1", hue);
combine.set_input("in2", saturation);
combine.set_input("in3", value);
NodeItem res = create_node("hsvadjust", NodeItem::Type::Color3);
res.set_input("in", color);
res.set_input("amount", combine);
return res;
}
} // namespace blender::nodes::materialx

View File

@ -1,16 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem InvertNodeParser::compute()
{
NodeItem fac = get_input_value("Fac", NodeItem::Type::Float);
NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
return fac.blend(color, fac.val(1.0f) - color);
}
} // namespace blender::nodes::materialx

View File

@ -1,21 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem LightFalloffNodeParser::compute()
{
NodeItem strength = get_input_value("Strength", NodeItem::Type::Float);
NodeItem smooth = get_input_value("Smooth", NodeItem::Type::Float);
/* This node isn't supported by MaterialX. This formula was given from OSL shader code in Cycles
* node_light_falloff.osl. Considered ray_length=1.0f. */
strength = strength * val(1.0f) / (smooth + val(1.0f));
return strength;
}
} // namespace blender::nodes::materialx

View File

@ -1,21 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem LightPathNodeParser::compute()
{
/* This node isn't supported by MaterialX. Only default values returned. */
if (STREQ(socket_out_->name, "Is Camera Ray")) {
return val(1.0f);
}
if (STREQ(socket_out_->name, "Ray Length")) {
return val(1.0f);
}
return val(0.0f);
}
} // namespace blender::nodes::materialx

View File

@ -1,51 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem MapRangeNodeParser::compute()
{
/* Interpolation isn't supported by MaterialX. */
const NodeMapRange *map_range = static_cast<NodeMapRange *>(node_->storage);
NodeItem::Type type;
NodeItem value = empty();
NodeItem from_min = empty();
NodeItem from_max = empty();
NodeItem to_min = empty();
NodeItem to_max = empty();
switch (map_range->data_type) {
case CD_PROP_FLOAT:
type = NodeItem::Type::Float;
value = get_input_value("Value", type);
from_min = get_input_value(1, type);
from_max = get_input_value(2, type);
to_min = get_input_value(3, type);
to_max = get_input_value(4, type);
break;
case CD_PROP_FLOAT3:
type = NodeItem::Type::Vector3;
value = get_input_value("Vector", type);
from_min = get_input_value(7, type);
from_max = get_input_value(8, type);
to_min = get_input_value(9, type);
to_max = get_input_value(10, type);
break;
default:
BLI_assert_unreachable();
}
NodeItem res = create_node("range", type);
res.set_input("in", value);
res.set_input("inlow", from_min);
res.set_input("inhigh", from_max);
res.set_input("outlow", to_min);
res.set_input("outhigh", to_max);
res.set_input("doclamp", val(bool(map_range->clamp)));
return res;
}
} // namespace blender::nodes::materialx

View File

@ -1,171 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "../material.h"
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem MathNodeParser::compute()
{
/* 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:
res = x.sin();
break;
case NODE_MATH_COSINE:
res = x.cos();
break;
case NODE_MATH_TANGENT:
res = x.tan();
break;
case NODE_MATH_ARCSINE:
res = x.asin();
break;
case NODE_MATH_ARCCOSINE:
res = x.acos();
break;
case NODE_MATH_ARCTANGENT:
res = x.atan();
break;
case NODE_MATH_ROUND:
res = (x + val(0.5f)).floor();
break;
case NODE_MATH_ABSOLUTE:
res = x.abs();
break;
case NODE_MATH_FLOOR:
res = x.floor();
break;
case NODE_MATH_CEIL:
res = x.ceil();
break;
case NODE_MATH_FRACTION:
res = x % val(1.0f);
break;
case NODE_MATH_SQRT:
res = x.sqrt();
break;
case NODE_MATH_INV_SQRT:
res = val(1.0f) / x.sqrt();
break;
case NODE_MATH_SIGN:
res = x.sign();
break;
case NODE_MATH_EXPONENT:
res = x.exp();
break;
case NODE_MATH_RADIANS:
res = x * val(float(M_PI) / 180.0f);
break;
case NODE_MATH_DEGREES:
res = x * val(180.0f * float(M_1_PI));
break;
case NODE_MATH_SINH:
res = x.sinh();
break;
case NODE_MATH_COSH:
res = x.cosh();
break;
case NODE_MATH_TANH:
res = x.tanh();
break;
case NODE_MATH_TRUNC:
res = x.sign() * x.abs().floor();
break;
default: {
/* 2-operand operations */
NodeItem y = get_input_value(1, NodeItem::Type::Float);
switch (op) {
case NODE_MATH_ADD:
res = x + y;
break;
case NODE_MATH_SUBTRACT:
res = x - y;
break;
case NODE_MATH_MULTIPLY:
res = x * y;
break;
case NODE_MATH_DIVIDE:
res = x / y;
break;
case NODE_MATH_POWER:
res = x ^ y;
break;
case NODE_MATH_LOGARITHM:
res = x.ln() / y.ln();
break;
case NODE_MATH_MINIMUM:
res = x.min(y);
break;
case NODE_MATH_MAXIMUM:
res = x.max(y);
break;
case NODE_MATH_LESS_THAN:
res = x.if_else(NodeItem::CompareOp::Less, y, val(1.0f), val(0.0f));
break;
case NODE_MATH_GREATER_THAN:
res = x.if_else(NodeItem::CompareOp::Greater, y, val(1.0f), val(0.0f));
break;
case NODE_MATH_MODULO:
res = x % y;
break;
case NODE_MATH_ARCTAN2:
res = x.atan2(y);
break;
case NODE_MATH_SNAP:
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
break;
case NODE_MATH_PINGPONG:
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
break;
case NODE_MATH_FLOORED_MODULO:
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
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);
break;
case NODE_MATH_COMPARE:
res = z.if_else(NodeItem::CompareOp::Less, (x - y).abs(), val(1.0f), val(0.0f));
break;
case NODE_MATH_MULTIPLY_ADD:
res = x * y + z;
break;
case NODE_MATH_SMOOTH_MIN:
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
break;
case NODE_MATH_SMOOTH_MAX:
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
break;
default:
BLI_assert_unreachable();
}
}
}
}
}
bool clamp_output = node_->custom2 != 0;
if (clamp_output && res) {
res = res.clamp();
}
return res;
}
} // namespace blender::nodes::materialx

View File

@ -1,15 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem MixRGBNodeParser::compute()
{
/* TODO: implement */
return empty();
}
} // namespace blender::nodes::materialx

View File

@ -1,46 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem MixShaderNodeParser::compute()
{
NodeItem res = empty();
switch (to_type_) {
case NodeItem::Type::BSDF:
case NodeItem::Type::EDF: {
NodeItem fac = get_input_value(0, NodeItem::Type::Float);
NodeItem shader1 = get_input_shader(1, to_type_);
NodeItem shader2 = get_input_shader(2, to_type_);
if (shader1 && !shader2) {
res = shader1 * (val(1.0f) - fac);
}
else if (!shader1 && shader2) {
res = shader2 * fac;
}
else if (shader1 && shader2) {
res = create_node("mix", to_type_);
res.set_input("fg", shader1);
res.set_input("bg", shader2);
res.set_input("mix", fac);
}
break;
}
case NodeItem::Type::SurfaceShader: {
res = get_input_shader(1, NodeItem::Type::SurfaceShader);
if (!res) {
res = get_input_shader(2, NodeItem::Type::SurfaceShader);
}
break;
}
default:
BLI_assert_unreachable();
}
return res;
}
} // namespace blender::nodes::materialx

View File

@ -1,40 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "../material.h"
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem NormalMapNodeParser::compute()
{
std::string default_space = "object";
NodeShaderNormalMap *normal_map_node = static_cast<NodeShaderNormalMap *>(node_->storage);
NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
NodeItem strength = get_input_value("Strength", NodeItem::Type::Float);
NodeItem res = create_node("normalmap", NodeItem::Type::Vector3);
res.set_input("in", color);
res.set_input("scale", strength);
switch (normal_map_node->space) {
case SHD_SPACE_TANGENT:
res.set_input("space", val(std::string("tangent")));
break;
case SHD_SPACE_OBJECT:
res.set_input("space", val(std::string("tangent")));
break;
default:
res.set_input("space", val(default_space));
CLOG_WARN(LOG_MATERIALX_SHADER,
"Ignoring unsupported Space: %d %s (%d), %s will be used",
normal_map_node->space,
node_->name,
node_->type,
default_space);
}
return res;
}
} // namespace blender::nodes::materialx

View File

@ -1,65 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "output_material.h"
namespace blender::nodes::materialx {
OutputMaterialNodeParser::OutputMaterialNodeParser(MaterialX::GraphElement *graph,
const Depsgraph *depsgraph,
const Material *material,
const bNode *node)
: NodeParser(graph, depsgraph, material, node, nullptr, NodeItem::Type::Material)
{
}
NodeItem OutputMaterialNodeParser::compute()
{
NodeItem surface = empty();
if (node_) {
NodeItem bsdf = get_input_link("Surface", NodeItem::Type::BSDF);
NodeItem edf = get_input_link("Surface", NodeItem::Type::EDF);
if (bsdf || edf) {
surface = create_node("surface", NodeItem::Type::SurfaceShader);
if (bsdf) {
surface.set_input("bsdf", bsdf);
}
if (edf) {
surface.set_input("edf", edf);
}
}
else {
surface = get_input_link("Surface", NodeItem::Type::SurfaceShader);
}
}
else {
surface = create_node("standard_surface", NodeItem::Type::SurfaceShader);
surface.set_input("base_color", val(MaterialX::Color3(1.0f, 0.0f, 1.0f)));
}
NodeItem res = create_node("surfacematerial", NodeItem::Type::Material);
res.set_input("surfaceshader", surface);
return res;
}
NodeItem OutputMaterialNodeParser::compute_default()
{
NodeItem surface = create_node("standard_surface", NodeItem::Type::SurfaceShader);
surface.set_input("base_color",
val(MaterialX::Color3(material_->r, material_->g, material_->b)));
surface.set_input("diffuse_roughness", val(material_->roughness));
if (material_->metallic > 0.0f) {
surface.set_input("metalness", val(material_->metallic));
}
if (material_->spec) {
surface.set_input("specular", val(material_->spec));
surface.set_input("specular_color", val(material_->spec));
surface.set_input("specular_roughness", val(material_->roughness));
}
NodeItem res = create_node("surfacematerial", NodeItem::Type::Material);
res.node->setName("Material_Default");
res.set_input("surfaceshader", surface);
return res;
}
} // namespace blender::nodes::materialx

View File

@ -1,23 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "node_parser.h"
namespace blender::nodes::materialx {
class OutputMaterialNodeParser : public NodeParser {
public:
OutputMaterialNodeParser(MaterialX::GraphElement *graph,
const Depsgraph *depsgraph,
const Material *material,
const bNode *node);
NodeItem compute() override;
using NodeParser::compute_full;
NodeItem compute_default();
};
} // namespace blender::nodes::materialx

View File

@ -1,18 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem RGBToBWNodeParser::compute()
{
NodeItem color = get_input_value("Color", NodeItem::Type::Color4);
NodeItem res = create_node("luminance", NodeItem::Type::Color4);
res.set_input("in", color);
return res;
}
} // namespace blender::nodes::materialx

View File

@ -1,72 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "../material.h"
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem SeparateColorNodeParser::compute()
{
int mode = static_cast<NodeCombSepColor *>(node_->storage)->mode;
NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
NodeItem convert = empty();
switch (mode) {
case NODE_COMBSEP_COLOR_RGB:
break;
case NODE_COMBSEP_COLOR_HSV:
convert = create_node("rgbtohsv", NodeItem::Type::Color3);
convert.set_input("in", color);
break;
case NODE_COMBSEP_COLOR_HSL:
CLOG_WARN(LOG_MATERIALX_SHADER, "Unsupported color model, using HSV instead: %d", mode);
convert = create_node("rgbtohsv", NodeItem::Type::Color3);
convert.set_input("in", color);
break;
default:
BLI_assert_unreachable();
}
int index = STREQ(socket_out_->name, "Red") ? 0 : STREQ(socket_out_->name, "Green") ? 1 : 2;
NodeItem res = convert ? convert : color;
return res.extract(index);
}
NodeItem CombineColorNodeParser::compute()
{
int mode = static_cast<NodeCombSepColor *>(node_->storage)->mode;
NodeItem red = get_input_value("Red", NodeItem::Type::Float);
NodeItem green = get_input_value("Green", NodeItem::Type::Float);
NodeItem blue = get_input_value("Blue", NodeItem::Type::Float);
NodeItem convert = empty();
NodeItem combine = create_node("combine3", NodeItem::Type::Color3);
combine.set_input("in1", red);
combine.set_input("in2", green);
combine.set_input("in3", blue);
switch (mode) {
case NODE_COMBSEP_COLOR_RGB:
break;
case NODE_COMBSEP_COLOR_HSV:
convert = create_node("hsvtorgb", NodeItem::Type::Color3);
convert.set_input("in", combine);
break;
case NODE_COMBSEP_COLOR_HSL:
CLOG_WARN(LOG_MATERIALX_SHADER, "Unsupported color model, using HSV instead: %d", mode);
convert = create_node("hsvtorgb", NodeItem::Type::Color3);
convert.set_input("in", combine);
break;
default:
BLI_assert_unreachable();
}
NodeItem res = convert ? convert : combine;
return res;
}
} // namespace blender::nodes::materialx

View File

@ -1,28 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem SeparateXYZNodeParser::compute()
{
NodeItem vector = get_input_value("Vector", NodeItem::Type::Vector3);
int index = STREQ(socket_out_->name, "X") ? 0 : STREQ(socket_out_->name, "Y") ? 1 : 2;
return vector.extract(index);
}
NodeItem CombineXYZNodeParser::compute()
{
NodeItem x = get_input_value("X", NodeItem::Type::Float);
NodeItem y = get_input_value("Y", NodeItem::Type::Float);
NodeItem z = get_input_value("Z", NodeItem::Type::Float);
NodeItem res = create_node("combine3", NodeItem::Type::Vector3);
res.set_input("in1", x);
res.set_input("in2", y);
res.set_input("in3", z);
return res;
}
} // namespace blender::nodes::materialx

View File

@ -1,15 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem SubsurfaceScatteringNodeParser::compute()
{
/* TODO: implement */
return empty();
}
} // namespace blender::nodes::materialx

View File

@ -1,28 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem TexCheckerNodeParser::compute()
{
NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector2);
if (!vector) {
vector = texcoord_node();
}
NodeItem value1 = val(1.0f);
NodeItem value2 = val(0.0f);
if (STREQ(socket_out_->name, "Color")) {
value1 = get_input_value("Color1", NodeItem::Type::Color4);
value2 = get_input_value("Color2", NodeItem::Type::Color4);
}
NodeItem scale = get_input_value("Scale", NodeItem::Type::Float);
vector = (vector * scale) % val(2.0f);
return (vector.extract(0).floor() + vector.extract(1).floor())
.if_else(NodeItem::CompareOp::Eq, val(1.0f), value1, value2);
}
} // namespace blender::nodes::materialx

View File

@ -1,61 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
#include "hydra/image.h"
#include "DEG_depsgraph_query.h"
namespace blender::nodes::materialx {
NodeItem TexEnvironmentNodeParser::compute()
{
NodeItem res = val(MaterialX::Color4(1.0f, 0.0f, 1.0f, 1.0f));
Image *image = (Image *)node_->id;
if (!image) {
return res;
}
NodeTexEnvironment *tex_env = static_cast<NodeTexEnvironment *>(node_->storage);
Scene *scene = DEG_get_input_scene(depsgraph_);
Main *bmain = DEG_get_bmain(depsgraph_);
/* TODO: What if Blender built without Hydra? Also io::hydra::cache_or_get_image_file contains
* pretty general code, so could be moved from bf_usd project. */
std::string image_path = io::hydra::cache_or_get_image_file(
bmain, scene, image, &tex_env->iuser);
NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector2);
if (!vector) {
vector = texcoord_node();
}
/* TODO: texcoords should be translated to spherical coordinates */
std::string filtertype;
switch (tex_env->interpolation) {
case SHD_INTERP_LINEAR:
filtertype = "linear";
break;
case SHD_INTERP_CLOSEST:
filtertype = "closest";
break;
case SHD_INTERP_CUBIC:
case SHD_INTERP_SMART:
filtertype = "cubic";
break;
default:
BLI_assert_unreachable();
}
res = create_node("image", NodeItem::Type::Color4);
res.set_input("file", image_path, NodeItem::Type::Filename);
res.set_input("texcoord", vector);
res.set_input("filtertype", val(filtertype));
return res;
}
} // namespace blender::nodes::materialx

View File

@ -1,81 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
#include "hydra/image.h"
#include "DEG_depsgraph_query.h"
namespace blender::nodes::materialx {
NodeItem TexImageNodeParser::compute()
{
NodeItem res = val(MaterialX::Color4(1.0f, 0.0f, 1.0f, 1.0f));
Image *image = (Image *)node_->id;
if (image) {
NodeTexImage *tex_image = static_cast<NodeTexImage *>(node_->storage);
Scene *scene = DEG_get_input_scene(depsgraph_);
Main *bmain = DEG_get_bmain(depsgraph_);
/* TODO: What if Blender built without Hydra? Also io::hydra::cache_or_get_image_file contains
* pretty general code, so could be moved from bf_usd project. */
std::string image_path = io::hydra::cache_or_get_image_file(
bmain, scene, image, &tex_image->iuser);
NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector2);
if (!vector) {
vector = texcoord_node();
}
/* TODO: add math to vector depending of tex_image->projection */
std::string filtertype;
switch (tex_image->interpolation) {
case SHD_INTERP_LINEAR:
filtertype = "linear";
break;
case SHD_INTERP_CLOSEST:
filtertype = "closest";
break;
case SHD_INTERP_CUBIC:
case SHD_INTERP_SMART:
filtertype = "cubic";
break;
default:
BLI_assert_unreachable();
}
std::string addressmode;
switch (tex_image->extension) {
case SHD_IMAGE_EXTENSION_REPEAT:
addressmode = "periodic";
break;
case SHD_IMAGE_EXTENSION_EXTEND:
addressmode = "clamp";
break;
case SHD_IMAGE_EXTENSION_CLIP:
addressmode = "constant";
break;
case SHD_IMAGE_EXTENSION_MIRROR:
addressmode = "mirror";
break;
default:
BLI_assert_unreachable();
}
res = create_node("image", NodeItem::Type::Color4);
res.set_input("file", image_path, NodeItem::Type::Filename);
res.set_input("texcoord", vector);
res.set_input("filtertype", val(filtertype));
res.set_input("uaddressmode", val(addressmode));
res.set_input("vaddressmode", val(addressmode));
}
if (STREQ(socket_out_->name, "Alpha")) {
res = res.extract(3);
}
return res;
}
} // namespace blender::nodes::materialx

View File

@ -1,29 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem TexNoiseNodeParser::compute()
{
NodeItem scale = get_input_value("Scale", NodeItem::Type::Float);
NodeItem detail = get_input_value("Detail", NodeItem::Type::Float);
NodeItem lacunarity = get_input_value("Lacunarity", NodeItem::Type::Float);
if (detail.value && detail.type() == NodeItem::Type::Float) {
detail = val(int(detail.value->asA<float>()));
}
NodeItem position = create_node("position", NodeItem::Type::Vector3);
position = position * scale;
NodeItem res = create_node("fractal3d", NodeItem::Type::Color3);
res.set_input("position", position);
res.set_input("octaves", detail);
res.set_input("lacunarity", lacunarity);
return res;
}
} // namespace blender::nodes::materialx

View File

@ -1,122 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "../material.h"
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem VectorMathNodeParser::compute()
{
/* TODO: finish some math operations */
auto op = node_->custom1;
NodeItem res = empty();
/* Single operand operations */
NodeItem x = get_input_value(0, NodeItem::Type::Vector3);
switch (op) {
case NODE_VECTOR_MATH_SINE:
res = x.sin();
break;
case NODE_VECTOR_MATH_COSINE:
res = x.cos();
break;
case NODE_VECTOR_MATH_TANGENT:
res = x.tan();
break;
case NODE_VECTOR_MATH_ABSOLUTE:
res = x.abs();
break;
case NODE_VECTOR_MATH_FLOOR:
res = x.floor();
break;
case NODE_VECTOR_MATH_CEIL:
res = x.ceil();
break;
case NODE_VECTOR_MATH_FRACTION:
res = x % val(1.0f);
break;
case NODE_VECTOR_MATH_LENGTH:
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
break;
case NODE_VECTOR_MATH_NORMALIZE:
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
break;
default: {
/* 2-operand operations */
NodeItem y = get_input_value(1, NodeItem::Type::Vector3);
switch (op) {
case NODE_VECTOR_MATH_ADD:
res = x + y;
break;
case NODE_VECTOR_MATH_SUBTRACT:
res = x - y;
break;
case NODE_VECTOR_MATH_MULTIPLY:
res = x * y;
break;
case NODE_VECTOR_MATH_DIVIDE:
res = x / y;
break;
case NODE_VECTOR_MATH_MINIMUM:
res = x.min(y);
break;
case NODE_VECTOR_MATH_MAXIMUM:
res = x.max(y);
break;
case NODE_VECTOR_MATH_MODULO:
res = x % y;
break;
case NODE_VECTOR_MATH_SNAP:
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
break;
case NODE_VECTOR_MATH_CROSS_PRODUCT:
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
break;
case NODE_VECTOR_MATH_DOT_PRODUCT:
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
break;
case NODE_VECTOR_MATH_PROJECT:
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
break;
case NODE_VECTOR_MATH_REFLECT:
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
break;
case NODE_VECTOR_MATH_DISTANCE:
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
break;
case NODE_VECTOR_MATH_SCALE:
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
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);
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);
break;
default:
BLI_assert_unreachable();
}
}
}
}
}
return res;
}
} // namespace blender::nodes::materialx

View File

@ -1,15 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem WavelengthNodeParser::compute()
{
/* TODO: implement */
return empty();
}
} // namespace blender::nodes::materialx

View File

@ -22,7 +22,7 @@
#include "node_shader_register.hh"
#include "materialx/nodes/node_parser.h"
#include "materialx/node_parser.h"
struct bContext;
typedef struct bContext bContext;