forked from blender/blender
Export other channels and parameters from texture nodes #16
@ -10,11 +10,13 @@ namespace blender::nodes::materialx {
|
|||||||
NodeItem MathNodeParser::compute()
|
NodeItem MathNodeParser::compute()
|
||||||
{
|
{
|
||||||
/* TODO: finish some math operations */
|
/* TODO: finish some math operations */
|
||||||
auto op = node_->custom1;
|
NodeMathOperation op = NodeMathOperation(node_->custom1);
|
||||||
NodeItem res = empty();
|
NodeItem res = empty();
|
||||||
|
|
||||||
/* Single operand operations */
|
/* Single operand operations */
|
||||||
NodeItem x = get_input_value(0, NodeItem::Type::Any);
|
NodeItem x = get_input_value(0, NodeItem::Type::Float);
|
||||||
|
/* TODO: Seems we have to use average if Vector or Color are added */
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case NODE_MATH_SINE:
|
case NODE_MATH_SINE:
|
||||||
res = x.sin();
|
res = x.sin();
|
||||||
@ -82,7 +84,7 @@ NodeItem MathNodeParser::compute()
|
|||||||
|
|
||||||
default: {
|
default: {
|
||||||
/* 2-operand operations */
|
/* 2-operand operations */
|
||||||
NodeItem y = get_input_value(1, NodeItem::Type::Any);
|
NodeItem y = get_input_value(1, NodeItem::Type::Float);
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case NODE_MATH_ADD:
|
case NODE_MATH_ADD:
|
||||||
res = x + y;
|
res = x + y;
|
||||||
@ -132,7 +134,7 @@ NodeItem MathNodeParser::compute()
|
|||||||
|
|
||||||
default: {
|
default: {
|
||||||
/* 3-operand operations */
|
/* 3-operand operations */
|
||||||
NodeItem z = get_input_value(2, NodeItem::Type::Any);
|
NodeItem z = get_input_value(2, NodeItem::Type::Float);
|
||||||
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);
|
||||||
|
@ -351,15 +351,6 @@ NodeItem NodeItem::exp() const
|
|||||||
return arithmetic("exp", [](float a) { return std::expf(a); });
|
return arithmetic("exp", [](float a) { return std::expf(a); });
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem NodeItem::extract(const int index) const
|
|
||||||
{
|
|
||||||
NodeItem res = empty();
|
|
||||||
res = create_node("extract", Type::Float);
|
|
||||||
res.set_input("in", *this);
|
|
||||||
res.set_input("index", val(index));
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem NodeItem::convert(Type to_type) const
|
NodeItem NodeItem::convert(Type to_type) const
|
||||||
{
|
{
|
||||||
Type from_type = type();
|
Type from_type = type();
|
||||||
@ -605,6 +596,15 @@ NodeItem NodeItem::if_else(CompareOp op,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::extract(const int index) const
|
||||||
|
{
|
||||||
|
NodeItem res = empty();
|
||||||
|
res = create_node("extract", Type::Float);
|
||||||
|
res.set_input("in", *this);
|
||||||
|
res.set_input("index", val(index));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
NodeItem NodeItem::empty() const
|
NodeItem NodeItem::empty() const
|
||||||
{
|
{
|
||||||
return NodeItem(graph_);
|
return NodeItem(graph_);
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
namespace blender::nodes::materialx {
|
namespace blender::nodes::materialx {
|
||||||
|
|
||||||
|
static const std::string TEXCOORD_NODE_NAME = "node_texcoord";
|
||||||
|
|
||||||
NodeParser::NodeParser(MaterialX::GraphElement *graph,
|
NodeParser::NodeParser(MaterialX::GraphElement *graph,
|
||||||
const Depsgraph *depsgraph,
|
const Depsgraph *depsgraph,
|
||||||
const Material *material,
|
const Material *material,
|
||||||
@ -79,6 +81,17 @@ NodeItem NodeParser::empty() const
|
|||||||
return NodeItem(graph_);
|
return NodeItem(graph_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NodeItem NodeParser::texcoord_node()
|
||||||
|
{
|
||||||
|
NodeItem res = empty();
|
||||||
|
res.node = graph_->getNode(TEXCOORD_NODE_NAME);
|
||||||
|
if (!res.node) {
|
||||||
|
res = create_node("texcoord", NodeItem::Type::Vector2);
|
||||||
|
res.node->setName(TEXCOORD_NODE_NAME);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
NodeItem NodeParser::get_input_default(const bNodeSocket &socket, NodeItem::Type to_type)
|
NodeItem NodeParser::get_input_default(const bNodeSocket &socket, NodeItem::Type to_type)
|
||||||
{
|
{
|
||||||
NodeItem res = empty();
|
NodeItem res = empty();
|
||||||
|
@ -42,6 +42,7 @@ class NodeParser {
|
|||||||
NodeItem get_input_value(int index, NodeItem::Type to_type);
|
NodeItem get_input_value(int index, NodeItem::Type to_type);
|
||||||
NodeItem empty() const;
|
NodeItem empty() const;
|
||||||
template<class T> NodeItem val(const T &data) const;
|
template<class T> NodeItem val(const T &data) const;
|
||||||
|
NodeItem texcoord_node();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NodeItem get_input_default(const bNodeSocket &socket, NodeItem::Type to_type);
|
NodeItem get_input_default(const bNodeSocket &socket, NodeItem::Type to_type);
|
||||||
|
@ -9,21 +9,20 @@ namespace blender::nodes::materialx {
|
|||||||
NodeItem TexCheckerNodeParser::compute()
|
NodeItem TexCheckerNodeParser::compute()
|
||||||
{
|
{
|
||||||
NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector2);
|
NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector2);
|
||||||
NodeItem color1 = get_input_value("Color1", NodeItem::Type::Color3);
|
if (!vector) {
|
||||||
NodeItem color2 = get_input_value("Color2", NodeItem::Type::Color3);
|
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);
|
NodeItem scale = get_input_value("Scale", NodeItem::Type::Float);
|
||||||
|
|
||||||
if (!vector) {
|
|
||||||
vector = create_node("texcoord", NodeItem::Type::Vector2);
|
|
||||||
}
|
|
||||||
vector = (vector * scale) % val(2.0f);
|
vector = (vector * scale) % val(2.0f);
|
||||||
NodeItem mix = (vector.extract(0).floor() + vector.extract(1).floor())
|
return (vector.extract(0).floor() + vector.extract(1).floor())
|
||||||
.if_else(NodeItem::CompareOp::Eq, val(1.0f), val(1.0f), val(0.0f));
|
.if_else(NodeItem::CompareOp::Eq, val(1.0f), value1, value2);
|
||||||
NodeItem res = create_node("mix", NodeItem::Type::Color3);
|
|
||||||
res.set_input("fg", color1);
|
|
||||||
res.set_input("bg", color2);
|
|
||||||
res.set_input("mix", mix);
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
} // namespace blender::nodes::materialx
|
||||||
|
@ -12,21 +12,49 @@ namespace blender::nodes::materialx {
|
|||||||
|
|
||||||
NodeItem TexEnvironmentNodeParser::compute()
|
NodeItem TexEnvironmentNodeParser::compute()
|
||||||
{
|
{
|
||||||
|
NodeItem res = val(MaterialX::Color4(1.0f, 0.0f, 1.0f, 1.0f));
|
||||||
|
|
||||||
Image *image = (Image *)node_->id;
|
Image *image = (Image *)node_->id;
|
||||||
NodeTexEnvironment *tex = static_cast<NodeTexEnvironment *>(node_->storage);
|
if (!image) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeTexEnvironment *tex_env = static_cast<NodeTexEnvironment *>(node_->storage);
|
||||||
Scene *scene = DEG_get_input_scene(depsgraph_);
|
Scene *scene = DEG_get_input_scene(depsgraph_);
|
||||||
Main *bmain = DEG_get_bmain(depsgraph_);
|
Main *bmain = DEG_get_bmain(depsgraph_);
|
||||||
std::string image_path;
|
|
||||||
/* TODO: What if Blender built without Hydra? Also io::hydra::cache_or_get_image_file contains
|
/* 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. */
|
* pretty general code, so could be moved from bf_usd project. */
|
||||||
#ifdef WITH_HYDRA
|
std::string image_path = io::hydra::cache_or_get_image_file(
|
||||||
image_path = io::hydra::cache_or_get_image_file(bmain, scene, image, &tex->iuser);
|
bmain, scene, image, &tex_env->iuser);
|
||||||
#endif
|
|
||||||
|
|
||||||
NodeItem texcoord = create_node("texcoord", NodeItem::Type::Vector2);
|
NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector2);
|
||||||
NodeItem res = create_node("image", NodeItem::Type::Color3);
|
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("file", image_path, NodeItem::Type::Filename);
|
||||||
res.set_input("texcoord", texcoord);
|
res.set_input("texcoord", vector);
|
||||||
|
res.set_input("filtertype", val(filtertype));
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,21 +12,69 @@ namespace blender::nodes::materialx {
|
|||||||
|
|
||||||
NodeItem TexImageNodeParser::compute()
|
NodeItem TexImageNodeParser::compute()
|
||||||
{
|
{
|
||||||
Image *image = (Image *)node_->id;
|
NodeItem res = val(MaterialX::Color4(1.0f, 0.0f, 1.0f, 1.0f));
|
||||||
NodeTexImage *tex = static_cast<NodeTexImage *>(node_->storage);
|
|
||||||
Scene *scene = DEG_get_input_scene(depsgraph_);
|
|
||||||
Main *bmain = DEG_get_bmain(depsgraph_);
|
|
||||||
std::string image_path;
|
|
||||||
/* 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. */
|
|
||||||
#ifdef WITH_HYDRA
|
|
||||||
image_path = io::hydra::cache_or_get_image_file(bmain, scene, image, &tex->iuser);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
NodeItem texcoord = create_node("texcoord", NodeItem::Type::Vector2);
|
Image *image = (Image *)node_->id;
|
||||||
NodeItem res = create_node("image", NodeItem::Type::Color3);
|
if (image) {
|
||||||
res.set_input("file", image_path, NodeItem::Type::Filename);
|
NodeTexImage *tex_image = static_cast<NodeTexImage *>(node_->storage);
|
||||||
res.set_input("texcoord", texcoord);
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user