forked from blender/blender
MaterialX: add convert nodes #15
@ -147,27 +147,39 @@ set(LIB
|
|||||||
if(WITH_MATERIALX)
|
if(WITH_MATERIALX)
|
||||||
list(APPEND SRC
|
list(APPEND SRC
|
||||||
materialx/material.cc
|
materialx/material.cc
|
||||||
|
materialx/nodes/add_shader.cc
|
||||||
materialx/nodes/blackbody.cc
|
materialx/nodes/blackbody.cc
|
||||||
materialx/nodes/brightness.cc
|
materialx/nodes/brightness.cc
|
||||||
|
materialx/nodes/bsdf_diffuse.cc
|
||||||
|
materialx/nodes/bsdf_glass.cc
|
||||||
|
materialx/nodes/bsdf_glossy.cc
|
||||||
materialx/nodes/bsdf_principled.cc
|
materialx/nodes/bsdf_principled.cc
|
||||||
|
materialx/nodes/bsdf_refraction.cc
|
||||||
|
materialx/nodes/bsdf_sheen.cc
|
||||||
|
materialx/nodes/bsdf_toon.cc
|
||||||
|
materialx/nodes/bsdf_translucent.cc
|
||||||
|
materialx/nodes/bsdf_transparent.cc
|
||||||
materialx/nodes/clamp.cc
|
materialx/nodes/clamp.cc
|
||||||
|
materialx/nodes/emission.cc
|
||||||
materialx/nodes/huesatval.cc
|
materialx/nodes/huesatval.cc
|
||||||
materialx/nodes/invert.cc
|
materialx/nodes/invert.cc
|
||||||
materialx/nodes/map_range.cc
|
materialx/nodes/map_range.cc
|
||||||
materialx/nodes/math.cc
|
materialx/nodes/math.cc
|
||||||
materialx/nodes/mix_rgb.cc
|
materialx/nodes/mix_rgb.cc
|
||||||
|
materialx/nodes/mix_shader.cc
|
||||||
materialx/nodes/node_item.cc
|
materialx/nodes/node_item.cc
|
||||||
materialx/nodes/node_parser.cc
|
materialx/nodes/node_parser.cc
|
||||||
materialx/nodes/normal_map.cc
|
materialx/nodes/normal_map.cc
|
||||||
materialx/nodes/output_material.cc
|
materialx/nodes/output_material.cc
|
||||||
materialx/nodes/sepcomb_color.cc
|
materialx/nodes/sepcomb_color.cc
|
||||||
materialx/nodes/sepcomb_xyz.cc
|
materialx/nodes/sepcomb_xyz.cc
|
||||||
|
materialx/nodes/subsurface_scattering.cc
|
||||||
materialx/nodes/tex_checker.cc
|
materialx/nodes/tex_checker.cc
|
||||||
materialx/nodes/tex_environment.cc
|
materialx/nodes/tex_environment.cc
|
||||||
materialx/nodes/tex_image.cc
|
materialx/nodes/tex_image.cc
|
||||||
materialx/nodes/tex_noise.cc
|
materialx/nodes/tex_noise.cc
|
||||||
materialx/nodes/vector_math.cc
|
materialx/nodes/vector_math.cc
|
||||||
|
|
||||||
materialx/material.h
|
materialx/material.h
|
||||||
materialx/nodes/node_item.h
|
materialx/nodes/node_item.h
|
||||||
materialx/nodes/node_parser.h
|
materialx/nodes/node_parser.h
|
||||||
|
@ -17,9 +17,7 @@ namespace blender::nodes::materialx {
|
|||||||
|
|
||||||
CLG_LOGREF_DECLARE_GLOBAL(LOG_MATERIALX_SHADER, "materialx.shader");
|
CLG_LOGREF_DECLARE_GLOBAL(LOG_MATERIALX_SHADER, "materialx.shader");
|
||||||
|
|
||||||
MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph,
|
MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, Material *material)
|
||||||
Material *material,
|
|
||||||
const std::string &socket_name)
|
|
||||||
{
|
{
|
||||||
CLOG_INFO(LOG_MATERIALX_SHADER, 0, "Material: %s", material->id.name);
|
CLOG_INFO(LOG_MATERIALX_SHADER, 0, "Material: %s", material->id.name);
|
||||||
|
|
||||||
@ -27,14 +25,14 @@ MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph,
|
|||||||
if (material->use_nodes) {
|
if (material->use_nodes) {
|
||||||
material->nodetree->ensure_topology_cache();
|
material->nodetree->ensure_topology_cache();
|
||||||
bNode *output_node = ntreeShaderOutputNode(material->nodetree, SHD_OUTPUT_ALL);
|
bNode *output_node = ntreeShaderOutputNode(material->nodetree, SHD_OUTPUT_ALL);
|
||||||
OutputMaterialNodeParser(doc.get(), depsgraph, material, output_node).compute(socket_name);
|
OutputMaterialNodeParser(doc.get(), depsgraph, material, output_node).compute_full();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
OutputMaterialNodeParser(doc.get(), depsgraph, material, nullptr).compute_default();
|
OutputMaterialNodeParser(doc.get(), depsgraph, material, nullptr).compute_default();
|
||||||
}
|
}
|
||||||
|
|
||||||
CLOG_INFO(LOG_MATERIALX_SHADER,
|
CLOG_INFO(LOG_MATERIALX_SHADER,
|
||||||
2,
|
1,
|
||||||
"Material: %s\n%s",
|
"Material: %s\n%s",
|
||||||
material->id.name,
|
material->id.name,
|
||||||
MaterialX::writeToXmlString(doc).c_str());
|
MaterialX::writeToXmlString(doc).c_str());
|
||||||
|
@ -15,8 +15,6 @@ namespace blender::nodes::materialx {
|
|||||||
|
|
||||||
extern struct CLG_LogRef *LOG_MATERIALX_SHADER;
|
extern struct CLG_LogRef *LOG_MATERIALX_SHADER;
|
||||||
|
|
||||||
MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph,
|
MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, Material *material);
|
||||||
Material *material,
|
|
||||||
const std::string &socket_name = "Surface");
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
} // namespace blender::nodes::materialx
|
||||||
|
42
source/blender/nodes/shader/materialx/nodes/add_shader.cc
Normal file
42
source/blender/nodes/shader/materialx/nodes/add_shader.cc
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/* 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 (shader_type_) {
|
||||||
|
case NodeItem::Type::BSDF:
|
||||||
|
case NodeItem::Type::EDF: {
|
||||||
|
NodeItem shader1 = get_input_shader(0, shader_type_);
|
||||||
|
NodeItem shader2 = get_input_shader(1, shader_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, shader_type_);
|
||||||
|
if (!res) {
|
||||||
|
res = get_input_shader(1, shader_type_);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace blender::nodes::materialx
|
@ -13,7 +13,7 @@ NodeItem BrightContrastNodeParser::compute()
|
|||||||
NodeItem contrast = get_input_value("Contrast", NodeItem::Type::Float);
|
NodeItem contrast = get_input_value("Contrast", NodeItem::Type::Float);
|
||||||
|
|
||||||
/* This formula was given from OSL shader code in Cycles. */
|
/* This formula was given from OSL shader code in Cycles. */
|
||||||
return (bright + color * (contrast + value(1.0f)) - contrast * value(0.5f)).max(value(0.0f));
|
return (bright + color * (contrast + val(1.0f)) - contrast * val(0.5f)).max(val(0.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
} // namespace blender::nodes::materialx
|
||||||
|
28
source/blender/nodes/shader/materialx/nodes/bsdf_diffuse.cc
Normal file
28
source/blender/nodes/shader/materialx/nodes/bsdf_diffuse.cc
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/* 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 (shader_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
|
15
source/blender/nodes/shader/materialx/nodes/bsdf_glass.cc
Normal file
15
source/blender/nodes/shader/materialx/nodes/bsdf_glass.cc
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* 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
|
15
source/blender/nodes/shader/materialx/nodes/bsdf_glossy.cc
Normal file
15
source/blender/nodes/shader/materialx/nodes/bsdf_glossy.cc
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* 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
|
@ -8,6 +8,11 @@ namespace blender::nodes::materialx {
|
|||||||
|
|
||||||
NodeItem BSDFPrincipledNodeParser::compute()
|
NodeItem BSDFPrincipledNodeParser::compute()
|
||||||
{
|
{
|
||||||
|
if (shader_type_ != NodeItem::Type::SurfaceShader) {
|
||||||
|
/* TODO: implement for BSDF and EDF */
|
||||||
|
return empty();
|
||||||
|
}
|
||||||
|
|
||||||
NodeItem base_color = get_input_value("Base Color", NodeItem::Type::Color3);
|
NodeItem base_color = get_input_value("Base Color", NodeItem::Type::Color3);
|
||||||
|
|
||||||
NodeItem subsurface = get_input_value("Subsurface", NodeItem::Type::Float);
|
NodeItem subsurface = get_input_value("Subsurface", NodeItem::Type::Float);
|
||||||
@ -40,13 +45,13 @@ NodeItem BSDFPrincipledNodeParser::compute()
|
|||||||
NodeItem alpha = get_input_value("Alpha", NodeItem::Type::Float);
|
NodeItem alpha = get_input_value("Alpha", NodeItem::Type::Float);
|
||||||
// transparency = 1.0 - alpha
|
// transparency = 1.0 - alpha
|
||||||
|
|
||||||
NodeItem normal = get_input_link("Normal");
|
NodeItem normal = get_input_link("Normal", NodeItem::Type::Vector3);
|
||||||
NodeItem clearcoat_normal = get_input_link("Clearcoat Normal");
|
NodeItem clearcoat_normal = get_input_link("Clearcoat Normal", NodeItem::Type::Vector3);
|
||||||
NodeItem tangent = get_input_link("Tangent");
|
NodeItem tangent = get_input_link("Tangent", NodeItem::Type::Vector3);
|
||||||
|
|
||||||
/* Creating standard_surface */
|
/* Creating standard_surface */
|
||||||
NodeItem res = create_node("standard_surface", "surfaceshader");
|
NodeItem res = create_node("standard_surface", NodeItem::Type::SurfaceShader);
|
||||||
res.set_input("base", 1.0, "float");
|
res.set_input("base", val(1.0f));
|
||||||
res.set_input("base_color", base_color);
|
res.set_input("base_color", base_color);
|
||||||
res.set_input("diffuse_roughness", roughness);
|
res.set_input("diffuse_roughness", roughness);
|
||||||
if (normal) {
|
if (normal) {
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
/* 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
|
15
source/blender/nodes/shader/materialx/nodes/bsdf_sheen.cc
Normal file
15
source/blender/nodes/shader/materialx/nodes/bsdf_sheen.cc
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* 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
|
15
source/blender/nodes/shader/materialx/nodes/bsdf_toon.cc
Normal file
15
source/blender/nodes/shader/materialx/nodes/bsdf_toon.cc
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* 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
|
@ -0,0 +1,15 @@
|
|||||||
|
/* 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
|
@ -0,0 +1,15 @@
|
|||||||
|
/* 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
|
23
source/blender/nodes/shader/materialx/nodes/emission.cc
Normal file
23
source/blender/nodes/shader/materialx/nodes/emission.cc
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/* 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 (shader_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
|
@ -12,19 +12,19 @@ NodeItem HueSatValNodeParser::compute()
|
|||||||
* source\blender\nodes\texture\nodes\node_texture_hueSatVal.cc */
|
* source\blender\nodes\texture\nodes\node_texture_hueSatVal.cc */
|
||||||
NodeItem hue = get_input_value("Hue", NodeItem::Type::Float);
|
NodeItem hue = get_input_value("Hue", NodeItem::Type::Float);
|
||||||
NodeItem saturation = get_input_value("Saturation", NodeItem::Type::Float);
|
NodeItem saturation = get_input_value("Saturation", NodeItem::Type::Float);
|
||||||
NodeItem val = get_input_value("Value", NodeItem::Type::Float);
|
NodeItem value = get_input_value("Value", NodeItem::Type::Float);
|
||||||
NodeItem fac = get_input_value("Fac", NodeItem::Type::Float);
|
NodeItem fac = get_input_value("Fac", NodeItem::Type::Float);
|
||||||
NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
|
NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
|
||||||
|
|
||||||
/* Modifier to follow Cycles result */
|
/* Modifier to follow Cycles result */
|
||||||
hue = hue - value(0.5f);
|
hue = hue - val(0.5f);
|
||||||
|
|
||||||
NodeItem combine = create_node("combine3", "vector3");
|
NodeItem combine = create_node("combine3", NodeItem::Type::Vector3);
|
||||||
combine.set_input("in1", hue);
|
combine.set_input("in1", hue);
|
||||||
combine.set_input("in2", saturation);
|
combine.set_input("in2", saturation);
|
||||||
combine.set_input("in3", val);
|
combine.set_input("in3", value);
|
||||||
|
|
||||||
NodeItem res = create_node("hsvadjust", "color3");
|
NodeItem res = create_node("hsvadjust", NodeItem::Type::Color3);
|
||||||
res.set_input("in", color);
|
res.set_input("in", color);
|
||||||
res.set_input("amount", combine);
|
res.set_input("amount", combine);
|
||||||
return res;
|
return res;
|
||||||
|
@ -12,7 +12,7 @@ NodeItem MapRangeNodeParser::compute()
|
|||||||
const NodeMapRange *map_range = static_cast<NodeMapRange *>(node_->storage);
|
const NodeMapRange *map_range = static_cast<NodeMapRange *>(node_->storage);
|
||||||
|
|
||||||
NodeItem::Type type;
|
NodeItem::Type type;
|
||||||
NodeItem val = empty();
|
NodeItem value = empty();
|
||||||
NodeItem from_min = empty();
|
NodeItem from_min = empty();
|
||||||
NodeItem from_max = empty();
|
NodeItem from_max = empty();
|
||||||
NodeItem to_min = empty();
|
NodeItem to_min = empty();
|
||||||
@ -20,7 +20,7 @@ NodeItem MapRangeNodeParser::compute()
|
|||||||
switch (map_range->data_type) {
|
switch (map_range->data_type) {
|
||||||
case CD_PROP_FLOAT:
|
case CD_PROP_FLOAT:
|
||||||
type = NodeItem::Type::Float;
|
type = NodeItem::Type::Float;
|
||||||
val = get_input_value("Value", type);
|
value = get_input_value("Value", type);
|
||||||
from_min = get_input_value(1, type);
|
from_min = get_input_value(1, type);
|
||||||
from_max = get_input_value(2, type);
|
from_max = get_input_value(2, type);
|
||||||
to_min = get_input_value(3, type);
|
to_min = get_input_value(3, type);
|
||||||
@ -28,7 +28,7 @@ NodeItem MapRangeNodeParser::compute()
|
|||||||
break;
|
break;
|
||||||
case CD_PROP_FLOAT3:
|
case CD_PROP_FLOAT3:
|
||||||
type = NodeItem::Type::Vector3;
|
type = NodeItem::Type::Vector3;
|
||||||
val = get_input_value("Vector", type);
|
value = get_input_value("Vector", type);
|
||||||
from_min = get_input_value(7, type);
|
from_min = get_input_value(7, type);
|
||||||
from_max = get_input_value(8, type);
|
from_max = get_input_value(8, type);
|
||||||
to_min = get_input_value(9, type);
|
to_min = get_input_value(9, type);
|
||||||
@ -38,13 +38,13 @@ NodeItem MapRangeNodeParser::compute()
|
|||||||
BLI_assert_unreachable();
|
BLI_assert_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem res = create_node("range", NodeItem::type(type));
|
NodeItem res = create_node("range", type);
|
||||||
res.set_input("in", val);
|
res.set_input("in", value);
|
||||||
res.set_input("inlow", from_min);
|
res.set_input("inlow", from_min);
|
||||||
res.set_input("inhigh", from_max);
|
res.set_input("inhigh", from_max);
|
||||||
res.set_input("outlow", to_min);
|
res.set_input("outlow", to_min);
|
||||||
res.set_input("outhigh", to_max);
|
res.set_input("outhigh", to_max);
|
||||||
res.set_input("doclamp", value(bool(map_range->clamp)));
|
res.set_input("doclamp", val(bool(map_range->clamp)));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ NodeItem MathNodeParser::compute()
|
|||||||
NodeItem res = empty();
|
NodeItem res = empty();
|
||||||
|
|
||||||
/* Single operand operations */
|
/* Single operand operations */
|
||||||
NodeItem x = get_input_value(0, NodeItem::Type::Empty);
|
NodeItem x = get_input_value(0, NodeItem::Type::Any);
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case NODE_MATH_SINE:
|
case NODE_MATH_SINE:
|
||||||
res = x.sin();
|
res = x.sin();
|
||||||
@ -35,7 +35,7 @@ NodeItem MathNodeParser::compute()
|
|||||||
res = x.atan();
|
res = x.atan();
|
||||||
break;
|
break;
|
||||||
case NODE_MATH_ROUND:
|
case NODE_MATH_ROUND:
|
||||||
res = (x + value(0.5f)).floor();
|
res = (x + val(0.5f)).floor();
|
||||||
break;
|
break;
|
||||||
case NODE_MATH_ABSOLUTE:
|
case NODE_MATH_ABSOLUTE:
|
||||||
res = x.abs();
|
res = x.abs();
|
||||||
@ -47,13 +47,13 @@ NodeItem MathNodeParser::compute()
|
|||||||
res = x.ceil();
|
res = x.ceil();
|
||||||
break;
|
break;
|
||||||
case NODE_MATH_FRACTION:
|
case NODE_MATH_FRACTION:
|
||||||
res = x % value(1.0f);
|
res = x % val(1.0f);
|
||||||
break;
|
break;
|
||||||
case NODE_MATH_SQRT:
|
case NODE_MATH_SQRT:
|
||||||
res = x.sqrt();
|
res = x.sqrt();
|
||||||
break;
|
break;
|
||||||
case NODE_MATH_INV_SQRT:
|
case NODE_MATH_INV_SQRT:
|
||||||
res = value(1.0f) / x.sqrt();
|
res = val(1.0f) / x.sqrt();
|
||||||
break;
|
break;
|
||||||
case NODE_MATH_SIGN:
|
case NODE_MATH_SIGN:
|
||||||
res = x.sign();
|
res = x.sign();
|
||||||
@ -62,10 +62,10 @@ NodeItem MathNodeParser::compute()
|
|||||||
res = x.exp();
|
res = x.exp();
|
||||||
break;
|
break;
|
||||||
case NODE_MATH_RADIANS:
|
case NODE_MATH_RADIANS:
|
||||||
res = x * value(float(M_PI) / 180.0f);
|
res = x * val(float(M_PI) / 180.0f);
|
||||||
break;
|
break;
|
||||||
case NODE_MATH_DEGREES:
|
case NODE_MATH_DEGREES:
|
||||||
res = x * value(180.0f * float(M_1_PI));
|
res = x * val(180.0f * float(M_1_PI));
|
||||||
break;
|
break;
|
||||||
case NODE_MATH_SINH:
|
case NODE_MATH_SINH:
|
||||||
res = x.sinh();
|
res = x.sinh();
|
||||||
@ -82,7 +82,7 @@ NodeItem MathNodeParser::compute()
|
|||||||
|
|
||||||
default: {
|
default: {
|
||||||
/* 2-operand operations */
|
/* 2-operand operations */
|
||||||
NodeItem y = get_input_value(1, NodeItem::Type::Empty);
|
NodeItem y = get_input_value(1, NodeItem::Type::Any);
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case NODE_MATH_ADD:
|
case NODE_MATH_ADD:
|
||||||
res = x + y;
|
res = x + y;
|
||||||
@ -109,10 +109,10 @@ NodeItem MathNodeParser::compute()
|
|||||||
res = x.max(y);
|
res = x.max(y);
|
||||||
break;
|
break;
|
||||||
case NODE_MATH_LESS_THAN:
|
case NODE_MATH_LESS_THAN:
|
||||||
res = x.if_else(NodeItem::CompareOp::Less, y, value(1.0f), value(0.0f));
|
res = x.if_else(NodeItem::CompareOp::Less, y, val(1.0f), val(0.0f));
|
||||||
break;
|
break;
|
||||||
case NODE_MATH_GREATER_THAN:
|
case NODE_MATH_GREATER_THAN:
|
||||||
res = x.if_else(NodeItem::CompareOp::Greater, y, value(1.0f), value(0.0f));
|
res = x.if_else(NodeItem::CompareOp::Greater, y, val(1.0f), val(0.0f));
|
||||||
break;
|
break;
|
||||||
case NODE_MATH_MODULO:
|
case NODE_MATH_MODULO:
|
||||||
res = x % y;
|
res = x % y;
|
||||||
@ -132,13 +132,13 @@ NodeItem MathNodeParser::compute()
|
|||||||
|
|
||||||
default: {
|
default: {
|
||||||
/* 3-operand operations */
|
/* 3-operand operations */
|
||||||
NodeItem z = get_input_value(2, NodeItem::Type::Empty);
|
NodeItem z = get_input_value(2, NodeItem::Type::Any);
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case NODE_MATH_WRAP:
|
case NODE_MATH_WRAP:
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||||
break;
|
break;
|
||||||
case NODE_MATH_COMPARE:
|
case NODE_MATH_COMPARE:
|
||||||
res = z.if_else(NodeItem::CompareOp::Less, (x - y).abs(), value(1.0f), value(0.0f));
|
res = z.if_else(NodeItem::CompareOp::Less, (x - y).abs(), val(1.0f), val(0.0f));
|
||||||
break;
|
break;
|
||||||
case NODE_MATH_MULTIPLY_ADD:
|
case NODE_MATH_MULTIPLY_ADD:
|
||||||
res = x * y + z;
|
res = x * y + z;
|
||||||
|
46
source/blender/nodes/shader/materialx/nodes/mix_shader.cc
Normal file
46
source/blender/nodes/shader/materialx/nodes/mix_shader.cc
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/* 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 (shader_type_) {
|
||||||
|
case NodeItem::Type::BSDF:
|
||||||
|
case NodeItem::Type::EDF: {
|
||||||
|
NodeItem fac = get_input_value(0, NodeItem::Type::Float);
|
||||||
|
NodeItem shader1 = get_input_shader(1, shader_type_);
|
||||||
|
NodeItem shader2 = get_input_shader(2, shader_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", shader_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
|
@ -12,6 +12,91 @@ namespace blender::nodes::materialx {
|
|||||||
|
|
||||||
NodeItem::NodeItem(MaterialX::GraphElement *graph) : graph_(graph) {}
|
NodeItem::NodeItem(MaterialX::GraphElement *graph) : graph_(graph) {}
|
||||||
|
|
||||||
|
NodeItem::Type NodeItem::type(const std::string &type_str)
|
||||||
|
{
|
||||||
|
if (type_str == "string") {
|
||||||
|
return Type::String;
|
||||||
|
}
|
||||||
|
if (type_str == "filename") {
|
||||||
|
return Type::Filename;
|
||||||
|
}
|
||||||
|
if (type_str == "boolean") {
|
||||||
|
return Type::Bool;
|
||||||
|
}
|
||||||
|
if (type_str == "integer") {
|
||||||
|
return Type::Integer;
|
||||||
|
}
|
||||||
|
if (type_str == "float") {
|
||||||
|
return Type::Float;
|
||||||
|
}
|
||||||
|
if (type_str == "vector2") {
|
||||||
|
return Type::Vector2;
|
||||||
|
}
|
||||||
|
if (type_str == "vector3") {
|
||||||
|
return Type::Vector3;
|
||||||
|
}
|
||||||
|
if (type_str == "vector4") {
|
||||||
|
return Type::Vector4;
|
||||||
|
}
|
||||||
|
if (type_str == "color3") {
|
||||||
|
return Type::Color3;
|
||||||
|
}
|
||||||
|
if (type_str == "color4") {
|
||||||
|
return Type::Color4;
|
||||||
|
}
|
||||||
|
if (type_str == "BSDF") {
|
||||||
|
return Type::BSDF;
|
||||||
|
}
|
||||||
|
if (type_str == "EDF") {
|
||||||
|
return Type::EDF;
|
||||||
|
}
|
||||||
|
if (type_str == "surfaceshader") {
|
||||||
|
return Type::SurfaceShader;
|
||||||
|
}
|
||||||
|
if (type_str == "material") {
|
||||||
|
return Type::Material;
|
||||||
|
}
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
return Type::Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string NodeItem::type(Type type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case Type::String:
|
||||||
|
return "string";
|
||||||
|
case Type::Filename:
|
||||||
|
return "filename";
|
||||||
|
case Type::Bool:
|
||||||
|
return "boolean";
|
||||||
|
case Type::Integer:
|
||||||
|
return "integer";
|
||||||
|
case Type::Float:
|
||||||
|
return "float";
|
||||||
|
case Type::Vector2:
|
||||||
|
return "vector2";
|
||||||
|
case Type::Vector3:
|
||||||
|
return "vector3";
|
||||||
|
case Type::Vector4:
|
||||||
|
return "vector4";
|
||||||
|
case Type::Color3:
|
||||||
|
return "color3";
|
||||||
|
case Type::Color4:
|
||||||
|
return "color4";
|
||||||
|
case Type::BSDF:
|
||||||
|
return "BSDF";
|
||||||
|
case Type::EDF:
|
||||||
|
return "EDF";
|
||||||
|
case Type::SurfaceShader:
|
||||||
|
return "surfaceshader";
|
||||||
|
case Type::Material:
|
||||||
|
return "material";
|
||||||
|
default:
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
NodeItem::operator bool() const
|
NodeItem::operator bool() const
|
||||||
{
|
{
|
||||||
return value || node;
|
return value || node;
|
||||||
@ -19,6 +104,21 @@ NodeItem::operator bool() const
|
|||||||
|
|
||||||
NodeItem NodeItem::operator+(const NodeItem &other) const
|
NodeItem NodeItem::operator+(const NodeItem &other) const
|
||||||
{
|
{
|
||||||
|
Type type = this->type();
|
||||||
|
if (ELEM(type, Type::BSDF, Type::EDF)) {
|
||||||
|
/* Special case: add BSDF/EDF shaders */
|
||||||
|
NodeItem res = empty();
|
||||||
|
if (other.type() == type) {
|
||||||
|
res = create_node("add", type);
|
||||||
|
res.set_input("in1", *this);
|
||||||
|
res.set_input("in2", other);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
return arithmetic(other, "add", [](float a, float b) { return a + b; });
|
return arithmetic(other, "add", [](float a, float b) { return a + b; });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,6 +134,22 @@ NodeItem NodeItem::operator-() const
|
|||||||
|
|
||||||
NodeItem NodeItem::operator*(const NodeItem &other) const
|
NodeItem NodeItem::operator*(const NodeItem &other) const
|
||||||
{
|
{
|
||||||
|
Type type = this->type();
|
||||||
|
if (ELEM(type, Type::BSDF, Type::EDF)) {
|
||||||
|
/* Special case: multiple BSDF/EDF shader by Float or Color3 */
|
||||||
|
NodeItem res = empty();
|
||||||
|
Type other_type = other.type();
|
||||||
|
if (ELEM(other_type, Type::Float, Type::Color3)) {
|
||||||
|
res = create_node("multiply", type);
|
||||||
|
res.set_input("in1", *this);
|
||||||
|
res.set_input("in2", other);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
return arithmetic(other, "multiply", [](float a, float b) { return a * b; });
|
return arithmetic(other, "multiply", [](float a, float b) { return a * b; });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +186,7 @@ bool NodeItem::operator==(const NodeItem &other) const
|
|||||||
|
|
||||||
NodeItem item1 = *this;
|
NodeItem item1 = *this;
|
||||||
NodeItem item2 = other;
|
NodeItem item2 = other;
|
||||||
Type to_type = adjust_types(item1, item2);
|
Type to_type = cast_types(item1, item2);
|
||||||
if (to_type == Type::Empty) {
|
if (to_type == Type::Empty) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -111,9 +227,8 @@ NodeItem NodeItem::dotproduct(const NodeItem &other) const
|
|||||||
{
|
{
|
||||||
NodeItem d = arithmetic(other, "dotproduct", [](float a, float b) { return a * b; });
|
NodeItem d = arithmetic(other, "dotproduct", [](float a, float b) { return a * b; });
|
||||||
if (d.value) {
|
if (d.value) {
|
||||||
Type mx_type = d.type();
|
|
||||||
float f = 0.0f;
|
float f = 0.0f;
|
||||||
switch (mx_type) {
|
switch (d.type()) {
|
||||||
case Type::Float: {
|
case Type::Float: {
|
||||||
f = value->asA<float>();
|
f = value->asA<float>();
|
||||||
break;
|
break;
|
||||||
@ -239,7 +354,7 @@ NodeItem NodeItem::exp() const
|
|||||||
NodeItem NodeItem::extract(const int index) const
|
NodeItem NodeItem::extract(const int index) const
|
||||||
{
|
{
|
||||||
NodeItem res = empty();
|
NodeItem res = empty();
|
||||||
res.node = graph_->addNode("extract", MaterialX::EMPTY_STRING, "float");
|
res = create_node("extract", Type::Float);
|
||||||
res.set_input("in", *this);
|
res.set_input("in", *this);
|
||||||
res.set_input("index", val(index));
|
res.set_input("index", val(index));
|
||||||
return res;
|
return res;
|
||||||
@ -248,10 +363,14 @@ NodeItem NodeItem::extract(const int index) const
|
|||||||
NodeItem NodeItem::convert(Type to_type) const
|
NodeItem NodeItem::convert(Type to_type) const
|
||||||
{
|
{
|
||||||
Type from_type = type();
|
Type from_type = type();
|
||||||
if (from_type == to_type) {
|
if (from_type == Type::Empty || from_type == to_type || to_type == Type::Any) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
if (!is_arithmetic(from_type) || !is_arithmetic(to_type)) {
|
if (!is_arithmetic(from_type) || !is_arithmetic(to_type)) {
|
||||||
|
CLOG_WARN(LOG_MATERIALX_SHADER,
|
||||||
|
"Cannot convert: %s -> %s",
|
||||||
|
type(from_type).c_str(),
|
||||||
|
type(to_type).c_str());
|
||||||
return empty();
|
return empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,7 +538,7 @@ NodeItem NodeItem::convert(Type to_type) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
res.node = graph_->addNode("convert", MaterialX::EMPTY_STRING, type(to_type));
|
res = create_node("convert", to_type);
|
||||||
res.set_input("in", *this);
|
res.set_input("in", *this);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
@ -448,24 +567,24 @@ NodeItem NodeItem::if_else(CompareOp op,
|
|||||||
|
|
||||||
auto item1 = if_val;
|
auto item1 = if_val;
|
||||||
auto item2 = else_val;
|
auto item2 = else_val;
|
||||||
Type to_type = adjust_types(item1, item2);
|
Type to_type = cast_types(item1, item2);
|
||||||
if (to_type == Type::Empty) {
|
if (to_type == Type::Empty) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::function<bool(float, float)> func = nullptr;
|
std::function<bool(float, float)> func = nullptr;
|
||||||
std::string mx_category;
|
std::string category;
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case CompareOp::Greater:
|
case CompareOp::Greater:
|
||||||
mx_category = "ifgreater";
|
category = "ifgreater";
|
||||||
func = [](float a, float b) { return a > b; };
|
func = [](float a, float b) { return a > b; };
|
||||||
break;
|
break;
|
||||||
case CompareOp::GreaterEq:
|
case CompareOp::GreaterEq:
|
||||||
mx_category = "ifgreatereq";
|
category = "ifgreatereq";
|
||||||
func = [](float a, float b) { return a >= b; };
|
func = [](float a, float b) { return a >= b; };
|
||||||
break;
|
break;
|
||||||
case CompareOp::Eq:
|
case CompareOp::Eq:
|
||||||
mx_category = "ifequal";
|
category = "ifequal";
|
||||||
func = [](float a, float b) { return a == b; };
|
func = [](float a, float b) { return a == b; };
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -476,7 +595,7 @@ NodeItem NodeItem::if_else(CompareOp op,
|
|||||||
res = func(value->asA<float>(), other.value->asA<float>()) ? item1 : item2;
|
res = func(value->asA<float>(), other.value->asA<float>()) ? item1 : item2;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
res.node = graph_->addNode(mx_category, MaterialX::EMPTY_STRING, type(to_type));
|
res = create_node(category, to_type);
|
||||||
res.set_input("value1", *this);
|
res.set_input("value1", *this);
|
||||||
res.set_input("value2", other);
|
res.set_input("value2", other);
|
||||||
res.set_input("in1", item1);
|
res.set_input("in1", item1);
|
||||||
@ -502,127 +621,81 @@ NodeItem::Type NodeItem::type() const
|
|||||||
return Type::Empty;
|
return Type::Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeItem::set_input(const std::string &name,
|
NodeItem NodeItem::create_node(const std::string &category, NodeItem::Type type) const
|
||||||
const NodeItem &item,
|
{
|
||||||
const std::string &output_name)
|
std::string type_str = this->type(type);
|
||||||
|
CLOG_INFO(LOG_MATERIALX_SHADER, 2, "<%s type=%s>", category.c_str(), type_str.c_str());
|
||||||
|
NodeItem res = empty();
|
||||||
|
res.node = graph_->addNode(category, MaterialX::EMPTY_STRING, type_str);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeItem::set_input(const std::string &in_name, const NodeItem &item)
|
||||||
{
|
{
|
||||||
if (item.value) {
|
if (item.value) {
|
||||||
Type item_type = item.type();
|
Type item_type = item.type();
|
||||||
std::string mx_type = type(item_type);
|
|
||||||
switch (item_type) {
|
switch (item_type) {
|
||||||
case Type::String:
|
case Type::String:
|
||||||
set_input(name, item.value->asA<std::string>(), mx_type);
|
set_input(in_name, item.value->asA<std::string>(), item_type);
|
||||||
break;
|
break;
|
||||||
case Type::Bool:
|
case Type::Bool:
|
||||||
set_input(name, item.value->asA<bool>(), mx_type);
|
set_input(in_name, item.value->asA<bool>(), item_type);
|
||||||
break;
|
break;
|
||||||
case Type::Integer:
|
case Type::Integer:
|
||||||
set_input(name, item.value->asA<int>(), mx_type);
|
set_input(in_name, item.value->asA<int>(), item_type);
|
||||||
break;
|
break;
|
||||||
case Type::Float:
|
case Type::Float:
|
||||||
set_input(name, item.value->asA<float>(), mx_type);
|
set_input(in_name, item.value->asA<float>(), item_type);
|
||||||
break;
|
break;
|
||||||
case Type::Vector2:
|
case Type::Vector2:
|
||||||
set_input(name, item.value->asA<MaterialX::Vector2>(), mx_type);
|
set_input(in_name, item.value->asA<MaterialX::Vector2>(), item_type);
|
||||||
break;
|
break;
|
||||||
case Type::Vector3:
|
case Type::Vector3:
|
||||||
set_input(name, item.value->asA<MaterialX::Vector3>(), mx_type);
|
set_input(in_name, item.value->asA<MaterialX::Vector3>(), item_type);
|
||||||
break;
|
break;
|
||||||
case Type::Vector4:
|
case Type::Vector4:
|
||||||
set_input(name, item.value->asA<MaterialX::Vector4>(), mx_type);
|
set_input(in_name, item.value->asA<MaterialX::Vector4>(), item_type);
|
||||||
break;
|
break;
|
||||||
case Type::Color3:
|
case Type::Color3:
|
||||||
set_input(name, item.value->asA<MaterialX::Color3>(), mx_type);
|
set_input(in_name, item.value->asA<MaterialX::Color3>(), item_type);
|
||||||
break;
|
break;
|
||||||
case Type::Color4:
|
case Type::Color4:
|
||||||
set_input(name, item.value->asA<MaterialX::Color4>(), mx_type);
|
set_input(in_name, item.value->asA<MaterialX::Color4>(), item_type);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
BLI_assert_unreachable();
|
BLI_assert_unreachable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (item.node) {
|
else if (item.node) {
|
||||||
node->setConnectedNode(name, item.node);
|
node->setConnectedNode(in_name, item.node);
|
||||||
if (output_name != "") {
|
|
||||||
node->setConnectedOutput(name, item.node->getOutput(output_name));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Empty item to input: %s", name.c_str());
|
CLOG_WARN(LOG_MATERIALX_SHADER, "Empty item to input: %s", in_name.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NodeItem::set_input_output(const std::string &in_name,
|
||||||
|
const NodeItem &item,
|
||||||
|
const std::string &out_name)
|
||||||
|
{
|
||||||
|
if (!item.node) {
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
node->setConnectedNode(in_name, item.node);
|
||||||
|
node->setConnectedOutput(in_name, item.node->getOutput(out_name));
|
||||||
|
}
|
||||||
|
|
||||||
void NodeItem::add_output(const std::string &name, Type out_type)
|
void NodeItem::add_output(const std::string &name, Type out_type)
|
||||||
{
|
{
|
||||||
node->addOutput(name, type(out_type));
|
node->addOutput(name, type(out_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem::Type NodeItem::type(const std::string &type_str)
|
|
||||||
{
|
|
||||||
if (type_str == "string") {
|
|
||||||
return Type::String;
|
|
||||||
}
|
|
||||||
if (type_str == "boolean") {
|
|
||||||
return Type::Bool;
|
|
||||||
}
|
|
||||||
if (type_str == "integer") {
|
|
||||||
return Type::Integer;
|
|
||||||
}
|
|
||||||
if (type_str == "float") {
|
|
||||||
return Type::Float;
|
|
||||||
}
|
|
||||||
if (type_str == "vector2") {
|
|
||||||
return Type::Vector2;
|
|
||||||
}
|
|
||||||
if (type_str == "vector3") {
|
|
||||||
return Type::Vector3;
|
|
||||||
}
|
|
||||||
if (type_str == "vector4") {
|
|
||||||
return Type::Vector4;
|
|
||||||
}
|
|
||||||
if (type_str == "color3") {
|
|
||||||
return Type::Color3;
|
|
||||||
}
|
|
||||||
if (type_str == "color4") {
|
|
||||||
return Type::Color4;
|
|
||||||
}
|
|
||||||
return Type::Other;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string NodeItem::type(Type type)
|
|
||||||
{
|
|
||||||
switch (type) {
|
|
||||||
case Type::String:
|
|
||||||
return "string";
|
|
||||||
case Type::Bool:
|
|
||||||
return "boolean";
|
|
||||||
case Type::Integer:
|
|
||||||
return "integer";
|
|
||||||
case Type::Float:
|
|
||||||
return "float";
|
|
||||||
case Type::Vector2:
|
|
||||||
return "vector2";
|
|
||||||
case Type::Vector3:
|
|
||||||
return "vector3";
|
|
||||||
case Type::Vector4:
|
|
||||||
return "vector4";
|
|
||||||
case Type::Color3:
|
|
||||||
return "color3";
|
|
||||||
case Type::Color4:
|
|
||||||
return "color4";
|
|
||||||
default:
|
|
||||||
BLI_assert_unreachable();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NodeItem::is_arithmetic(Type type)
|
bool NodeItem::is_arithmetic(Type type)
|
||||||
{
|
{
|
||||||
return type >= Type::Float;
|
return type >= Type::Float && type <= Type::Color4;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem::Type NodeItem::adjust_types(NodeItem &item1, NodeItem &item2)
|
NodeItem::Type NodeItem::cast_types(NodeItem &item1, NodeItem &item2)
|
||||||
{
|
{
|
||||||
Type t1 = item1.type();
|
Type t1 = item1.type();
|
||||||
Type t2 = item2.type();
|
Type t2 = item2.type();
|
||||||
@ -630,6 +703,8 @@ NodeItem::Type NodeItem::adjust_types(NodeItem &item1, NodeItem &item2)
|
|||||||
return t1;
|
return t1;
|
||||||
}
|
}
|
||||||
if (!is_arithmetic(t1) || !is_arithmetic(t2)) {
|
if (!is_arithmetic(t1) || !is_arithmetic(t2)) {
|
||||||
|
CLOG_WARN(
|
||||||
|
LOG_MATERIALX_SHADER, "Can't adjust types: %s <-> %s", type(t1).c_str(), type(t2).c_str());
|
||||||
return Type::Empty;
|
return Type::Empty;
|
||||||
}
|
}
|
||||||
if (t1 < t2) {
|
if (t1 < t2) {
|
||||||
@ -697,7 +772,7 @@ NodeItem NodeItem::arithmetic(const std::string &category, std::function<float(f
|
|||||||
else {
|
else {
|
||||||
/* TODO: Some of math functions (sin, cos, ...) doesn't work with Color types,
|
/* TODO: Some of math functions (sin, cos, ...) doesn't work with Color types,
|
||||||
* we have to convert to Vector */
|
* we have to convert to Vector */
|
||||||
res.node = graph_->addNode(category, MaterialX::EMPTY_STRING, this->type(type));
|
res = create_node(category, type);
|
||||||
res.set_input("in", *this);
|
res.set_input("in", *this);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
@ -710,7 +785,7 @@ NodeItem NodeItem::arithmetic(const NodeItem &other,
|
|||||||
NodeItem res = empty();
|
NodeItem res = empty();
|
||||||
NodeItem item1 = *this;
|
NodeItem item1 = *this;
|
||||||
NodeItem item2 = other;
|
NodeItem item2 = other;
|
||||||
Type to_type = adjust_types(item1, item2);
|
Type to_type = cast_types(item1, item2);
|
||||||
if (to_type == Type::Empty) {
|
if (to_type == Type::Empty) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -763,7 +838,7 @@ NodeItem NodeItem::arithmetic(const NodeItem &other,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
res.node = graph_->addNode(category, MaterialX::EMPTY_STRING, type(to_type));
|
res = create_node(category, to_type);
|
||||||
res.set_input("in1", item1);
|
res.set_input("in1", item1);
|
||||||
res.set_input("in2", item2);
|
res.set_input("in2", item2);
|
||||||
}
|
}
|
||||||
|
@ -11,17 +11,29 @@ namespace blender::nodes::materialx {
|
|||||||
class NodeItem {
|
class NodeItem {
|
||||||
public:
|
public:
|
||||||
enum class Type {
|
enum class Type {
|
||||||
Empty = 0,
|
Any = 0,
|
||||||
Other, /* For MaterialX types like: surfaceshader, bsdf, edf, ...*/
|
Empty,
|
||||||
|
|
||||||
|
/* Value types */
|
||||||
String,
|
String,
|
||||||
|
Filename,
|
||||||
Bool,
|
Bool,
|
||||||
BogdanNagirniak marked this conversation as resolved
Outdated
|
|||||||
Integer,
|
Integer,
|
||||||
|
/* Block of arithmetic types. Ordered by type cast */
|
||||||
Float,
|
Float,
|
||||||
Vector2,
|
Vector2,
|
||||||
Vector3,
|
Vector3,
|
||||||
Vector4,
|
|
||||||
Color3,
|
Color3,
|
||||||
Color4
|
Vector4,
|
||||||
|
Color4,
|
||||||
|
/* End of arithmetic types */
|
||||||
|
|
||||||
|
/* Shader types
|
||||||
|
* NOTE: There are only supported types */
|
||||||
|
BSDF,
|
||||||
|
EDF,
|
||||||
|
SurfaceShader,
|
||||||
|
Material,
|
||||||
};
|
};
|
||||||
enum class CompareOp { Less = 0, LessEq, Eq, GreaterEq, Greater, NotEq };
|
enum class CompareOp { Less = 0, LessEq, Eq, GreaterEq, Greater, NotEq };
|
||||||
|
|
||||||
@ -36,6 +48,9 @@ class NodeItem {
|
|||||||
NodeItem(MaterialX::GraphElement *graph);
|
NodeItem(MaterialX::GraphElement *graph);
|
||||||
~NodeItem() = default;
|
~NodeItem() = default;
|
||||||
|
|
||||||
|
static Type type(const std::string &type_str);
|
||||||
|
static std::string type(Type type);
|
||||||
|
|
||||||
/* Operators */
|
/* Operators */
|
||||||
operator bool() const;
|
operator bool() const;
|
||||||
NodeItem operator+(const NodeItem &other) const;
|
NodeItem operator+(const NodeItem &other) const;
|
||||||
@ -48,9 +63,6 @@ class NodeItem {
|
|||||||
bool operator==(const NodeItem &other) const;
|
bool operator==(const NodeItem &other) const;
|
||||||
bool operator!=(const NodeItem &other) const;
|
bool operator!=(const NodeItem &other) const;
|
||||||
|
|
||||||
static Type type(const std::string &type_str);
|
|
||||||
static std::string type(Type type);
|
|
||||||
|
|
||||||
/* Math functions */
|
/* Math functions */
|
||||||
NodeItem abs() const;
|
NodeItem abs() const;
|
||||||
NodeItem floor() const;
|
NodeItem floor() const;
|
||||||
@ -86,18 +98,19 @@ class NodeItem {
|
|||||||
NodeItem empty() const;
|
NodeItem empty() const;
|
||||||
template<class T> NodeItem val(const T &data) const;
|
template<class T> NodeItem val(const T &data) const;
|
||||||
Type type() const;
|
Type type() const;
|
||||||
|
NodeItem create_node(const std::string &category, NodeItem::Type type) const;
|
||||||
|
|
||||||
/* Functions to set input and output */
|
/* Functions to set input and output */
|
||||||
template<class T>
|
template<class T> void set_input(const std::string &in_name, const T &value, Type in_type);
|
||||||
void set_input(const std::string &in_name, const T &value, const std::string &in_type);
|
void set_input(const std::string &in_name, const NodeItem &item);
|
||||||
void set_input(const std::string &in_name,
|
void set_input_output(const std::string &in_name,
|
||||||
const NodeItem &item,
|
const NodeItem &item,
|
||||||
const std::string &out_name = "");
|
const std::string &out_name);
|
||||||
void add_output(const std::string &in_name, Type out_type);
|
void add_output(const std::string &in_name, Type out_type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool is_arithmetic(Type type);
|
static bool is_arithmetic(Type type);
|
||||||
static Type adjust_types(NodeItem &item1, NodeItem &item2);
|
static Type cast_types(NodeItem &item1, NodeItem &item2);
|
||||||
|
|
||||||
bool is_arithmetic() const;
|
bool is_arithmetic() const;
|
||||||
NodeItem arithmetic(const std::string &category, std::function<float(float)> func) const;
|
NodeItem arithmetic(const std::string &category, std::function<float(float)> func) const;
|
||||||
@ -114,9 +127,9 @@ template<class T> NodeItem NodeItem::val(const T &data) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void NodeItem::set_input(const std::string &in_name, const T &value, const std::string &in_type)
|
void NodeItem::set_input(const std::string &in_name, const T &value, Type in_type)
|
||||||
{
|
{
|
||||||
node->setInputValue(in_name, value, in_type);
|
node->setInputValue(in_name, value, type(in_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
} // namespace blender::nodes::materialx
|
||||||
|
@ -22,48 +22,56 @@ NodeParser::NodeParser(MaterialX::GraphElement *graph,
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string NodeParser::node_name(const bNode *node, const bNodeSocket *socket_out)
|
NodeItem NodeParser::compute_full()
|
||||||
{
|
{
|
||||||
return MaterialX::createValidName(node->output_sockets().size() <= 1 ?
|
CLOG_INFO(LOG_MATERIALX_SHADER, 1, "%s [%d]", node_->name, node_->typeinfo->type);
|
||||||
std::string(node->name) :
|
NodeItem res = compute();
|
||||||
std::string(node->name) + "_" + socket_out->name);
|
if (res.node) {
|
||||||
}
|
res.node->setName(node_name());
|
||||||
|
}
|
||||||
NodeItem NodeParser::create_node(const std::string &mx_category, const std::string &mx_type)
|
|
||||||
{
|
|
||||||
NodeItem res = empty();
|
|
||||||
res.node = graph_->addNode(mx_category, MaterialX::EMPTY_STRING, mx_type);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem NodeParser::get_input_default(const std::string &name)
|
std::string NodeParser::node_name()
|
||||||
{
|
{
|
||||||
return get_input_default(node_->input_by_identifier(name));
|
return MaterialX::createValidName(node_->output_sockets().size() <= 1 ?
|
||||||
|
std::string(node_->name) :
|
||||||
|
std::string(node_->name) + "_" + socket_out_->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem NodeParser::get_input_default(int index)
|
NodeItem NodeParser::create_node(const std::string &category, NodeItem::Type type)
|
||||||
{
|
{
|
||||||
return get_input_default(node_->input_socket(index));
|
return empty().create_node(category, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem NodeParser::get_input_link(const std::string &name)
|
NodeItem NodeParser::get_input_default(const std::string &name, NodeItem::Type to_type)
|
||||||
{
|
{
|
||||||
return get_input_link(node_->input_by_identifier(name));
|
return get_input_default(node_->input_by_identifier(name), to_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem NodeParser::get_input_link(int index)
|
NodeItem NodeParser::get_input_default(int index, NodeItem::Type to_type)
|
||||||
{
|
{
|
||||||
return get_input_link(node_->input_socket(index));
|
return get_input_default(node_->input_socket(index), to_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem NodeParser::get_input_value(const std::string &name, const NodeItem::Type type)
|
NodeItem NodeParser::get_input_link(const std::string &name, NodeItem::Type to_type)
|
||||||
{
|
{
|
||||||
return get_input_value(node_->input_by_identifier(name), type);
|
return get_input_link(node_->input_by_identifier(name), to_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem NodeParser::get_input_value(int index, const NodeItem::Type type)
|
NodeItem NodeParser::get_input_link(int index, NodeItem::Type to_type)
|
||||||
{
|
{
|
||||||
return get_input_value(node_->input_socket(index), type);
|
return get_input_link(node_->input_socket(index), to_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeParser::get_input_value(const std::string &name, NodeItem::Type to_type)
|
||||||
|
{
|
||||||
|
return get_input_value(node_->input_by_identifier(name), to_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeParser::get_input_value(int index, NodeItem::Type to_type)
|
||||||
|
{
|
||||||
|
return get_input_value(node_->input_socket(index), to_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem NodeParser::empty() const
|
NodeItem NodeParser::empty() const
|
||||||
@ -71,7 +79,7 @@ NodeItem NodeParser::empty() const
|
|||||||
return NodeItem(graph_);
|
return NodeItem(graph_);
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem NodeParser::get_input_default(const bNodeSocket &socket)
|
NodeItem NodeParser::get_input_default(const bNodeSocket &socket, NodeItem::Type to_type)
|
||||||
{
|
{
|
||||||
NodeItem res = empty();
|
NodeItem res = empty();
|
||||||
switch (socket.type) {
|
switch (socket.type) {
|
||||||
@ -96,10 +104,10 @@ NodeItem NodeParser::get_input_default(const bNodeSocket &socket)
|
|||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unsupported socket type: %d", socket.type);
|
CLOG_WARN(LOG_MATERIALX_SHADER, "Unsupported socket type: %d", socket.type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res;
|
return res.convert(to_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem NodeParser::get_input_link(const bNodeSocket &socket)
|
NodeItem NodeParser::get_input_link(const bNodeSocket &socket, NodeItem::Type to_type)
|
||||||
{
|
{
|
||||||
NodeItem res = empty();
|
NodeItem res = empty();
|
||||||
|
|
||||||
@ -119,22 +127,17 @@ NodeItem NodeParser::get_input_link(const bNodeSocket &socket)
|
|||||||
from_node = link->fromnode;
|
from_node = link->fromnode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Checking if node was already computed */
|
/* Creating required NodeParser object */
|
||||||
res.node = graph_->getNode(node_name(from_node, link->fromsock));
|
std::unique_ptr<NodeParser> parser;
|
||||||
if (res.node) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Computing from_node with required NodeParser object */
|
|
||||||
#define CASE_NODE_TYPE(type, T) \
|
#define CASE_NODE_TYPE(type, T) \
|
||||||
case type: \
|
case type: \
|
||||||
res = T(graph_, depsgraph_, material_, from_node, link->fromsock).compute_full(); \
|
parser = std::make_unique<T>(graph_, depsgraph_, material_, from_node, link->fromsock); \
|
||||||
break;
|
break;
|
||||||
|
|
||||||
switch (from_node->typeinfo->type) {
|
switch (from_node->typeinfo->type) {
|
||||||
CASE_NODE_TYPE(SH_NODE_BLACKBODY, BlackbodyNodeParser)
|
CASE_NODE_TYPE(SH_NODE_BLACKBODY, BlackbodyNodeParser)
|
||||||
CASE_NODE_TYPE(SH_NODE_BRIGHTCONTRAST, BrightContrastNodeParser)
|
CASE_NODE_TYPE(SH_NODE_BRIGHTCONTRAST, BrightContrastNodeParser)
|
||||||
CASE_NODE_TYPE(SH_NODE_BSDF_PRINCIPLED, BSDFPrincipledNodeParser)
|
|
||||||
CASE_NODE_TYPE(SH_NODE_CLAMP, ClampNodeParser)
|
CASE_NODE_TYPE(SH_NODE_CLAMP, ClampNodeParser)
|
||||||
CASE_NODE_TYPE(SH_NODE_COMBINE_COLOR, CombineColorNodeParser)
|
CASE_NODE_TYPE(SH_NODE_COMBINE_COLOR, CombineColorNodeParser)
|
||||||
CASE_NODE_TYPE(SH_NODE_COMBXYZ, CombineXYZNodeParser)
|
CASE_NODE_TYPE(SH_NODE_COMBXYZ, CombineXYZNodeParser)
|
||||||
@ -158,27 +161,137 @@ NodeItem NodeParser::get_input_link(const bNodeSocket &socket)
|
|||||||
from_node->name,
|
from_node->name,
|
||||||
from_node->typeinfo->type);
|
from_node->typeinfo->type);
|
||||||
}
|
}
|
||||||
|
if (!parser) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Checking if node was already computed */
|
||||||
|
res.node = graph_->getNode(parser->node_name());
|
||||||
|
if (res.node) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Computing */
|
||||||
|
res = parser->compute_full();
|
||||||
|
return res.convert(to_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeParser::get_input_value(const bNodeSocket &socket, NodeItem::Type to_type)
|
||||||
|
{
|
||||||
|
NodeItem res = get_input_link(socket, to_type);
|
||||||
|
if (!res) {
|
||||||
|
res = get_input_default(socket, to_type);
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem NodeParser::get_input_value(const bNodeSocket &socket, const NodeItem::Type type)
|
ShaderNodeParser::ShaderNodeParser(MaterialX::GraphElement *graph,
|
||||||
|
const Depsgraph *depsgraph,
|
||||||
|
const Material *material,
|
||||||
|
const bNode *node,
|
||||||
|
const bNodeSocket *socket_out,
|
||||||
|
NodeItem::Type shader_type)
|
||||||
|
: NodeParser(graph, depsgraph, material, node, socket_out), shader_type_(shader_type)
|
||||||
{
|
{
|
||||||
NodeItem res = get_input_link(socket);
|
|
||||||
if (!res) {
|
|
||||||
res = get_input_default(socket);
|
|
||||||
}
|
|
||||||
return type == NodeItem::Type::Empty ? res : res.convert(type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem NodeParser::compute_full()
|
NodeItem ShaderNodeParser::compute_full()
|
||||||
{
|
{
|
||||||
CLOG_INFO(LOG_MATERIALX_SHADER, 1, "%s [%d]", node_->name, node_->typeinfo->type);
|
CLOG_INFO(LOG_MATERIALX_SHADER,
|
||||||
|
1,
|
||||||
|
"%s [%d] - %s",
|
||||||
|
node_->name,
|
||||||
|
node_->typeinfo->type,
|
||||||
|
NodeItem::type(shader_type_).c_str());
|
||||||
NodeItem res = compute();
|
NodeItem res = compute();
|
||||||
if (res.node) {
|
if (res.node) {
|
||||||
res.node->setName(node_name(node_, socket_out_));
|
res.node->setName(node_name());
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string ShaderNodeParser::node_name()
|
||||||
|
{
|
||||||
|
std::string name = NodeParser::node_name();
|
||||||
|
if (shader_type_ != NodeItem::Type::SurfaceShader) {
|
||||||
|
name += "_" + NodeItem::type(shader_type_);
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem ShaderNodeParser::get_input_shader(const std::string &name, NodeItem::Type shader_type)
|
||||||
|
{
|
||||||
|
return get_input_shader(node_->input_by_identifier(name), shader_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem ShaderNodeParser::get_input_shader(int index, NodeItem::Type shader_type)
|
||||||
|
{
|
||||||
|
return get_input_shader(node_->input_socket(index), shader_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem ShaderNodeParser::get_input_shader(const bNodeSocket &socket, NodeItem::Type shader_type)
|
||||||
|
{
|
||||||
|
NodeItem res = empty();
|
||||||
|
|
||||||
|
const bNodeLink *link = socket.link;
|
||||||
|
if (!(link && link->is_used())) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bNode *from_node = link->fromnode;
|
||||||
|
|
||||||
|
/* Passing NODE_REROUTE nodes */
|
||||||
|
while (from_node->type == NODE_REROUTE) {
|
||||||
|
link = from_node->input_socket(0).link;
|
||||||
|
if (!(link && link->is_used())) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
from_node = link->fromnode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Creating required ShaderNodeParser object */
|
||||||
|
std::unique_ptr<ShaderNodeParser> parser;
|
||||||
|
|
||||||
|
#define CASE_SHADER_NODE_TYPE(type, T) \
|
||||||
|
case type: \
|
||||||
|
parser = std::make_unique<T>( \
|
||||||
|
graph_, depsgraph_, material_, from_node, link->fromsock, shader_type); \
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (from_node->typeinfo->type) {
|
||||||
|
CASE_SHADER_NODE_TYPE(SH_NODE_ADD_SHADER, AddShaderNodeParser)
|
||||||
|
CASE_SHADER_NODE_TYPE(SH_NODE_BSDF_DIFFUSE, BSDFDiffuseNodeParser)
|
||||||
|
// CASE_SHADER_NODE_TYPE(SH_NODE_BSDF_GLASS, BSDFGlassNodeParser)
|
||||||
|
// CASE_SHADER_NODE_TYPE(SH_NODE_BSDF_GLOSSY, BSDFGlossyNodeParser)
|
||||||
|
CASE_SHADER_NODE_TYPE(SH_NODE_BSDF_PRINCIPLED, BSDFPrincipledNodeParser)
|
||||||
|
// CASE_SHADER_NODE_TYPE(SH_NODE_BSDF_REFRACTION, BSDFRefractionNodeParser)
|
||||||
|
// CASE_SHADER_NODE_TYPE(SH_NODE_BSDF_SHEEN, BSDFSheenNodeParser)
|
||||||
|
// CASE_SHADER_NODE_TYPE(SH_NODE_BSDF_TOON, BSDFToonNodeParser)
|
||||||
|
// CASE_SHADER_NODE_TYPE(SH_NODE_BSDF_TRANSLUCENT, BSDFTranslucentNodeParser)
|
||||||
|
// CASE_SHADER_NODE_TYPE(SH_NODE_BSDF_TRANSPARENT, BSDFTransparentNodeParser)
|
||||||
|
CASE_SHADER_NODE_TYPE(SH_NODE_EMISSION, EmissionNodeParser)
|
||||||
|
CASE_SHADER_NODE_TYPE(SH_NODE_MIX_SHADER, MixShaderNodeParser)
|
||||||
|
// CASE_SHADER_NODE_TYPE(SH_NODE_SUBSURFACE_SCATTERING, SubsurfaceScatteringNodeParser)
|
||||||
|
|
||||||
|
default:
|
||||||
|
CLOG_WARN(LOG_MATERIALX_SHADER,
|
||||||
|
"Unsupported node: %s [%d]",
|
||||||
|
from_node->name,
|
||||||
|
from_node->typeinfo->type);
|
||||||
|
}
|
||||||
|
if (!parser) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Checking if node was already computed */
|
||||||
|
res.node = graph_->getNode(parser->node_name());
|
||||||
|
if (res.node) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Computing */
|
||||||
|
res = parser->compute_full();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
} // namespace blender::nodes::materialx
|
||||||
|
@ -31,56 +31,96 @@ class NodeParser {
|
|||||||
virtual NodeItem compute() = 0;
|
virtual NodeItem compute() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static std::string node_name(const bNode *node, const bNodeSocket *socket_out);
|
virtual NodeItem compute_full();
|
||||||
NodeItem create_node(const std::string &mx_category, const std::string &mx_type);
|
virtual std::string node_name();
|
||||||
NodeItem get_input_default(const std::string &name);
|
NodeItem create_node(const std::string &category, NodeItem::Type type);
|
||||||
NodeItem get_input_default(int index);
|
NodeItem get_input_default(const std::string &name, NodeItem::Type to_type);
|
||||||
NodeItem get_input_link(const std::string &name);
|
NodeItem get_input_default(int index, NodeItem::Type to_type);
|
||||||
NodeItem get_input_link(int index);
|
NodeItem get_input_link(const std::string &name, NodeItem::Type to_type);
|
||||||
NodeItem get_input_value(const std::string &name,
|
NodeItem get_input_link(int index, NodeItem::Type to_type);
|
||||||
const NodeItem::Type type);
|
NodeItem get_input_value(const std::string &name, NodeItem::Type to_type);
|
||||||
NodeItem get_input_value(int index, const NodeItem::Type type);
|
NodeItem get_input_value(int index, NodeItem::Type to_type);
|
||||||
NodeItem empty() const;
|
NodeItem empty() const;
|
||||||
template<class T> NodeItem value(const T &data) const;
|
template<class T> NodeItem val(const T &data) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NodeItem get_input_default(const bNodeSocket &socket);
|
NodeItem get_input_default(const bNodeSocket &socket, NodeItem::Type to_type);
|
||||||
NodeItem get_input_link(const bNodeSocket &socket);
|
NodeItem get_input_link(const bNodeSocket &socket, NodeItem::Type to_type);
|
||||||
NodeItem get_input_value(const bNodeSocket &socket,
|
NodeItem get_input_value(const bNodeSocket &socket, NodeItem::Type to_type);
|
||||||
const NodeItem::Type type);
|
|
||||||
NodeItem compute_full();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T> NodeItem NodeParser::value(const T &data) const
|
class ShaderNodeParser : public NodeParser {
|
||||||
|
protected:
|
||||||
|
NodeItem::Type shader_type_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ShaderNodeParser(MaterialX::GraphElement *graph,
|
||||||
|
const Depsgraph *depsgraph,
|
||||||
|
const Material *material,
|
||||||
|
const bNode *node,
|
||||||
|
const bNodeSocket *socket_out,
|
||||||
|
NodeItem::Type shader_type);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
NodeItem compute_full() override;
|
||||||
|
std::string node_name() override;
|
||||||
|
NodeItem get_input_shader(const std::string &name, NodeItem::Type shader_type);
|
||||||
|
NodeItem get_input_shader(int index, NodeItem::Type shader_type);
|
||||||
|
|
||||||
|
private:
|
||||||
|
NodeItem get_input_shader(const bNodeSocket &socket, NodeItem::Type shader_type);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T> NodeItem NodeParser::val(const T &data) const
|
||||||
{
|
{
|
||||||
return empty().val(data);
|
return empty().val(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DECLARE_PARSER(T) \
|
#define DECLARE_NODE_PARSER(T) \
|
||||||
class T : public NodeParser { \
|
class T : public NodeParser { \
|
||||||
public: \
|
public: \
|
||||||
using NodeParser::NodeParser; \
|
using NodeParser::NodeParser; \
|
||||||
NodeItem compute() override; \
|
NodeItem compute() override; \
|
||||||
};
|
};
|
||||||
|
|
||||||
DECLARE_PARSER(BlackbodyNodeParser)
|
#define DECLARE_SHADER_NODE_PARSER(T) \
|
||||||
DECLARE_PARSER(BrightContrastNodeParser)
|
class T : public ShaderNodeParser { \
|
||||||
DECLARE_PARSER(BSDFPrincipledNodeParser)
|
public: \
|
||||||
DECLARE_PARSER(ClampNodeParser)
|
using ShaderNodeParser::ShaderNodeParser; \
|
||||||
DECLARE_PARSER(CombineColorNodeParser)
|
NodeItem compute() override; \
|
||||||
DECLARE_PARSER(CombineXYZNodeParser)
|
};
|
||||||
DECLARE_PARSER(HueSatValNodeParser)
|
|
||||||
DECLARE_PARSER(InvertNodeParser)
|
DECLARE_NODE_PARSER(BlackbodyNodeParser)
|
||||||
DECLARE_PARSER(MapRangeNodeParser)
|
DECLARE_NODE_PARSER(BrightContrastNodeParser)
|
||||||
DECLARE_PARSER(MathNodeParser)
|
DECLARE_NODE_PARSER(ClampNodeParser)
|
||||||
DECLARE_PARSER(MixRGBNodeParser)
|
DECLARE_NODE_PARSER(CombineColorNodeParser)
|
||||||
DECLARE_PARSER(NormalMapNodeParser)
|
DECLARE_NODE_PARSER(CombineXYZNodeParser)
|
||||||
DECLARE_PARSER(SeparateColorNodeParser)
|
DECLARE_NODE_PARSER(HueSatValNodeParser)
|
||||||
DECLARE_PARSER(SeparateXYZNodeParser)
|
DECLARE_NODE_PARSER(InvertNodeParser)
|
||||||
DECLARE_PARSER(TexCheckerNodeParser)
|
DECLARE_NODE_PARSER(MapRangeNodeParser)
|
||||||
DECLARE_PARSER(TexEnvironmentNodeParser)
|
DECLARE_NODE_PARSER(MathNodeParser)
|
||||||
DECLARE_PARSER(TexImageNodeParser)
|
DECLARE_NODE_PARSER(MixRGBNodeParser)
|
||||||
DECLARE_PARSER(TexNoiseNodeParser)
|
DECLARE_NODE_PARSER(NormalMapNodeParser)
|
||||||
DECLARE_PARSER(VectorMathNodeParser)
|
DECLARE_NODE_PARSER(SeparateColorNodeParser)
|
||||||
|
DECLARE_NODE_PARSER(SeparateXYZNodeParser)
|
||||||
|
DECLARE_NODE_PARSER(TexCheckerNodeParser)
|
||||||
|
DECLARE_NODE_PARSER(TexEnvironmentNodeParser)
|
||||||
|
DECLARE_NODE_PARSER(TexImageNodeParser)
|
||||||
|
DECLARE_NODE_PARSER(TexNoiseNodeParser)
|
||||||
|
DECLARE_NODE_PARSER(VectorMathNodeParser)
|
||||||
|
|
||||||
|
DECLARE_SHADER_NODE_PARSER(AddShaderNodeParser)
|
||||||
|
DECLARE_SHADER_NODE_PARSER(BSDFDiffuseNodeParser)
|
||||||
|
DECLARE_SHADER_NODE_PARSER(BSDFGlassNodeParser)
|
||||||
|
DECLARE_SHADER_NODE_PARSER(BSDFGlossyNodeParser)
|
||||||
|
DECLARE_SHADER_NODE_PARSER(BSDFPrincipledNodeParser)
|
||||||
|
DECLARE_SHADER_NODE_PARSER(BSDFRefractionNodeParser)
|
||||||
|
DECLARE_SHADER_NODE_PARSER(BSDFSheenNodeParser)
|
||||||
|
DECLARE_SHADER_NODE_PARSER(BSDFToonNodeParser)
|
||||||
|
DECLARE_SHADER_NODE_PARSER(BSDFTranslucentNodeParser)
|
||||||
|
DECLARE_SHADER_NODE_PARSER(BSDFTransparentNodeParser)
|
||||||
|
DECLARE_SHADER_NODE_PARSER(EmissionNodeParser)
|
||||||
|
DECLARE_SHADER_NODE_PARSER(MixShaderNodeParser)
|
||||||
|
DECLARE_SHADER_NODE_PARSER(SubsurfaceScatteringNodeParser)
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
} // namespace blender::nodes::materialx
|
||||||
|
@ -14,19 +14,19 @@ NodeItem NormalMapNodeParser::compute()
|
|||||||
NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
|
NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
|
||||||
NodeItem strength = get_input_value("Strength", NodeItem::Type::Float);
|
NodeItem strength = get_input_value("Strength", NodeItem::Type::Float);
|
||||||
|
|
||||||
NodeItem res = create_node("normalmap", "vector3");
|
NodeItem res = create_node("normalmap", NodeItem::Type::Vector3);
|
||||||
res.set_input("in", color);
|
res.set_input("in", color);
|
||||||
res.set_input("scale", strength);
|
res.set_input("scale", strength);
|
||||||
|
|
||||||
switch (normal_map_node->space) {
|
switch (normal_map_node->space) {
|
||||||
case SHD_SPACE_TANGENT:
|
case SHD_SPACE_TANGENT:
|
||||||
res.set_input("space", value(std::string("tangent")));
|
res.set_input("space", val(std::string("tangent")));
|
||||||
break;
|
break;
|
||||||
case SHD_SPACE_OBJECT:
|
case SHD_SPACE_OBJECT:
|
||||||
res.set_input("space", value(std::string("tangent")));
|
res.set_input("space", val(std::string("tangent")));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
res.set_input("space", value(default_space));
|
res.set_input("space", val(default_space));
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER,
|
CLOG_WARN(LOG_MATERIALX_SHADER,
|
||||||
"Ignoring unsupported Space: %d %s (%d), %s will be used",
|
"Ignoring unsupported Space: %d %s (%d), %s will be used",
|
||||||
normal_map_node->space,
|
normal_map_node->space,
|
||||||
|
@ -9,50 +9,62 @@ OutputMaterialNodeParser::OutputMaterialNodeParser(MaterialX::GraphElement *grap
|
|||||||
const Depsgraph *depsgraph,
|
const Depsgraph *depsgraph,
|
||||||
const Material *material,
|
const Material *material,
|
||||||
const bNode *node)
|
const bNode *node)
|
||||||
: NodeParser(graph, depsgraph, material, node, nullptr)
|
: ShaderNodeParser(graph, depsgraph, material, node, nullptr, NodeItem::Type::Material)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem OutputMaterialNodeParser::compute()
|
NodeItem OutputMaterialNodeParser::compute()
|
||||||
{
|
|
||||||
return empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem OutputMaterialNodeParser::compute(const std::string &socket_name)
|
|
||||||
{
|
{
|
||||||
NodeItem surface = empty();
|
NodeItem surface = empty();
|
||||||
if (node_) {
|
if (node_) {
|
||||||
surface = get_input_link(socket_name);
|
NodeItem bsdf = get_input_shader("Surface", NodeItem::Type::BSDF);
|
||||||
|
NodeItem edf = get_input_shader("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_shader("Surface", NodeItem::Type::SurfaceShader);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
surface = create_node("standard_surface", "surfaceshader");
|
surface = create_node("standard_surface", NodeItem::Type::SurfaceShader);
|
||||||
surface.set_input("base_color", value(MaterialX::Color3(1.0f, 0.0f, 1.0f)));
|
surface.set_input("base_color", val(MaterialX::Color3(1.0f, 0.0f, 1.0f)));
|
||||||
}
|
}
|
||||||
NodeItem res = create_node("surfacematerial", "material");
|
NodeItem res = create_node("surfacematerial", NodeItem::Type::Material);
|
||||||
res.node->setName(node_name(node_, nullptr));
|
|
||||||
res.set_input("surfaceshader", surface);
|
res.set_input("surfaceshader", surface);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem OutputMaterialNodeParser::compute_default()
|
NodeItem OutputMaterialNodeParser::compute_default()
|
||||||
{
|
{
|
||||||
NodeItem surface = create_node("standard_surface", "surfaceshader");
|
NodeItem surface = create_node("standard_surface", NodeItem::Type::SurfaceShader);
|
||||||
surface.set_input("base_color",
|
surface.set_input("base_color",
|
||||||
value(MaterialX::Color3(material_->r, material_->g, material_->b)));
|
val(MaterialX::Color3(material_->r, material_->g, material_->b)));
|
||||||
surface.set_input("diffuse_roughness", value(material_->roughness));
|
surface.set_input("diffuse_roughness", val(material_->roughness));
|
||||||
if (material_->metallic > 0.0f) {
|
if (material_->metallic > 0.0f) {
|
||||||
surface.set_input("metalness", value(material_->metallic));
|
surface.set_input("metalness", val(material_->metallic));
|
||||||
}
|
}
|
||||||
if (material_->spec) {
|
if (material_->spec) {
|
||||||
surface.set_input("specular", value(material_->spec));
|
surface.set_input("specular", val(material_->spec));
|
||||||
surface.set_input("specular_color", value(material_->spec));
|
surface.set_input("specular_color", val(material_->spec));
|
||||||
surface.set_input("specular_roughness", value(material_->roughness));
|
surface.set_input("specular_roughness", val(material_->roughness));
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem res = create_node("surfacematerial", "material");
|
NodeItem res = create_node("surfacematerial", NodeItem::Type::Material);
|
||||||
res.node->setName("Material_Default");
|
res.node->setName("Material_Default");
|
||||||
res.set_input("surfaceshader", surface);
|
res.set_input("surfaceshader", surface);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string OutputMaterialNodeParser::node_name()
|
||||||
|
{
|
||||||
|
return NodeParser::node_name();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
} // namespace blender::nodes::materialx
|
||||||
|
@ -8,15 +8,19 @@
|
|||||||
|
|
||||||
namespace blender::nodes::materialx {
|
namespace blender::nodes::materialx {
|
||||||
|
|
||||||
class OutputMaterialNodeParser : public NodeParser {
|
class OutputMaterialNodeParser : public ShaderNodeParser {
|
||||||
public:
|
public:
|
||||||
OutputMaterialNodeParser(MaterialX::GraphElement *graph,
|
OutputMaterialNodeParser(MaterialX::GraphElement *graph,
|
||||||
const Depsgraph *depsgraph,
|
const Depsgraph *depsgraph,
|
||||||
const Material *material,
|
const Material *material,
|
||||||
const bNode *node);
|
const bNode *node);
|
||||||
NodeItem compute() override;
|
NodeItem compute() override;
|
||||||
NodeItem compute(const std::string &socket_name);
|
|
||||||
|
using ShaderNodeParser::compute_full;
|
||||||
NodeItem compute_default();
|
NodeItem compute_default();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string node_name() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
} // namespace blender::nodes::materialx
|
||||||
|
@ -18,12 +18,12 @@ NodeItem SeparateColorNodeParser::compute()
|
|||||||
case NODE_COMBSEP_COLOR_RGB:
|
case NODE_COMBSEP_COLOR_RGB:
|
||||||
break;
|
break;
|
||||||
case NODE_COMBSEP_COLOR_HSV:
|
case NODE_COMBSEP_COLOR_HSV:
|
||||||
convert = create_node("rgbtohsv", "color3");
|
convert = create_node("rgbtohsv", NodeItem::Type::Color3);
|
||||||
convert.set_input("in", color);
|
convert.set_input("in", color);
|
||||||
break;
|
break;
|
||||||
case NODE_COMBSEP_COLOR_HSL:
|
case NODE_COMBSEP_COLOR_HSL:
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unsupported color model, using HSV instead: %d", mode);
|
CLOG_WARN(LOG_MATERIALX_SHADER, "Unsupported color model, using HSV instead: %d", mode);
|
||||||
convert = create_node("rgbtohsv", "color3");
|
convert = create_node("rgbtohsv", NodeItem::Type::Color3);
|
||||||
convert.set_input("in", color);
|
convert.set_input("in", color);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -44,7 +44,7 @@ NodeItem CombineColorNodeParser::compute()
|
|||||||
NodeItem blue = get_input_value("Blue", NodeItem::Type::Float);
|
NodeItem blue = get_input_value("Blue", NodeItem::Type::Float);
|
||||||
|
|
||||||
NodeItem convert = empty();
|
NodeItem convert = empty();
|
||||||
NodeItem combine = create_node("combine3", "color3");
|
NodeItem combine = create_node("combine3", NodeItem::Type::Color3);
|
||||||
combine.set_input("in1", red);
|
combine.set_input("in1", red);
|
||||||
combine.set_input("in2", green);
|
combine.set_input("in2", green);
|
||||||
combine.set_input("in3", blue);
|
combine.set_input("in3", blue);
|
||||||
@ -53,12 +53,12 @@ NodeItem CombineColorNodeParser::compute()
|
|||||||
case NODE_COMBSEP_COLOR_RGB:
|
case NODE_COMBSEP_COLOR_RGB:
|
||||||
break;
|
break;
|
||||||
case NODE_COMBSEP_COLOR_HSV:
|
case NODE_COMBSEP_COLOR_HSV:
|
||||||
convert = create_node("hsvtorgb", "color3");
|
convert = create_node("hsvtorgb", NodeItem::Type::Color3);
|
||||||
convert.set_input("in", combine);
|
convert.set_input("in", combine);
|
||||||
break;
|
break;
|
||||||
case NODE_COMBSEP_COLOR_HSL:
|
case NODE_COMBSEP_COLOR_HSL:
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unsupported color model, using HSV instead: %d", mode);
|
CLOG_WARN(LOG_MATERIALX_SHADER, "Unsupported color model, using HSV instead: %d", mode);
|
||||||
convert = create_node("hsvtorgb", "color3");
|
convert = create_node("hsvtorgb", NodeItem::Type::Color3);
|
||||||
convert.set_input("in", combine);
|
convert.set_input("in", combine);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -18,7 +18,7 @@ NodeItem CombineXYZNodeParser::compute()
|
|||||||
NodeItem x = get_input_value("X", NodeItem::Type::Float);
|
NodeItem x = get_input_value("X", NodeItem::Type::Float);
|
||||||
NodeItem y = get_input_value("Y", NodeItem::Type::Float);
|
NodeItem y = get_input_value("Y", NodeItem::Type::Float);
|
||||||
NodeItem z = get_input_value("Z", NodeItem::Type::Float);
|
NodeItem z = get_input_value("Z", NodeItem::Type::Float);
|
||||||
NodeItem res = create_node("combine3", "vector3");
|
NodeItem res = create_node("combine3", NodeItem::Type::Vector3);
|
||||||
res.set_input("in1", x);
|
res.set_input("in1", x);
|
||||||
res.set_input("in2", y);
|
res.set_input("in2", y);
|
||||||
res.set_input("in3", z);
|
res.set_input("in3", z);
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
/* 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
|
@ -8,36 +8,21 @@ namespace blender::nodes::materialx {
|
|||||||
|
|
||||||
NodeItem TexCheckerNodeParser::compute()
|
NodeItem TexCheckerNodeParser::compute()
|
||||||
{
|
{
|
||||||
NodeItem vector = get_input_link("Vector");
|
NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector2);
|
||||||
NodeItem color1 = get_input_value("Color1", NodeItem::Type::Color3);
|
NodeItem color1 = get_input_value("Color1", NodeItem::Type::Color3);
|
||||||
NodeItem color2 = get_input_value("Color2", NodeItem::Type::Color3);
|
NodeItem color2 = get_input_value("Color2", NodeItem::Type::Color3);
|
||||||
NodeItem scale = get_input_value("Scale", NodeItem::Type::Float);
|
NodeItem scale = get_input_value("Scale", NodeItem::Type::Float);
|
||||||
|
|
||||||
if (!vector) {
|
if (!vector) {
|
||||||
vector = create_node("texcoord", "vector2");
|
vector = create_node("texcoord", NodeItem::Type::Vector2);
|
||||||
}
|
}
|
||||||
vector = vector * scale;
|
vector = (vector * scale) % val(2.0f);
|
||||||
|
NodeItem mix = (vector.extract(0).floor() + vector.extract(1).floor())
|
||||||
NodeItem separate = create_node("separate2", "multioutput");
|
.if_else(NodeItem::CompareOp::Eq, val(1.0f), val(1.0f), val(0.0f));
|
||||||
separate.set_input("in", vector);
|
NodeItem res = create_node("mix", NodeItem::Type::Color3);
|
||||||
separate.add_output("outx", NodeItem::Type::Float);
|
res.set_input("fg", color1);
|
||||||
separate.add_output("outy", NodeItem::Type::Float);
|
res.set_input("bg", color2);
|
||||||
|
res.set_input("mix", mix);
|
||||||
NodeItem modulo_x = create_node("modulo", "float");
|
|
||||||
modulo_x.set_input("in1", separate, "outx");
|
|
||||||
modulo_x.set_input("in2", value(2.0f));
|
|
||||||
|
|
||||||
NodeItem modulo_y = create_node("modulo", "float");
|
|
||||||
modulo_y.set_input("in1", separate, "outy");
|
|
||||||
modulo_y.set_input("in2", value(2.0f));
|
|
||||||
|
|
||||||
NodeItem ifequal = (modulo_x.floor() + modulo_y.floor())
|
|
||||||
.if_else(NodeItem::CompareOp::Eq, value(1.0f), value(0.0f), value(1.0f));
|
|
||||||
|
|
||||||
NodeItem res = create_node("mix", "color3");
|
|
||||||
res.set_input("bg", color1);
|
|
||||||
res.set_input("fg", color2);
|
|
||||||
res.set_input("mix", ifequal);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,9 +23,9 @@ NodeItem TexEnvironmentNodeParser::compute()
|
|||||||
image_path = io::hydra::cache_or_get_image_file(bmain, scene, image, &tex->iuser);
|
image_path = io::hydra::cache_or_get_image_file(bmain, scene, image, &tex->iuser);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NodeItem texcoord = create_node("texcoord", "vector2");
|
NodeItem texcoord = create_node("texcoord", NodeItem::Type::Vector2);
|
||||||
NodeItem res = create_node("image", "color3");
|
NodeItem res = create_node("image", NodeItem::Type::Color3);
|
||||||
res.set_input("file", image_path, "filename");
|
res.set_input("file", image_path, NodeItem::Type::Filename);
|
||||||
res.set_input("texcoord", texcoord);
|
res.set_input("texcoord", texcoord);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -23,9 +23,9 @@ NodeItem TexImageNodeParser::compute()
|
|||||||
image_path = io::hydra::cache_or_get_image_file(bmain, scene, image, &tex->iuser);
|
image_path = io::hydra::cache_or_get_image_file(bmain, scene, image, &tex->iuser);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NodeItem texcoord = create_node("texcoord", "vector2");
|
NodeItem texcoord = create_node("texcoord", NodeItem::Type::Vector2);
|
||||||
NodeItem res = create_node("image", "color3");
|
NodeItem res = create_node("image", NodeItem::Type::Color3);
|
||||||
res.set_input("file", image_path, "filename");
|
res.set_input("file", image_path, NodeItem::Type::Filename);
|
||||||
res.set_input("texcoord", texcoord);
|
res.set_input("texcoord", texcoord);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -13,13 +13,13 @@ NodeItem TexNoiseNodeParser::compute()
|
|||||||
NodeItem lacunarity = get_input_value("Lacunarity", NodeItem::Type::Float);
|
NodeItem lacunarity = get_input_value("Lacunarity", NodeItem::Type::Float);
|
||||||
|
|
||||||
if (detail.value && detail.type() == NodeItem::Type::Float) {
|
if (detail.value && detail.type() == NodeItem::Type::Float) {
|
||||||
detail = value(int(detail.value->asA<float>()));
|
detail = val(int(detail.value->asA<float>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem position = create_node("position", "vector3");
|
NodeItem position = create_node("position", NodeItem::Type::Vector3);
|
||||||
position = position * scale;
|
position = position * scale;
|
||||||
|
|
||||||
NodeItem res = create_node("fractal3d", "color3");
|
NodeItem res = create_node("fractal3d", NodeItem::Type::Color3);
|
||||||
res.set_input("position", position);
|
res.set_input("position", position);
|
||||||
res.set_input("octaves", detail);
|
res.set_input("octaves", detail);
|
||||||
res.set_input("lacunarity", lacunarity);
|
res.set_input("lacunarity", lacunarity);
|
||||||
|
@ -14,7 +14,7 @@ NodeItem VectorMathNodeParser::compute()
|
|||||||
NodeItem res = empty();
|
NodeItem res = empty();
|
||||||
|
|
||||||
/* Single operand operations */
|
/* Single operand operations */
|
||||||
NodeItem x = get_input_value(0, NodeItem::Type::Empty);
|
NodeItem x = get_input_value(0, NodeItem::Type::Any);
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case NODE_VECTOR_MATH_SINE:
|
case NODE_VECTOR_MATH_SINE:
|
||||||
res = x.sin();
|
res = x.sin();
|
||||||
@ -35,7 +35,7 @@ NodeItem VectorMathNodeParser::compute()
|
|||||||
res = x.ceil();
|
res = x.ceil();
|
||||||
break;
|
break;
|
||||||
case NODE_VECTOR_MATH_FRACTION:
|
case NODE_VECTOR_MATH_FRACTION:
|
||||||
res = x % value(1.0f);
|
res = x % val(1.0f);
|
||||||
break;
|
break;
|
||||||
case NODE_VECTOR_MATH_LENGTH:
|
case NODE_VECTOR_MATH_LENGTH:
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||||
@ -46,7 +46,7 @@ NodeItem VectorMathNodeParser::compute()
|
|||||||
|
|
||||||
default: {
|
default: {
|
||||||
/* 2-operand operations */
|
/* 2-operand operations */
|
||||||
NodeItem y = get_input_value(1, NodeItem::Type::Empty);
|
NodeItem y = get_input_value(1, NodeItem::Type::Any);
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case NODE_VECTOR_MATH_ADD:
|
case NODE_VECTOR_MATH_ADD:
|
||||||
res = x + y;
|
res = x + y;
|
||||||
@ -93,7 +93,7 @@ NodeItem VectorMathNodeParser::compute()
|
|||||||
|
|
||||||
default: {
|
default: {
|
||||||
/* 3-operand operations */
|
/* 3-operand operations */
|
||||||
NodeItem z = get_input_value(2, NodeItem::Type::Empty);
|
NodeItem z = get_input_value(2, NodeItem::Type::Any);
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case NODE_VECTOR_MATH_MULTIPLY_ADD:
|
case NODE_VECTOR_MATH_MULTIPLY_ADD:
|
||||||
res = x * y + z;
|
res = x * y + z;
|
||||||
|
Loading…
Reference in New Issue
Block a user
Maybe rename to Boolean, as we use full names for other types?