forked from blender/blender
MaterialX: fix review comments #19
@ -225,6 +225,9 @@ typedef int (*NodeGPUExecFunction)(struct GPUMaterial *mat,
|
|||||||
struct bNodeExecData *execdata,
|
struct bNodeExecData *execdata,
|
||||||
struct GPUNodeStack *in,
|
struct GPUNodeStack *in,
|
||||||
struct GPUNodeStack *out);
|
struct GPUNodeStack *out);
|
||||||
|
typedef void (*NodeMaterialXExecFunction)(void *data,
|
||||||
|
struct bNode *node,
|
||||||
|
struct bNodeSocket *out);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Defines a node type.
|
* \brief Defines a node type.
|
||||||
@ -339,6 +342,8 @@ typedef struct bNodeType {
|
|||||||
NodeExecFunction exec_fn;
|
NodeExecFunction exec_fn;
|
||||||
/* gpu */
|
/* gpu */
|
||||||
NodeGPUExecFunction gpu_fn;
|
NodeGPUExecFunction gpu_fn;
|
||||||
|
/* MaterialX */
|
||||||
|
NodeMaterialXExecFunction materialx_fn;
|
||||||
|
|
||||||
/* Get an instance of this node's compositor operation. Freeing the instance is the
|
/* Get an instance of this node's compositor operation. Freeing the instance is the
|
||||||
* responsibility of the caller. */
|
* responsibility of the caller. */
|
||||||
|
@ -147,44 +147,12 @@ 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/node_item.cc
|
||||||
materialx/nodes/blackbody.cc
|
materialx/node_parser.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_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/emission.cc
|
|
||||||
materialx/nodes/huesatval.cc
|
|
||||||
materialx/nodes/invert.cc
|
|
||||||
materialx/nodes/map_range.cc
|
|
||||||
materialx/nodes/math.cc
|
|
||||||
materialx/nodes/mix_rgb.cc
|
|
||||||
materialx/nodes/mix_shader.cc
|
|
||||||
materialx/nodes/node_item.cc
|
|
||||||
materialx/nodes/node_parser.cc
|
|
||||||
materialx/nodes/normal_map.cc
|
|
||||||
materialx/nodes/output_material.cc
|
|
||||||
materialx/nodes/rgb_to_bw.cc
|
|
||||||
materialx/nodes/sepcomb_color.cc
|
|
||||||
materialx/nodes/sepcomb_xyz.cc
|
|
||||||
materialx/nodes/subsurface_scattering.cc
|
|
||||||
materialx/nodes/tex_checker.cc
|
|
||||||
materialx/nodes/tex_environment.cc
|
|
||||||
materialx/nodes/tex_image.cc
|
|
||||||
materialx/nodes/tex_noise.cc
|
|
||||||
materialx/nodes/vector_math.cc
|
|
||||||
|
|
||||||
materialx/material.h
|
materialx/material.h
|
||||||
materialx/nodes/node_item.h
|
materialx/node_item.h
|
||||||
materialx/nodes/node_parser.h
|
materialx/node_parser.h
|
||||||
materialx/nodes/output_material.h
|
|
||||||
)
|
)
|
||||||
list(APPEND LIB
|
list(APPEND LIB
|
||||||
MaterialXCore
|
MaterialXCore
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
#include "material.h"
|
#include "material.h"
|
||||||
#include "nodes/output_material.h"
|
#include "node_parser.h"
|
||||||
|
|
||||||
#include <MaterialXFormat/XmlIo.h>
|
#include <MaterialXFormat/XmlIo.h>
|
||||||
|
|
||||||
@ -15,7 +15,42 @@
|
|||||||
|
|
||||||
namespace blender::nodes::materialx {
|
namespace blender::nodes::materialx {
|
||||||
|
|
||||||
CLG_LOGREF_DECLARE_GLOBAL(LOG_MATERIALX_SHADER, "materialx.shader");
|
class DefaultMaterialNodeParser : public NodeParser {
|
||||||
|
public:
|
||||||
|
using NodeParser::NodeParser;
|
||||||
|
|
||||||
|
NodeItem compute() override
|
||||||
|
{
|
||||||
|
NodeItem surface = create_node("standard_surface", NodeItem::Type::SurfaceShader);
|
||||||
|
surface.set_input("base_color",
|
||||||
|
val(MaterialX::Color3(material_->r, material_->g, material_->b)));
|
||||||
|
surface.set_input("diffuse_roughness", val(material_->roughness));
|
||||||
|
if (material_->metallic > 0.0f) {
|
||||||
|
surface.set_input("metalness", val(material_->metallic));
|
||||||
|
}
|
||||||
|
if (material_->spec) {
|
||||||
|
surface.set_input("specular", val(material_->spec));
|
||||||
|
surface.set_input("specular_color", val(material_->spec));
|
||||||
|
surface.set_input("specular_roughness", val(material_->roughness));
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem res = create_node("surfacematerial", NodeItem::Type::Material);
|
||||||
|
res.node->setName("Material_Default");
|
||||||
|
res.set_input("surfaceshader", surface);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem compute_error()
|
||||||
|
{
|
||||||
|
NodeItem surface = create_node("standard_surface", NodeItem::Type::SurfaceShader);
|
||||||
|
surface.set_input("base_color", val(MaterialX::Color3(1.0f, 0.0f, 1.0f)));
|
||||||
|
|
||||||
|
NodeItem res = create_node("surfacematerial", NodeItem::Type::Material);
|
||||||
|
res.node->setName("Material_Error");
|
||||||
|
res.set_input("surfaceshader", surface);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, Material *material)
|
MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, Material *material)
|
||||||
{
|
{
|
||||||
@ -25,10 +60,21 @@ MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, Material *mater
|
|||||||
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_full();
|
if (output_node) {
|
||||||
|
NodeParserData data = {
|
||||||
|
doc.get(), depsgraph, material, NodeItem::Type::Material, NodeItem(doc.get())};
|
||||||
|
output_node->typeinfo->materialx_fn(&data, output_node, nullptr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DefaultMaterialNodeParser(
|
||||||
|
doc.get(), depsgraph, material, nullptr, nullptr, NodeItem::Type::Material)
|
||||||
|
.compute_error();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
OutputMaterialNodeParser(doc.get(), depsgraph, material, nullptr).compute_default();
|
DefaultMaterialNodeParser(
|
||||||
|
doc.get(), depsgraph, material, nullptr, nullptr, NodeItem::Type::Material)
|
||||||
|
.compute();
|
||||||
}
|
}
|
||||||
|
|
||||||
CLOG_INFO(LOG_MATERIALX_SHADER,
|
CLOG_INFO(LOG_MATERIALX_SHADER,
|
||||||
|
@ -6,15 +6,11 @@
|
|||||||
|
|
||||||
#include <MaterialXCore/Document.h>
|
#include <MaterialXCore/Document.h>
|
||||||
|
|
||||||
#include "CLG_log.h"
|
|
||||||
|
|
||||||
struct Depsgraph;
|
struct Depsgraph;
|
||||||
struct Material;
|
struct Material;
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
namespace blender::nodes::materialx {
|
||||||
|
|
||||||
extern struct CLG_LogRef *LOG_MATERIALX_SHADER;
|
|
||||||
|
|
||||||
MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, Material *material);
|
MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, Material *material);
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
} // namespace blender::nodes::materialx
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
#include "node_item.h"
|
#include "node_item.h"
|
||||||
#include "../material.h"
|
|
||||||
|
|
||||||
#include "BLI_assert.h"
|
#include "BLI_assert.h"
|
||||||
#include "BLI_utildefines.h"
|
#include "BLI_utildefines.h"
|
||||||
@ -63,6 +62,8 @@ NodeItem::Type NodeItem::type(const std::string &type_str)
|
|||||||
std::string NodeItem::type(Type type)
|
std::string NodeItem::type(Type type)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case Type::Any:
|
||||||
|
return "";
|
||||||
case Type::String:
|
case Type::String:
|
||||||
return "string";
|
return "string";
|
||||||
case Type::Filename:
|
case Type::Filename:
|
@ -53,6 +53,7 @@ class NodeItem {
|
|||||||
|
|
||||||
static Type type(const std::string &type_str);
|
static Type type(const std::string &type_str);
|
||||||
static std::string type(Type type);
|
static std::string type(Type type);
|
||||||
|
static bool is_arithmetic(Type type);
|
||||||
|
|
||||||
/* Operators */
|
/* Operators */
|
||||||
operator bool() const;
|
operator bool() const;
|
||||||
@ -112,7 +113,6 @@ class NodeItem {
|
|||||||
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 Type cast_types(NodeItem &item1, NodeItem &item2);
|
static Type cast_types(NodeItem &item1, NodeItem &item2);
|
||||||
|
|
||||||
bool is_arithmetic() const;
|
bool is_arithmetic() const;
|
188
source/blender/nodes/shader/materialx/node_parser.cc
Normal file
188
source/blender/nodes/shader/materialx/node_parser.cc
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
#include "node_parser.h"
|
||||||
|
|
||||||
|
#include "BKE_node_runtime.hh"
|
||||||
|
|
||||||
|
namespace blender::nodes::materialx {
|
||||||
|
|
||||||
|
static const std::string TEXCOORD_NODE_NAME = "node_texcoord";
|
||||||
|
|
||||||
|
CLG_LOGREF_DECLARE_GLOBAL(LOG_MATERIALX_SHADER, "materialx.shader");
|
||||||
|
|
||||||
|
NodeParser::NodeParser(MaterialX::GraphElement *graph,
|
||||||
|
const Depsgraph *depsgraph,
|
||||||
|
const Material *material,
|
||||||
|
const bNode *node,
|
||||||
|
const bNodeSocket *socket_out,
|
||||||
|
NodeItem::Type to_type)
|
||||||
|
: graph_(graph),
|
||||||
|
depsgraph_(depsgraph),
|
||||||
|
material_(material),
|
||||||
|
node_(node),
|
||||||
|
socket_out_(socket_out),
|
||||||
|
to_type_(to_type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeParser::compute_full()
|
||||||
|
{
|
||||||
|
NodeItem res = empty();
|
||||||
|
|
||||||
|
/* Checking if node was already computed */
|
||||||
|
res.node = graph_->getNode(node_name());
|
||||||
|
if (res.node) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
CLOG_INFO(LOG_MATERIALX_SHADER,
|
||||||
|
1,
|
||||||
|
"%s [%d] => %s",
|
||||||
|
node_->name,
|
||||||
|
node_->typeinfo->type,
|
||||||
|
NodeItem::type(to_type_).c_str());
|
||||||
|
|
||||||
|
res = compute();
|
||||||
|
if (res.node) {
|
||||||
|
res.node->setName(node_name());
|
||||||
|
}
|
||||||
|
if (NodeItem::is_arithmetic(to_type_)) {
|
||||||
|
res = res.convert(to_type_);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string NodeParser::node_name()
|
||||||
|
{
|
||||||
|
std::string name = node_->name;
|
||||||
|
if (node_->output_sockets().size() > 1) {
|
||||||
|
name += std::string("_") + socket_out_->name;
|
||||||
|
}
|
||||||
|
if (ELEM(to_type_, NodeItem::Type::BSDF, NodeItem::Type::EDF)) {
|
||||||
|
name += "_" + NodeItem::type(to_type_);
|
||||||
|
}
|
||||||
|
return MaterialX::createValidName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeParser::create_node(const std::string &category, NodeItem::Type type)
|
||||||
|
{
|
||||||
|
return empty().create_node(category, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeParser::get_input_default(const std::string &name, NodeItem::Type to_type)
|
||||||
|
{
|
||||||
|
return get_input_default(node_->input_by_identifier(name), to_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeParser::get_input_default(int index, NodeItem::Type to_type)
|
||||||
|
{
|
||||||
|
return get_input_default(node_->input_socket(index), to_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeParser::get_input_link(const std::string &name, NodeItem::Type to_type)
|
||||||
|
{
|
||||||
|
return get_input_link(node_->input_by_identifier(name), to_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeParser::get_input_link(int index, NodeItem::Type to_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
|
||||||
|
{
|
||||||
|
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 res = empty();
|
||||||
|
switch (socket.type) {
|
||||||
|
case SOCK_FLOAT: {
|
||||||
|
float v = socket.default_value_typed<bNodeSocketValueFloat>()->value;
|
||||||
|
res.value = MaterialX::Value::createValue<float>(v);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SOCK_VECTOR: {
|
||||||
|
const float *v = socket.default_value_typed<bNodeSocketValueVector>()->value;
|
||||||
|
res.value = MaterialX::Value::createValue<MaterialX::Vector3>(
|
||||||
|
MaterialX::Vector3(v[0], v[1], v[2]));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SOCK_RGBA: {
|
||||||
|
const float *v = socket.default_value_typed<bNodeSocketValueRGBA>()->value;
|
||||||
|
res.value = MaterialX::Value::createValue<MaterialX::Color4>(
|
||||||
|
MaterialX::Color4(v[0], v[1], v[2], v[3]));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
CLOG_WARN(LOG_MATERIALX_SHADER, "Unsupported socket type: %d", socket.type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res.convert(to_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeParser::get_input_link(const bNodeSocket &socket, NodeItem::Type to_type)
|
||||||
|
{
|
||||||
|
const bNodeLink *link = socket.link;
|
||||||
|
if (!(link && link->is_used())) {
|
||||||
|
return empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
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 empty();
|
||||||
|
}
|
||||||
|
from_node = link->fromnode;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!from_node->typeinfo->materialx_fn) {
|
||||||
|
CLOG_WARN(LOG_MATERIALX_SHADER,
|
||||||
|
"Unsupported node: %s [%d]",
|
||||||
|
from_node->name,
|
||||||
|
from_node->typeinfo->type);
|
||||||
|
return empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeParserData data = {graph_, depsgraph_, material_, to_type, empty()};
|
||||||
|
from_node->typeinfo->materialx_fn(&data, const_cast<bNode *>(from_node), link->fromsock);
|
||||||
|
return data.result;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace blender::nodes::materialx
|
96
source/blender/nodes/shader/materialx/node_parser.h
Normal file
96
source/blender/nodes/shader/materialx/node_parser.h
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "node_item.h"
|
||||||
|
|
||||||
|
#include "DEG_depsgraph.h"
|
||||||
|
#include "DNA_material_types.h"
|
||||||
|
#include "DNA_node_types.h"
|
||||||
|
|
||||||
|
#include "CLG_log.h"
|
||||||
|
|
||||||
|
namespace blender::nodes::materialx {
|
||||||
|
|
||||||
|
extern struct CLG_LogRef *LOG_MATERIALX_SHADER;
|
||||||
|
|
||||||
|
class NodeParser {
|
||||||
|
protected:
|
||||||
|
MaterialX::GraphElement *graph_;
|
||||||
|
const Depsgraph *depsgraph_;
|
||||||
|
const Material *material_;
|
||||||
|
const bNode *node_;
|
||||||
|
const bNodeSocket *socket_out_;
|
||||||
|
NodeItem::Type to_type_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
NodeParser(MaterialX::GraphElement *graph,
|
||||||
|
const Depsgraph *depsgraph,
|
||||||
|
const Material *material,
|
||||||
|
const bNode *node,
|
||||||
|
const bNodeSocket *socket_out,
|
||||||
|
NodeItem::Type to_type);
|
||||||
|
virtual ~NodeParser() = default;
|
||||||
|
|
||||||
|
virtual NodeItem compute() = 0;
|
||||||
|
virtual NodeItem compute_full();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string node_name();
|
||||||
|
NodeItem create_node(const std::string &category, NodeItem::Type type);
|
||||||
|
NodeItem get_input_default(const std::string &name, NodeItem::Type to_type);
|
||||||
|
NodeItem get_input_default(int index, NodeItem::Type to_type);
|
||||||
|
NodeItem get_input_link(const std::string &name, NodeItem::Type to_type);
|
||||||
|
NodeItem get_input_link(int index, NodeItem::Type to_type);
|
||||||
|
NodeItem get_input_value(const std::string &name, NodeItem::Type to_type);
|
||||||
|
NodeItem get_input_value(int index, NodeItem::Type to_type);
|
||||||
|
NodeItem empty() const;
|
||||||
|
template<class T> NodeItem val(const T &data) const;
|
||||||
|
NodeItem texcoord_node();
|
||||||
|
|
||||||
|
private:
|
||||||
|
NodeItem get_input_default(const bNodeSocket &socket, NodeItem::Type to_type);
|
||||||
|
NodeItem get_input_link(const bNodeSocket &socket, NodeItem::Type to_type);
|
||||||
|
NodeItem get_input_value(const bNodeSocket &socket, NodeItem::Type to_type);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T> NodeItem NodeParser::val(const T &data) const
|
||||||
|
{
|
||||||
|
return empty().val(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defines for including MaterialX node parsing code into node_shader_<name>.cc
|
||||||
|
*/
|
||||||
|
struct NodeParserData {
|
||||||
|
MaterialX::GraphElement *graph;
|
||||||
|
const Depsgraph *depsgraph;
|
||||||
|
const Material *material;
|
||||||
|
NodeItem::Type to_type;
|
||||||
|
NodeItem result;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NODE_SHADER_MATERIALX_BEGIN \
|
||||||
|
class MaterialXNodeParser : public materialx::NodeParser { \
|
||||||
|
public: \
|
||||||
|
using materialx::NodeParser::NodeParser; \
|
||||||
|
materialx::NodeItem compute() override; \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
materialx::NodeItem MaterialXNodeParser::compute() \
|
||||||
|
{ \
|
||||||
|
using NodeItem = materialx::NodeItem;
|
||||||
|
|
||||||
|
#define NODE_SHADER_MATERIALX_END \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
void node_shader_materialx(void *data, struct bNode *node, struct bNodeSocket *out) \
|
||||||
|
{ \
|
||||||
|
materialx::NodeParserData *d = reinterpret_cast<materialx::NodeParserData *>(data); \
|
||||||
|
d->result = MaterialXNodeParser(d->graph, d->depsgraph, d->material, node, out, d->to_type) \
|
||||||
|
.compute_full(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace blender::nodes::materialx
|
@ -1,42 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem AddShaderNodeParser::compute()
|
|
||||||
{
|
|
||||||
NodeItem res = empty();
|
|
||||||
switch (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
|
|
@ -1,22 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem BlackbodyNodeParser::compute()
|
|
||||||
{
|
|
||||||
/* This node doesn't have an implementation in MaterialX 1.38.6.
|
|
||||||
* It's added in MaterialX 1.38.8. Uncomment this code after switching to 1.38.8.
|
|
||||||
*
|
|
||||||
* NodeItem temperature = get_input_value("Temperature", NodeItem::Type::Float);
|
|
||||||
|
|
||||||
* NodeItem res = create_node("blackbody", NodeItem::Type::Color3);
|
|
||||||
* res.set_input("temperature", temperature);
|
|
||||||
* return res; */
|
|
||||||
return empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -1,19 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem BrightContrastNodeParser::compute()
|
|
||||||
{
|
|
||||||
NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
|
|
||||||
NodeItem bright = get_input_value("Bright", NodeItem::Type::Float);
|
|
||||||
NodeItem contrast = get_input_value("Contrast", NodeItem::Type::Float);
|
|
||||||
|
|
||||||
/* This formula was given from OSL shader code in Cycles. */
|
|
||||||
return (bright + color * (contrast + val(1.0f)) - contrast * val(0.5f)).max(val(0.0f));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -1,28 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem BSDFDiffuseNodeParser::compute()
|
|
||||||
{
|
|
||||||
if (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
|
|
@ -1,15 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem BSDFGlassNodeParser::compute()
|
|
||||||
{
|
|
||||||
/* TODO: implement */
|
|
||||||
return empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -1,15 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem BSDFGlossyNodeParser::compute()
|
|
||||||
{
|
|
||||||
/* TODO: implement */
|
|
||||||
return empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -1,101 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem BSDFPrincipledNodeParser::compute()
|
|
||||||
{
|
|
||||||
if (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 subsurface = get_input_value("Subsurface", NodeItem::Type::Float);
|
|
||||||
NodeItem subsurface_radius = get_input_value("Subsurface Radius", NodeItem::Type::Color3);
|
|
||||||
NodeItem subsurface_color = get_input_value("Subsurface Color", NodeItem::Type::Color3);
|
|
||||||
|
|
||||||
NodeItem metallic = get_input_value("Metallic", NodeItem::Type::Float);
|
|
||||||
NodeItem specular = get_input_value("Specular", NodeItem::Type::Float);
|
|
||||||
// NodeItem specular_tint = get_input_value("Specular Tint");
|
|
||||||
NodeItem roughness = get_input_value("Roughness", NodeItem::Type::Float);
|
|
||||||
|
|
||||||
/* TODO: use Specular Tint input */
|
|
||||||
NodeItem anisotropic = get_input_value("Anisotropic", NodeItem::Type::Float);
|
|
||||||
NodeItem anisotropic_rotation = get_input_value("Anisotropic Rotation", NodeItem::Type::Float);
|
|
||||||
// anisotropic_rotation = 0.5 - (anisotropic_rotation % 1.0)
|
|
||||||
|
|
||||||
NodeItem sheen = get_input_value("Sheen", NodeItem::Type::Float);
|
|
||||||
// sheen_tint = get_input_value("Sheen Tint");
|
|
||||||
|
|
||||||
NodeItem clearcoat = get_input_value("Clearcoat", NodeItem::Type::Float);
|
|
||||||
NodeItem clearcoat_roughness = get_input_value("Clearcoat Roughness", NodeItem::Type::Float);
|
|
||||||
|
|
||||||
NodeItem ior = get_input_value("IOR", NodeItem::Type::Float);
|
|
||||||
|
|
||||||
NodeItem transmission = get_input_value("Transmission", NodeItem::Type::Float);
|
|
||||||
|
|
||||||
NodeItem emission = get_input_value("Emission", NodeItem::Type::Color3);
|
|
||||||
NodeItem emission_strength = get_input_value("Emission Strength", NodeItem::Type::Float);
|
|
||||||
|
|
||||||
NodeItem alpha = get_input_value("Alpha", NodeItem::Type::Float);
|
|
||||||
// transparency = 1.0 - alpha
|
|
||||||
|
|
||||||
NodeItem normal = get_input_link("Normal", NodeItem::Type::Vector3);
|
|
||||||
NodeItem clearcoat_normal = get_input_link("Clearcoat Normal", NodeItem::Type::Vector3);
|
|
||||||
NodeItem tangent = get_input_link("Tangent", NodeItem::Type::Vector3);
|
|
||||||
|
|
||||||
/* Creating standard_surface */
|
|
||||||
NodeItem res = create_node("standard_surface", NodeItem::Type::SurfaceShader);
|
|
||||||
res.set_input("base", val(1.0f));
|
|
||||||
res.set_input("base_color", base_color);
|
|
||||||
res.set_input("diffuse_roughness", roughness);
|
|
||||||
if (normal) {
|
|
||||||
res.set_input("normal", normal);
|
|
||||||
}
|
|
||||||
if (tangent) {
|
|
||||||
res.set_input("tangent", tangent);
|
|
||||||
}
|
|
||||||
res.set_input("metalness", metallic);
|
|
||||||
|
|
||||||
res.set_input("specular", specular);
|
|
||||||
res.set_input("specular_color", base_color);
|
|
||||||
res.set_input("specular_roughness", roughness);
|
|
||||||
res.set_input("specular_IOR", ior);
|
|
||||||
res.set_input("specular_anisotropy", anisotropic);
|
|
||||||
res.set_input("specular_rotation", anisotropic_rotation);
|
|
||||||
|
|
||||||
res.set_input("transmission", transmission);
|
|
||||||
res.set_input("transmission_color", base_color);
|
|
||||||
res.set_input("transmission_extra_roughness", roughness);
|
|
||||||
|
|
||||||
res.set_input("subsurface", subsurface);
|
|
||||||
res.set_input("subsurface_color", subsurface_color);
|
|
||||||
res.set_input("subsurface_radius", subsurface_radius);
|
|
||||||
res.set_input("subsurface_anisotropy", anisotropic);
|
|
||||||
|
|
||||||
res.set_input("sheen", sheen);
|
|
||||||
res.set_input("sheen_color", base_color);
|
|
||||||
res.set_input("sheen_roughness", roughness);
|
|
||||||
|
|
||||||
res.set_input("coat", clearcoat);
|
|
||||||
res.set_input("coat_color", base_color);
|
|
||||||
res.set_input("coat_roughness", clearcoat_roughness);
|
|
||||||
res.set_input("coat_IOR", ior);
|
|
||||||
res.set_input("coat_anisotropy", anisotropic);
|
|
||||||
res.set_input("coat_rotation", anisotropic_rotation);
|
|
||||||
if (clearcoat_normal) {
|
|
||||||
res.set_input("coat_normal", clearcoat_normal);
|
|
||||||
}
|
|
||||||
|
|
||||||
res.set_input("emission", emission_strength);
|
|
||||||
res.set_input("emission_color", emission);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -1,15 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem BSDFRefractionNodeParser::compute()
|
|
||||||
{
|
|
||||||
/* TODO: implement */
|
|
||||||
return empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -1,15 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem BSDFSheenNodeParser::compute()
|
|
||||||
{
|
|
||||||
/* TODO: implement */
|
|
||||||
return empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -1,15 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem BSDFToonNodeParser::compute()
|
|
||||||
{
|
|
||||||
/* TODO: implement */
|
|
||||||
return empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -1,15 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem BSDFTranslucentNodeParser::compute()
|
|
||||||
{
|
|
||||||
/* TODO: implement */
|
|
||||||
return empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -1,15 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem BSDFTransparentNodeParser::compute()
|
|
||||||
{
|
|
||||||
/* TODO: implement */
|
|
||||||
return empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -1,27 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem ClampNodeParser::compute()
|
|
||||||
{
|
|
||||||
auto type = node_->custom1;
|
|
||||||
NodeItem value = get_input_value("Value", NodeItem::Type::Float);
|
|
||||||
NodeItem min = get_input_value("Min", NodeItem::Type::Float);
|
|
||||||
NodeItem max = get_input_value("Max", NodeItem::Type::Float);
|
|
||||||
|
|
||||||
NodeItem res = empty();
|
|
||||||
if (type == NODE_CLAMP_RANGE) {
|
|
||||||
res = min.if_else(
|
|
||||||
NodeItem::CompareOp::Less, max, value.clamp(min, max), value.clamp(max, min));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
res = value.clamp(min, max);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -1,23 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem EmissionNodeParser::compute()
|
|
||||||
{
|
|
||||||
if (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
|
|
@ -1,33 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem HueSatValNodeParser::compute()
|
|
||||||
{
|
|
||||||
/* TODO: implement fac, see do_hue_sat_fac in
|
|
||||||
* source\blender\nodes\texture\nodes\node_texture_hueSatVal.cc */
|
|
||||||
NodeItem hue = get_input_value("Hue", NodeItem::Type::Float);
|
|
||||||
NodeItem saturation = get_input_value("Saturation", NodeItem::Type::Float);
|
|
||||||
NodeItem value = get_input_value("Value", NodeItem::Type::Float);
|
|
||||||
NodeItem fac = get_input_value("Fac", NodeItem::Type::Float);
|
|
||||||
NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
|
|
||||||
|
|
||||||
/* Modifier to follow Cycles result */
|
|
||||||
hue = hue - val(0.5f);
|
|
||||||
|
|
||||||
NodeItem combine = create_node("combine3", NodeItem::Type::Vector3);
|
|
||||||
combine.set_input("in1", hue);
|
|
||||||
combine.set_input("in2", saturation);
|
|
||||||
combine.set_input("in3", value);
|
|
||||||
|
|
||||||
NodeItem res = create_node("hsvadjust", NodeItem::Type::Color3);
|
|
||||||
res.set_input("in", color);
|
|
||||||
res.set_input("amount", combine);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -1,16 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem InvertNodeParser::compute()
|
|
||||||
{
|
|
||||||
NodeItem fac = get_input_value("Fac", NodeItem::Type::Float);
|
|
||||||
NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
|
|
||||||
return fac.blend(color, fac.val(1.0f) - color);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -1,51 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem MapRangeNodeParser::compute()
|
|
||||||
{
|
|
||||||
/* Interpolation isn't supported by MaterialX. */
|
|
||||||
const NodeMapRange *map_range = static_cast<NodeMapRange *>(node_->storage);
|
|
||||||
|
|
||||||
NodeItem::Type type;
|
|
||||||
NodeItem value = empty();
|
|
||||||
NodeItem from_min = empty();
|
|
||||||
NodeItem from_max = empty();
|
|
||||||
NodeItem to_min = empty();
|
|
||||||
NodeItem to_max = empty();
|
|
||||||
switch (map_range->data_type) {
|
|
||||||
case CD_PROP_FLOAT:
|
|
||||||
type = NodeItem::Type::Float;
|
|
||||||
value = get_input_value("Value", type);
|
|
||||||
from_min = get_input_value(1, type);
|
|
||||||
from_max = get_input_value(2, type);
|
|
||||||
to_min = get_input_value(3, type);
|
|
||||||
to_max = get_input_value(4, type);
|
|
||||||
break;
|
|
||||||
case CD_PROP_FLOAT3:
|
|
||||||
type = NodeItem::Type::Vector3;
|
|
||||||
value = get_input_value("Vector", type);
|
|
||||||
from_min = get_input_value(7, type);
|
|
||||||
from_max = get_input_value(8, type);
|
|
||||||
to_min = get_input_value(9, type);
|
|
||||||
to_max = get_input_value(10, type);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
BLI_assert_unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem res = create_node("range", type);
|
|
||||||
res.set_input("in", value);
|
|
||||||
res.set_input("inlow", from_min);
|
|
||||||
res.set_input("inhigh", from_max);
|
|
||||||
res.set_input("outlow", to_min);
|
|
||||||
res.set_input("outhigh", to_max);
|
|
||||||
res.set_input("doclamp", val(bool(map_range->clamp)));
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -1,171 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "../material.h"
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem MathNodeParser::compute()
|
|
||||||
{
|
|
||||||
/* TODO: finish some math operations */
|
|
||||||
NodeMathOperation op = NodeMathOperation(node_->custom1);
|
|
||||||
NodeItem res = empty();
|
|
||||||
|
|
||||||
/* Single operand operations */
|
|
||||||
NodeItem x = get_input_value(0, NodeItem::Type::Float);
|
|
||||||
/* TODO: Seems we have to use average if Vector or Color are added */
|
|
||||||
|
|
||||||
switch (op) {
|
|
||||||
case NODE_MATH_SINE:
|
|
||||||
res = x.sin();
|
|
||||||
break;
|
|
||||||
case NODE_MATH_COSINE:
|
|
||||||
res = x.cos();
|
|
||||||
break;
|
|
||||||
case NODE_MATH_TANGENT:
|
|
||||||
res = x.tan();
|
|
||||||
break;
|
|
||||||
case NODE_MATH_ARCSINE:
|
|
||||||
res = x.asin();
|
|
||||||
break;
|
|
||||||
case NODE_MATH_ARCCOSINE:
|
|
||||||
res = x.acos();
|
|
||||||
break;
|
|
||||||
case NODE_MATH_ARCTANGENT:
|
|
||||||
res = x.atan();
|
|
||||||
break;
|
|
||||||
case NODE_MATH_ROUND:
|
|
||||||
res = (x + val(0.5f)).floor();
|
|
||||||
break;
|
|
||||||
case NODE_MATH_ABSOLUTE:
|
|
||||||
res = x.abs();
|
|
||||||
break;
|
|
||||||
case NODE_MATH_FLOOR:
|
|
||||||
res = x.floor();
|
|
||||||
break;
|
|
||||||
case NODE_MATH_CEIL:
|
|
||||||
res = x.ceil();
|
|
||||||
break;
|
|
||||||
case NODE_MATH_FRACTION:
|
|
||||||
res = x % val(1.0f);
|
|
||||||
break;
|
|
||||||
case NODE_MATH_SQRT:
|
|
||||||
res = x.sqrt();
|
|
||||||
break;
|
|
||||||
case NODE_MATH_INV_SQRT:
|
|
||||||
res = val(1.0f) / x.sqrt();
|
|
||||||
break;
|
|
||||||
case NODE_MATH_SIGN:
|
|
||||||
res = x.sign();
|
|
||||||
break;
|
|
||||||
case NODE_MATH_EXPONENT:
|
|
||||||
res = x.exp();
|
|
||||||
break;
|
|
||||||
case NODE_MATH_RADIANS:
|
|
||||||
res = x * val(float(M_PI) / 180.0f);
|
|
||||||
break;
|
|
||||||
case NODE_MATH_DEGREES:
|
|
||||||
res = x * val(180.0f * float(M_1_PI));
|
|
||||||
break;
|
|
||||||
case NODE_MATH_SINH:
|
|
||||||
res = x.sinh();
|
|
||||||
break;
|
|
||||||
case NODE_MATH_COSH:
|
|
||||||
res = x.cosh();
|
|
||||||
break;
|
|
||||||
case NODE_MATH_TANH:
|
|
||||||
res = x.tanh();
|
|
||||||
break;
|
|
||||||
case NODE_MATH_TRUNC:
|
|
||||||
res = x.sign() * x.abs().floor();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: {
|
|
||||||
/* 2-operand operations */
|
|
||||||
NodeItem y = get_input_value(1, NodeItem::Type::Float);
|
|
||||||
switch (op) {
|
|
||||||
case NODE_MATH_ADD:
|
|
||||||
res = x + y;
|
|
||||||
break;
|
|
||||||
case NODE_MATH_SUBTRACT:
|
|
||||||
res = x - y;
|
|
||||||
break;
|
|
||||||
case NODE_MATH_MULTIPLY:
|
|
||||||
res = x * y;
|
|
||||||
break;
|
|
||||||
case NODE_MATH_DIVIDE:
|
|
||||||
res = x / y;
|
|
||||||
break;
|
|
||||||
case NODE_MATH_POWER:
|
|
||||||
res = x ^ y;
|
|
||||||
break;
|
|
||||||
case NODE_MATH_LOGARITHM:
|
|
||||||
res = x.ln() / y.ln();
|
|
||||||
break;
|
|
||||||
case NODE_MATH_MINIMUM:
|
|
||||||
res = x.min(y);
|
|
||||||
break;
|
|
||||||
case NODE_MATH_MAXIMUM:
|
|
||||||
res = x.max(y);
|
|
||||||
break;
|
|
||||||
case NODE_MATH_LESS_THAN:
|
|
||||||
res = x.if_else(NodeItem::CompareOp::Less, y, val(1.0f), val(0.0f));
|
|
||||||
break;
|
|
||||||
case NODE_MATH_GREATER_THAN:
|
|
||||||
res = x.if_else(NodeItem::CompareOp::Greater, y, val(1.0f), val(0.0f));
|
|
||||||
break;
|
|
||||||
case NODE_MATH_MODULO:
|
|
||||||
res = x % y;
|
|
||||||
break;
|
|
||||||
case NODE_MATH_ARCTAN2:
|
|
||||||
res = x.atan2(y);
|
|
||||||
break;
|
|
||||||
case NODE_MATH_SNAP:
|
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
|
||||||
break;
|
|
||||||
case NODE_MATH_PINGPONG:
|
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
|
||||||
break;
|
|
||||||
case NODE_MATH_FLOORED_MODULO:
|
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: {
|
|
||||||
/* 3-operand operations */
|
|
||||||
NodeItem z = get_input_value(2, NodeItem::Type::Float);
|
|
||||||
switch (op) {
|
|
||||||
case NODE_MATH_WRAP:
|
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
|
||||||
break;
|
|
||||||
case NODE_MATH_COMPARE:
|
|
||||||
res = z.if_else(NodeItem::CompareOp::Less, (x - y).abs(), val(1.0f), val(0.0f));
|
|
||||||
break;
|
|
||||||
case NODE_MATH_MULTIPLY_ADD:
|
|
||||||
res = x * y + z;
|
|
||||||
break;
|
|
||||||
case NODE_MATH_SMOOTH_MIN:
|
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
|
||||||
break;
|
|
||||||
case NODE_MATH_SMOOTH_MAX:
|
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
BLI_assert_unreachable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool clamp_output = node_->custom2 != 0;
|
|
||||||
if (clamp_output && res) {
|
|
||||||
res = res.clamp();
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -1,15 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem MixRGBNodeParser::compute()
|
|
||||||
{
|
|
||||||
/* TODO: implement */
|
|
||||||
return empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -1,46 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem MixShaderNodeParser::compute()
|
|
||||||
{
|
|
||||||
NodeItem res = empty();
|
|
||||||
switch (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
|
|
@ -1,311 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
#include "../material.h"
|
|
||||||
|
|
||||||
#include "BKE_node_runtime.hh"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
static const std::string TEXCOORD_NODE_NAME = "node_texcoord";
|
|
||||||
|
|
||||||
NodeParser::NodeParser(MaterialX::GraphElement *graph,
|
|
||||||
const Depsgraph *depsgraph,
|
|
||||||
const Material *material,
|
|
||||||
const bNode *node,
|
|
||||||
const bNodeSocket *socket_out)
|
|
||||||
: graph_(graph),
|
|
||||||
depsgraph_(depsgraph),
|
|
||||||
material_(material),
|
|
||||||
node_(node),
|
|
||||||
socket_out_(socket_out)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem NodeParser::compute_full()
|
|
||||||
{
|
|
||||||
CLOG_INFO(LOG_MATERIALX_SHADER, 1, "%s [%d]", node_->name, node_->typeinfo->type);
|
|
||||||
NodeItem res = compute();
|
|
||||||
if (res.node) {
|
|
||||||
res.node->setName(node_name());
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string NodeParser::node_name()
|
|
||||||
{
|
|
||||||
return MaterialX::createValidName(node_->output_sockets().size() <= 1 ?
|
|
||||||
std::string(node_->name) :
|
|
||||||
std::string(node_->name) + "_" + socket_out_->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem NodeParser::create_node(const std::string &category, NodeItem::Type type)
|
|
||||||
{
|
|
||||||
return empty().create_node(category, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem NodeParser::get_input_default(const std::string &name, NodeItem::Type to_type)
|
|
||||||
{
|
|
||||||
return get_input_default(node_->input_by_identifier(name), to_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem NodeParser::get_input_default(int index, NodeItem::Type to_type)
|
|
||||||
{
|
|
||||||
return get_input_default(node_->input_socket(index), to_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem NodeParser::get_input_link(const std::string &name, NodeItem::Type to_type)
|
|
||||||
{
|
|
||||||
return get_input_link(node_->input_by_identifier(name), to_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem NodeParser::get_input_link(int index, NodeItem::Type to_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
|
|
||||||
{
|
|
||||||
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 res = empty();
|
|
||||||
switch (socket.type) {
|
|
||||||
case SOCK_FLOAT: {
|
|
||||||
float v = socket.default_value_typed<bNodeSocketValueFloat>()->value;
|
|
||||||
res.value = MaterialX::Value::createValue<float>(v);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SOCK_VECTOR: {
|
|
||||||
const float *v = socket.default_value_typed<bNodeSocketValueVector>()->value;
|
|
||||||
res.value = MaterialX::Value::createValue<MaterialX::Vector3>(
|
|
||||||
MaterialX::Vector3(v[0], v[1], v[2]));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SOCK_RGBA: {
|
|
||||||
const float *v = socket.default_value_typed<bNodeSocketValueRGBA>()->value;
|
|
||||||
res.value = MaterialX::Value::createValue<MaterialX::Color4>(
|
|
||||||
MaterialX::Color4(v[0], v[1], v[2], v[3]));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unsupported socket type: %d", socket.type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res.convert(to_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem NodeParser::get_input_link(const bNodeSocket &socket, NodeItem::Type to_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 NodeParser object */
|
|
||||||
std::unique_ptr<NodeParser> parser;
|
|
||||||
|
|
||||||
#define CASE_NODE_TYPE(type, T) \
|
|
||||||
case type: \
|
|
||||||
parser = std::make_unique<T>(graph_, depsgraph_, material_, from_node, link->fromsock); \
|
|
||||||
break;
|
|
||||||
|
|
||||||
switch (from_node->typeinfo->type) {
|
|
||||||
CASE_NODE_TYPE(SH_NODE_BLACKBODY, BlackbodyNodeParser)
|
|
||||||
CASE_NODE_TYPE(SH_NODE_BRIGHTCONTRAST, BrightContrastNodeParser)
|
|
||||||
CASE_NODE_TYPE(SH_NODE_CLAMP, ClampNodeParser)
|
|
||||||
CASE_NODE_TYPE(SH_NODE_COMBINE_COLOR, CombineColorNodeParser)
|
|
||||||
CASE_NODE_TYPE(SH_NODE_COMBXYZ, CombineXYZNodeParser)
|
|
||||||
CASE_NODE_TYPE(SH_NODE_HUE_SAT, HueSatValNodeParser)
|
|
||||||
CASE_NODE_TYPE(SH_NODE_INVERT, InvertNodeParser)
|
|
||||||
CASE_NODE_TYPE(SH_NODE_MAP_RANGE, MapRangeNodeParser)
|
|
||||||
CASE_NODE_TYPE(SH_NODE_MATH, MathNodeParser)
|
|
||||||
CASE_NODE_TYPE(SH_NODE_MIX_RGB_LEGACY, MixRGBNodeParser)
|
|
||||||
CASE_NODE_TYPE(SH_NODE_NORMAL_MAP, NormalMapNodeParser)
|
|
||||||
CASE_NODE_TYPE(SH_NODE_RGBTOBW, RGBToBWNodeParser)
|
|
||||||
CASE_NODE_TYPE(SH_NODE_SEPARATE_COLOR, SeparateColorNodeParser)
|
|
||||||
CASE_NODE_TYPE(SH_NODE_SEPXYZ, SeparateXYZNodeParser)
|
|
||||||
CASE_NODE_TYPE(SH_NODE_TEX_CHECKER, TexCheckerNodeParser)
|
|
||||||
CASE_NODE_TYPE(SH_NODE_TEX_ENVIRONMENT, TexEnvironmentNodeParser)
|
|
||||||
CASE_NODE_TYPE(SH_NODE_TEX_IMAGE, TexImageNodeParser)
|
|
||||||
CASE_NODE_TYPE(SH_NODE_TEX_NOISE, TexNoiseNodeParser)
|
|
||||||
CASE_NODE_TYPE(SH_NODE_VECTOR_MATH, VectorMathNodeParser)
|
|
||||||
|
|
||||||
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.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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 ShaderNodeParser::compute_full()
|
|
||||||
{
|
|
||||||
CLOG_INFO(LOG_MATERIALX_SHADER,
|
|
||||||
1,
|
|
||||||
"%s [%d] - %s",
|
|
||||||
node_->name,
|
|
||||||
node_->typeinfo->type,
|
|
||||||
NodeItem::type(shader_type_).c_str());
|
|
||||||
NodeItem res = compute();
|
|
||||||
if (res.node) {
|
|
||||||
res.node->setName(node_name());
|
|
||||||
}
|
|
||||||
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
|
|
@ -1,128 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "node_item.h"
|
|
||||||
|
|
||||||
#include "DEG_depsgraph.h"
|
|
||||||
#include "DNA_material_types.h"
|
|
||||||
#include "DNA_node_types.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
class NodeParser {
|
|
||||||
protected:
|
|
||||||
MaterialX::GraphElement *graph_;
|
|
||||||
const Depsgraph *depsgraph_;
|
|
||||||
const Material *material_;
|
|
||||||
const bNode *node_;
|
|
||||||
const bNodeSocket *socket_out_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
NodeParser(MaterialX::GraphElement *graph,
|
|
||||||
const Depsgraph *depsgraph,
|
|
||||||
const Material *material,
|
|
||||||
const bNode *node,
|
|
||||||
const bNodeSocket *socket_out);
|
|
||||||
virtual ~NodeParser() = default;
|
|
||||||
|
|
||||||
virtual NodeItem compute() = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual NodeItem compute_full();
|
|
||||||
virtual std::string node_name();
|
|
||||||
NodeItem create_node(const std::string &category, NodeItem::Type type);
|
|
||||||
NodeItem get_input_default(const std::string &name, NodeItem::Type to_type);
|
|
||||||
NodeItem get_input_default(int index, NodeItem::Type to_type);
|
|
||||||
NodeItem get_input_link(const std::string &name, NodeItem::Type to_type);
|
|
||||||
NodeItem get_input_link(int index, NodeItem::Type to_type);
|
|
||||||
NodeItem get_input_value(const std::string &name, NodeItem::Type to_type);
|
|
||||||
NodeItem get_input_value(int index, NodeItem::Type to_type);
|
|
||||||
NodeItem empty() const;
|
|
||||||
template<class T> NodeItem val(const T &data) const;
|
|
||||||
NodeItem texcoord_node();
|
|
||||||
|
|
||||||
private:
|
|
||||||
NodeItem get_input_default(const bNodeSocket &socket, NodeItem::Type to_type);
|
|
||||||
NodeItem get_input_link(const bNodeSocket &socket, NodeItem::Type to_type);
|
|
||||||
NodeItem get_input_value(const bNodeSocket &socket, NodeItem::Type to_type);
|
|
||||||
};
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DECLARE_NODE_PARSER(T) \
|
|
||||||
class T : public NodeParser { \
|
|
||||||
public: \
|
|
||||||
using NodeParser::NodeParser; \
|
|
||||||
NodeItem compute() override; \
|
|
||||||
};
|
|
||||||
|
|
||||||
#define DECLARE_SHADER_NODE_PARSER(T) \
|
|
||||||
class T : public ShaderNodeParser { \
|
|
||||||
public: \
|
|
||||||
using ShaderNodeParser::ShaderNodeParser; \
|
|
||||||
NodeItem compute() override; \
|
|
||||||
};
|
|
||||||
|
|
||||||
DECLARE_NODE_PARSER(BlackbodyNodeParser)
|
|
||||||
DECLARE_NODE_PARSER(BrightContrastNodeParser)
|
|
||||||
DECLARE_NODE_PARSER(ClampNodeParser)
|
|
||||||
DECLARE_NODE_PARSER(CombineColorNodeParser)
|
|
||||||
DECLARE_NODE_PARSER(CombineXYZNodeParser)
|
|
||||||
DECLARE_NODE_PARSER(HueSatValNodeParser)
|
|
||||||
DECLARE_NODE_PARSER(InvertNodeParser)
|
|
||||||
DECLARE_NODE_PARSER(MapRangeNodeParser)
|
|
||||||
DECLARE_NODE_PARSER(MathNodeParser)
|
|
||||||
DECLARE_NODE_PARSER(MixRGBNodeParser)
|
|
||||||
DECLARE_NODE_PARSER(NormalMapNodeParser)
|
|
||||||
DECLARE_NODE_PARSER(RGBToBWNodeParser)
|
|
||||||
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
|
|
@ -1,40 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "../material.h"
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem NormalMapNodeParser::compute()
|
|
||||||
{
|
|
||||||
std::string default_space = "object";
|
|
||||||
NodeShaderNormalMap *normal_map_node = static_cast<NodeShaderNormalMap *>(node_->storage);
|
|
||||||
NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
|
|
||||||
NodeItem strength = get_input_value("Strength", NodeItem::Type::Float);
|
|
||||||
|
|
||||||
NodeItem res = create_node("normalmap", NodeItem::Type::Vector3);
|
|
||||||
res.set_input("in", color);
|
|
||||||
res.set_input("scale", strength);
|
|
||||||
|
|
||||||
switch (normal_map_node->space) {
|
|
||||||
case SHD_SPACE_TANGENT:
|
|
||||||
res.set_input("space", val(std::string("tangent")));
|
|
||||||
break;
|
|
||||||
case SHD_SPACE_OBJECT:
|
|
||||||
res.set_input("space", val(std::string("tangent")));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
res.set_input("space", val(default_space));
|
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER,
|
|
||||||
"Ignoring unsupported Space: %d %s (%d), %s will be used",
|
|
||||||
normal_map_node->space,
|
|
||||||
node_->name,
|
|
||||||
node_->type,
|
|
||||||
default_space);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -1,70 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "output_material.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
OutputMaterialNodeParser::OutputMaterialNodeParser(MaterialX::GraphElement *graph,
|
|
||||||
const Depsgraph *depsgraph,
|
|
||||||
const Material *material,
|
|
||||||
const bNode *node)
|
|
||||||
: ShaderNodeParser(graph, depsgraph, material, node, nullptr, NodeItem::Type::Material)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem OutputMaterialNodeParser::compute()
|
|
||||||
{
|
|
||||||
NodeItem surface = empty();
|
|
||||||
if (node_) {
|
|
||||||
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 {
|
|
||||||
surface = create_node("standard_surface", NodeItem::Type::SurfaceShader);
|
|
||||||
surface.set_input("base_color", val(MaterialX::Color3(1.0f, 0.0f, 1.0f)));
|
|
||||||
}
|
|
||||||
NodeItem res = create_node("surfacematerial", NodeItem::Type::Material);
|
|
||||||
res.set_input("surfaceshader", surface);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem OutputMaterialNodeParser::compute_default()
|
|
||||||
{
|
|
||||||
NodeItem surface = create_node("standard_surface", NodeItem::Type::SurfaceShader);
|
|
||||||
surface.set_input("base_color",
|
|
||||||
val(MaterialX::Color3(material_->r, material_->g, material_->b)));
|
|
||||||
surface.set_input("diffuse_roughness", val(material_->roughness));
|
|
||||||
if (material_->metallic > 0.0f) {
|
|
||||||
surface.set_input("metalness", val(material_->metallic));
|
|
||||||
}
|
|
||||||
if (material_->spec) {
|
|
||||||
surface.set_input("specular", val(material_->spec));
|
|
||||||
surface.set_input("specular_color", val(material_->spec));
|
|
||||||
surface.set_input("specular_roughness", val(material_->roughness));
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem res = create_node("surfacematerial", NodeItem::Type::Material);
|
|
||||||
res.node->setName("Material_Default");
|
|
||||||
res.set_input("surfaceshader", surface);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string OutputMaterialNodeParser::node_name()
|
|
||||||
{
|
|
||||||
return NodeParser::node_name();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -1,26 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
class OutputMaterialNodeParser : public ShaderNodeParser {
|
|
||||||
public:
|
|
||||||
OutputMaterialNodeParser(MaterialX::GraphElement *graph,
|
|
||||||
const Depsgraph *depsgraph,
|
|
||||||
const Material *material,
|
|
||||||
const bNode *node);
|
|
||||||
NodeItem compute() override;
|
|
||||||
|
|
||||||
using ShaderNodeParser::compute_full;
|
|
||||||
NodeItem compute_default();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::string node_name() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -1,18 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem RGBToBWNodeParser::compute()
|
|
||||||
{
|
|
||||||
NodeItem color = get_input_value("Color", NodeItem::Type::Color4);
|
|
||||||
|
|
||||||
NodeItem res = create_node("luminance", NodeItem::Type::Color4);
|
|
||||||
res.set_input("in", color);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -1,72 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "../material.h"
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem SeparateColorNodeParser::compute()
|
|
||||||
{
|
|
||||||
int mode = static_cast<NodeCombSepColor *>(node_->storage)->mode;
|
|
||||||
NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
|
|
||||||
|
|
||||||
NodeItem convert = empty();
|
|
||||||
|
|
||||||
switch (mode) {
|
|
||||||
case NODE_COMBSEP_COLOR_RGB:
|
|
||||||
break;
|
|
||||||
case NODE_COMBSEP_COLOR_HSV:
|
|
||||||
convert = create_node("rgbtohsv", NodeItem::Type::Color3);
|
|
||||||
convert.set_input("in", color);
|
|
||||||
break;
|
|
||||||
case NODE_COMBSEP_COLOR_HSL:
|
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unsupported color model, using HSV instead: %d", mode);
|
|
||||||
convert = create_node("rgbtohsv", NodeItem::Type::Color3);
|
|
||||||
convert.set_input("in", color);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
BLI_assert_unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
int index = STREQ(socket_out_->name, "Red") ? 0 : STREQ(socket_out_->name, "Green") ? 1 : 2;
|
|
||||||
|
|
||||||
NodeItem res = convert ? convert : color;
|
|
||||||
return res.extract(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem CombineColorNodeParser::compute()
|
|
||||||
{
|
|
||||||
int mode = static_cast<NodeCombSepColor *>(node_->storage)->mode;
|
|
||||||
NodeItem red = get_input_value("Red", NodeItem::Type::Float);
|
|
||||||
NodeItem green = get_input_value("Green", NodeItem::Type::Float);
|
|
||||||
NodeItem blue = get_input_value("Blue", NodeItem::Type::Float);
|
|
||||||
|
|
||||||
NodeItem convert = empty();
|
|
||||||
NodeItem combine = create_node("combine3", NodeItem::Type::Color3);
|
|
||||||
combine.set_input("in1", red);
|
|
||||||
combine.set_input("in2", green);
|
|
||||||
combine.set_input("in3", blue);
|
|
||||||
|
|
||||||
switch (mode) {
|
|
||||||
case NODE_COMBSEP_COLOR_RGB:
|
|
||||||
break;
|
|
||||||
case NODE_COMBSEP_COLOR_HSV:
|
|
||||||
convert = create_node("hsvtorgb", NodeItem::Type::Color3);
|
|
||||||
convert.set_input("in", combine);
|
|
||||||
break;
|
|
||||||
case NODE_COMBSEP_COLOR_HSL:
|
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unsupported color model, using HSV instead: %d", mode);
|
|
||||||
convert = create_node("hsvtorgb", NodeItem::Type::Color3);
|
|
||||||
convert.set_input("in", combine);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
BLI_assert_unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem res = convert ? convert : combine;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -1,28 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem SeparateXYZNodeParser::compute()
|
|
||||||
{
|
|
||||||
NodeItem vector = get_input_value("Vector", NodeItem::Type::Vector3);
|
|
||||||
int index = STREQ(socket_out_->name, "X") ? 0 : STREQ(socket_out_->name, "Y") ? 1 : 2;
|
|
||||||
return vector.extract(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem CombineXYZNodeParser::compute()
|
|
||||||
{
|
|
||||||
NodeItem x = get_input_value("X", NodeItem::Type::Float);
|
|
||||||
NodeItem y = get_input_value("Y", NodeItem::Type::Float);
|
|
||||||
NodeItem z = get_input_value("Z", NodeItem::Type::Float);
|
|
||||||
NodeItem res = create_node("combine3", NodeItem::Type::Vector3);
|
|
||||||
res.set_input("in1", x);
|
|
||||||
res.set_input("in2", y);
|
|
||||||
res.set_input("in3", z);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -1,15 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem SubsurfaceScatteringNodeParser::compute()
|
|
||||||
{
|
|
||||||
/* TODO: implement */
|
|
||||||
return empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -1,28 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem TexCheckerNodeParser::compute()
|
|
||||||
{
|
|
||||||
NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector2);
|
|
||||||
if (!vector) {
|
|
||||||
vector = texcoord_node();
|
|
||||||
}
|
|
||||||
NodeItem value1 = val(1.0f);
|
|
||||||
NodeItem value2 = val(0.0f);
|
|
||||||
if (STREQ(socket_out_->name, "Color")) {
|
|
||||||
value1 = get_input_value("Color1", NodeItem::Type::Color4);
|
|
||||||
value2 = get_input_value("Color2", NodeItem::Type::Color4);
|
|
||||||
}
|
|
||||||
NodeItem scale = get_input_value("Scale", NodeItem::Type::Float);
|
|
||||||
|
|
||||||
vector = (vector * scale) % val(2.0f);
|
|
||||||
return (vector.extract(0).floor() + vector.extract(1).floor())
|
|
||||||
.if_else(NodeItem::CompareOp::Eq, val(1.0f), value1, value2);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -1,61 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
#include "hydra/image.h"
|
|
||||||
|
|
||||||
#include "DEG_depsgraph_query.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem TexEnvironmentNodeParser::compute()
|
|
||||||
{
|
|
||||||
NodeItem res = val(MaterialX::Color4(1.0f, 0.0f, 1.0f, 1.0f));
|
|
||||||
|
|
||||||
Image *image = (Image *)node_->id;
|
|
||||||
if (!image) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeTexEnvironment *tex_env = static_cast<NodeTexEnvironment *>(node_->storage);
|
|
||||||
Scene *scene = DEG_get_input_scene(depsgraph_);
|
|
||||||
Main *bmain = DEG_get_bmain(depsgraph_);
|
|
||||||
|
|
||||||
/* TODO: What if Blender built without Hydra? Also io::hydra::cache_or_get_image_file contains
|
|
||||||
* pretty general code, so could be moved from bf_usd project. */
|
|
||||||
std::string image_path = io::hydra::cache_or_get_image_file(
|
|
||||||
bmain, scene, image, &tex_env->iuser);
|
|
||||||
|
|
||||||
NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector2);
|
|
||||||
if (!vector) {
|
|
||||||
vector = texcoord_node();
|
|
||||||
}
|
|
||||||
/* TODO: texcoords should be translated to spherical coordinates */
|
|
||||||
|
|
||||||
std::string filtertype;
|
|
||||||
switch (tex_env->interpolation) {
|
|
||||||
case SHD_INTERP_LINEAR:
|
|
||||||
filtertype = "linear";
|
|
||||||
break;
|
|
||||||
case SHD_INTERP_CLOSEST:
|
|
||||||
filtertype = "closest";
|
|
||||||
break;
|
|
||||||
case SHD_INTERP_CUBIC:
|
|
||||||
case SHD_INTERP_SMART:
|
|
||||||
filtertype = "cubic";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
BLI_assert_unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
res = create_node("image", NodeItem::Type::Color4);
|
|
||||||
res.set_input("file", image_path, NodeItem::Type::Filename);
|
|
||||||
res.set_input("texcoord", vector);
|
|
||||||
res.set_input("filtertype", val(filtertype));
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -1,81 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
#include "hydra/image.h"
|
|
||||||
|
|
||||||
#include "DEG_depsgraph_query.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem TexImageNodeParser::compute()
|
|
||||||
{
|
|
||||||
NodeItem res = val(MaterialX::Color4(1.0f, 0.0f, 1.0f, 1.0f));
|
|
||||||
|
|
||||||
Image *image = (Image *)node_->id;
|
|
||||||
if (image) {
|
|
||||||
NodeTexImage *tex_image = static_cast<NodeTexImage *>(node_->storage);
|
|
||||||
Scene *scene = DEG_get_input_scene(depsgraph_);
|
|
||||||
Main *bmain = DEG_get_bmain(depsgraph_);
|
|
||||||
|
|
||||||
/* TODO: What if Blender built without Hydra? Also io::hydra::cache_or_get_image_file contains
|
|
||||||
* pretty general code, so could be moved from bf_usd project. */
|
|
||||||
std::string image_path = io::hydra::cache_or_get_image_file(
|
|
||||||
bmain, scene, image, &tex_image->iuser);
|
|
||||||
|
|
||||||
NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector2);
|
|
||||||
if (!vector) {
|
|
||||||
vector = texcoord_node();
|
|
||||||
}
|
|
||||||
/* TODO: add math to vector depending of tex_image->projection */
|
|
||||||
|
|
||||||
std::string filtertype;
|
|
||||||
switch (tex_image->interpolation) {
|
|
||||||
case SHD_INTERP_LINEAR:
|
|
||||||
filtertype = "linear";
|
|
||||||
break;
|
|
||||||
case SHD_INTERP_CLOSEST:
|
|
||||||
filtertype = "closest";
|
|
||||||
break;
|
|
||||||
case SHD_INTERP_CUBIC:
|
|
||||||
case SHD_INTERP_SMART:
|
|
||||||
filtertype = "cubic";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
BLI_assert_unreachable();
|
|
||||||
}
|
|
||||||
std::string addressmode;
|
|
||||||
switch (tex_image->extension) {
|
|
||||||
case SHD_IMAGE_EXTENSION_REPEAT:
|
|
||||||
addressmode = "periodic";
|
|
||||||
break;
|
|
||||||
case SHD_IMAGE_EXTENSION_EXTEND:
|
|
||||||
addressmode = "clamp";
|
|
||||||
break;
|
|
||||||
case SHD_IMAGE_EXTENSION_CLIP:
|
|
||||||
addressmode = "constant";
|
|
||||||
break;
|
|
||||||
case SHD_IMAGE_EXTENSION_MIRROR:
|
|
||||||
addressmode = "mirror";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
BLI_assert_unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
res = create_node("image", NodeItem::Type::Color4);
|
|
||||||
res.set_input("file", image_path, NodeItem::Type::Filename);
|
|
||||||
res.set_input("texcoord", vector);
|
|
||||||
res.set_input("filtertype", val(filtertype));
|
|
||||||
res.set_input("uaddressmode", val(addressmode));
|
|
||||||
res.set_input("vaddressmode", val(addressmode));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (STREQ(socket_out_->name, "Alpha")) {
|
|
||||||
res = res.extract(3);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -1,29 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem TexNoiseNodeParser::compute()
|
|
||||||
{
|
|
||||||
NodeItem scale = get_input_value("Scale", NodeItem::Type::Float);
|
|
||||||
NodeItem detail = get_input_value("Detail", NodeItem::Type::Float);
|
|
||||||
NodeItem lacunarity = get_input_value("Lacunarity", NodeItem::Type::Float);
|
|
||||||
|
|
||||||
if (detail.value && detail.type() == NodeItem::Type::Float) {
|
|
||||||
detail = val(int(detail.value->asA<float>()));
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem position = create_node("position", NodeItem::Type::Vector3);
|
|
||||||
position = position * scale;
|
|
||||||
|
|
||||||
NodeItem res = create_node("fractal3d", NodeItem::Type::Color3);
|
|
||||||
res.set_input("position", position);
|
|
||||||
res.set_input("octaves", detail);
|
|
||||||
res.set_input("lacunarity", lacunarity);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -1,122 +0,0 @@
|
|||||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#include "../material.h"
|
|
||||||
#include "node_parser.h"
|
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
|
||||||
|
|
||||||
NodeItem VectorMathNodeParser::compute()
|
|
||||||
{
|
|
||||||
/* TODO: finish some math operations */
|
|
||||||
auto op = node_->custom1;
|
|
||||||
NodeItem res = empty();
|
|
||||||
|
|
||||||
/* Single operand operations */
|
|
||||||
NodeItem x = get_input_value(0, NodeItem::Type::Any);
|
|
||||||
switch (op) {
|
|
||||||
case NODE_VECTOR_MATH_SINE:
|
|
||||||
res = x.sin();
|
|
||||||
break;
|
|
||||||
case NODE_VECTOR_MATH_COSINE:
|
|
||||||
res = x.cos();
|
|
||||||
break;
|
|
||||||
case NODE_VECTOR_MATH_TANGENT:
|
|
||||||
res = x.tan();
|
|
||||||
break;
|
|
||||||
case NODE_VECTOR_MATH_ABSOLUTE:
|
|
||||||
res = x.abs();
|
|
||||||
break;
|
|
||||||
case NODE_VECTOR_MATH_FLOOR:
|
|
||||||
res = x.floor();
|
|
||||||
break;
|
|
||||||
case NODE_VECTOR_MATH_CEIL:
|
|
||||||
res = x.ceil();
|
|
||||||
break;
|
|
||||||
case NODE_VECTOR_MATH_FRACTION:
|
|
||||||
res = x % val(1.0f);
|
|
||||||
break;
|
|
||||||
case NODE_VECTOR_MATH_LENGTH:
|
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
|
||||||
break;
|
|
||||||
case NODE_VECTOR_MATH_NORMALIZE:
|
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: {
|
|
||||||
/* 2-operand operations */
|
|
||||||
NodeItem y = get_input_value(1, NodeItem::Type::Any);
|
|
||||||
switch (op) {
|
|
||||||
case NODE_VECTOR_MATH_ADD:
|
|
||||||
res = x + y;
|
|
||||||
break;
|
|
||||||
case NODE_VECTOR_MATH_SUBTRACT:
|
|
||||||
res = x - y;
|
|
||||||
break;
|
|
||||||
case NODE_VECTOR_MATH_MULTIPLY:
|
|
||||||
res = x * y;
|
|
||||||
break;
|
|
||||||
case NODE_VECTOR_MATH_DIVIDE:
|
|
||||||
res = x / y;
|
|
||||||
break;
|
|
||||||
case NODE_VECTOR_MATH_MINIMUM:
|
|
||||||
res = x.min(y);
|
|
||||||
break;
|
|
||||||
case NODE_VECTOR_MATH_MAXIMUM:
|
|
||||||
res = x.max(y);
|
|
||||||
break;
|
|
||||||
case NODE_VECTOR_MATH_MODULO:
|
|
||||||
res = x % y;
|
|
||||||
break;
|
|
||||||
case NODE_VECTOR_MATH_SNAP:
|
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
|
||||||
break;
|
|
||||||
case NODE_VECTOR_MATH_CROSS_PRODUCT:
|
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
|
||||||
break;
|
|
||||||
case NODE_VECTOR_MATH_DOT_PRODUCT:
|
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
|
||||||
break;
|
|
||||||
case NODE_VECTOR_MATH_PROJECT:
|
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
|
||||||
break;
|
|
||||||
case NODE_VECTOR_MATH_REFLECT:
|
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
|
||||||
break;
|
|
||||||
case NODE_VECTOR_MATH_DISTANCE:
|
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
|
||||||
break;
|
|
||||||
case NODE_VECTOR_MATH_SCALE:
|
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: {
|
|
||||||
/* 3-operand operations */
|
|
||||||
NodeItem z = get_input_value(2, NodeItem::Type::Any);
|
|
||||||
switch (op) {
|
|
||||||
case NODE_VECTOR_MATH_MULTIPLY_ADD:
|
|
||||||
res = x * y + z;
|
|
||||||
break;
|
|
||||||
case NODE_VECTOR_MATH_REFRACT:
|
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
|
||||||
break;
|
|
||||||
case NODE_VECTOR_MATH_FACEFORWARD:
|
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
|
||||||
break;
|
|
||||||
case NODE_VECTOR_MATH_WRAP:
|
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
BLI_assert_unreachable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
|
@ -22,6 +22,8 @@
|
|||||||
|
|
||||||
#include "node_shader_register.hh"
|
#include "node_shader_register.hh"
|
||||||
|
|
||||||
|
#include "materialx/node_parser.h"
|
||||||
|
|
||||||
struct bContext;
|
struct bContext;
|
||||||
typedef struct bContext bContext;
|
typedef struct bContext bContext;
|
||||||
struct bNodeExecContext;
|
struct bNodeExecContext;
|
||||||
|
@ -22,6 +22,41 @@ static int node_shader_gpu_add_shader(GPUMaterial *mat,
|
|||||||
return GPU_stack_link(mat, node, "node_add_shader", in, out);
|
return GPU_stack_link(mat, node, "node_add_shader", in, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
NodeItem res = empty();
|
||||||
|
switch (to_type_) {
|
||||||
|
case NodeItem::Type::BSDF:
|
||||||
|
case NodeItem::Type::EDF: {
|
||||||
|
NodeItem shader1 = get_input_link(0, to_type_);
|
||||||
|
NodeItem shader2 = get_input_link(1, to_type_);
|
||||||
|
|
||||||
|
if (shader1 && !shader2) {
|
||||||
|
res = shader1;
|
||||||
|
}
|
||||||
|
else if (!shader1 && shader2) {
|
||||||
|
res = shader2;
|
||||||
|
}
|
||||||
|
else if (shader1 && shader2) {
|
||||||
|
res = shader1 + shader2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NodeItem::Type::SurfaceShader: {
|
||||||
|
/* SurfaceShaders can't be added, returning the first one connected */
|
||||||
|
res = get_input_link(0, to_type_);
|
||||||
|
if (!res) {
|
||||||
|
res = get_input_link(1, to_type_);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_add_shader_cc
|
} // namespace blender::nodes::node_shader_add_shader_cc
|
||||||
|
|
||||||
/* node type definition */
|
/* node type definition */
|
||||||
|
@ -31,6 +31,20 @@ static int node_shader_gpu_blackbody(GPUMaterial *mat,
|
|||||||
return GPU_stack_link(mat, node, "node_blackbody", in, out, ramp_texture, GPU_constant(&layer));
|
return GPU_stack_link(mat, node, "node_blackbody", in, out, ramp_texture, GPU_constant(&layer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
/* TODO: This node doesn't have an implementation in MaterialX 1.38.6.
|
||||||
|
* It's added in MaterialX 1.38.8. Uncomment this code after switching to 1.38.8.
|
||||||
|
*
|
||||||
|
* NodeItem temperature = get_input_value("Temperature", NodeItem::Type::Float);
|
||||||
|
|
||||||
|
* NodeItem res = create_node("blackbody", NodeItem::Type::Color3);
|
||||||
|
* res.set_input("temperature", temperature);
|
||||||
|
* return res; */
|
||||||
|
return empty();
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_blackbody_cc
|
} // namespace blender::nodes::node_shader_blackbody_cc
|
||||||
|
|
||||||
/* node type definition */
|
/* node type definition */
|
||||||
@ -44,6 +58,7 @@ void register_node_type_sh_blackbody()
|
|||||||
ntype.declare = file_ns::node_declare;
|
ntype.declare = file_ns::node_declare;
|
||||||
blender::bke::node_type_size_preset(&ntype, blender::bke::eNodeSizePreset::MIDDLE);
|
blender::bke::node_type_size_preset(&ntype, blender::bke::eNodeSizePreset::MIDDLE);
|
||||||
ntype.gpu_fn = file_ns::node_shader_gpu_blackbody;
|
ntype.gpu_fn = file_ns::node_shader_gpu_blackbody;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,17 @@ static int gpu_shader_brightcontrast(GPUMaterial *mat,
|
|||||||
return GPU_stack_link(mat, node, "brightness_contrast", in, out);
|
return GPU_stack_link(mat, node, "brightness_contrast", in, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
|
||||||
|
NodeItem bright = get_input_value("Bright", NodeItem::Type::Float);
|
||||||
|
NodeItem contrast = get_input_value("Contrast", NodeItem::Type::Float);
|
||||||
|
|
||||||
|
/* This formula was given from OSL shader code in Cycles. */
|
||||||
|
return (bright + color * (contrast + val(1.0f)) - contrast * val(0.5f)).max(val(0.0f));
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_brightness_cc
|
} // namespace blender::nodes::node_shader_brightness_cc
|
||||||
|
|
||||||
void register_node_type_sh_brightcontrast()
|
void register_node_type_sh_brightcontrast()
|
||||||
@ -34,6 +45,7 @@ void register_node_type_sh_brightcontrast()
|
|||||||
sh_node_type_base(&ntype, SH_NODE_BRIGHTCONTRAST, "Brightness/Contrast", NODE_CLASS_OP_COLOR);
|
sh_node_type_base(&ntype, SH_NODE_BRIGHTCONTRAST, "Brightness/Contrast", NODE_CLASS_OP_COLOR);
|
||||||
ntype.declare = file_ns::node_declare;
|
ntype.declare = file_ns::node_declare;
|
||||||
ntype.gpu_fn = file_ns::gpu_shader_brightcontrast;
|
ntype.gpu_fn = file_ns::gpu_shader_brightcontrast;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,26 @@ static int node_shader_gpu_bsdf_diffuse(GPUMaterial *mat,
|
|||||||
return GPU_stack_link(mat, node, "node_bsdf_diffuse", in, out);
|
return GPU_stack_link(mat, node, "node_bsdf_diffuse", in, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
if (to_type_ != NodeItem::Type::BSDF) {
|
||||||
|
return empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
|
||||||
|
NodeItem roughness = get_input_value("Roughness", NodeItem::Type::Float);
|
||||||
|
NodeItem normal = get_input_link("Normal", NodeItem::Type::Vector3);
|
||||||
|
|
||||||
|
NodeItem res = create_node("oren_nayar_diffuse_bsdf", NodeItem::Type::BSDF);
|
||||||
|
res.set_input("color", color);
|
||||||
|
res.set_input("roughness", roughness);
|
||||||
|
if (normal) {
|
||||||
|
res.set_input("normal", normal);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_bsdf_diffuse_cc
|
} // namespace blender::nodes::node_shader_bsdf_diffuse_cc
|
||||||
|
|
||||||
/* node type definition */
|
/* node type definition */
|
||||||
@ -48,6 +68,7 @@ void register_node_type_sh_bsdf_diffuse()
|
|||||||
ntype.add_ui_poll = object_shader_nodes_poll;
|
ntype.add_ui_poll = object_shader_nodes_poll;
|
||||||
blender::bke::node_type_size_preset(&ntype, blender::bke::eNodeSizePreset::MIDDLE);
|
blender::bke::node_type_size_preset(&ntype, blender::bke::eNodeSizePreset::MIDDLE);
|
||||||
ntype.gpu_fn = file_ns::node_shader_gpu_bsdf_diffuse;
|
ntype.gpu_fn = file_ns::node_shader_gpu_bsdf_diffuse;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
@ -253,6 +253,99 @@ static void node_shader_update_principled(bNodeTree *ntree, bNode *node)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
if (to_type_ != NodeItem::Type::SurfaceShader) {
|
||||||
|
/* TODO: implement for BSDF and EDF */
|
||||||
|
return empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem base_color = get_input_value("Base Color", NodeItem::Type::Color3);
|
||||||
|
|
||||||
|
NodeItem subsurface = get_input_value("Subsurface", NodeItem::Type::Float);
|
||||||
|
NodeItem subsurface_radius = get_input_value("Subsurface Radius", NodeItem::Type::Color3);
|
||||||
|
NodeItem subsurface_color = get_input_value("Subsurface Color", NodeItem::Type::Color3);
|
||||||
|
|
||||||
|
NodeItem metallic = get_input_value("Metallic", NodeItem::Type::Float);
|
||||||
|
NodeItem specular = get_input_value("Specular", NodeItem::Type::Float);
|
||||||
|
// NodeItem specular_tint = get_input_value("Specular Tint");
|
||||||
|
NodeItem roughness = get_input_value("Roughness", NodeItem::Type::Float);
|
||||||
|
|
||||||
|
/* TODO: use Specular Tint input */
|
||||||
|
NodeItem anisotropic = get_input_value("Anisotropic", NodeItem::Type::Float);
|
||||||
|
NodeItem anisotropic_rotation = get_input_value("Anisotropic Rotation", NodeItem::Type::Float);
|
||||||
|
// anisotropic_rotation = 0.5 - (anisotropic_rotation % 1.0)
|
||||||
|
|
||||||
|
NodeItem sheen = get_input_value("Sheen", NodeItem::Type::Float);
|
||||||
|
// sheen_tint = get_input_value("Sheen Tint");
|
||||||
|
|
||||||
|
NodeItem clearcoat = get_input_value("Clearcoat", NodeItem::Type::Float);
|
||||||
|
NodeItem clearcoat_roughness = get_input_value("Clearcoat Roughness", NodeItem::Type::Float);
|
||||||
|
|
||||||
|
NodeItem ior = get_input_value("IOR", NodeItem::Type::Float);
|
||||||
|
|
||||||
|
NodeItem transmission = get_input_value("Transmission", NodeItem::Type::Float);
|
||||||
|
|
||||||
|
NodeItem emission = get_input_value("Emission", NodeItem::Type::Color3);
|
||||||
|
NodeItem emission_strength = get_input_value("Emission Strength", NodeItem::Type::Float);
|
||||||
|
|
||||||
|
NodeItem alpha = get_input_value("Alpha", NodeItem::Type::Float);
|
||||||
|
// transparency = 1.0 - alpha
|
||||||
|
|
||||||
|
NodeItem normal = get_input_link("Normal", NodeItem::Type::Vector3);
|
||||||
|
NodeItem clearcoat_normal = get_input_link("Clearcoat Normal", NodeItem::Type::Vector3);
|
||||||
|
NodeItem tangent = get_input_link("Tangent", NodeItem::Type::Vector3);
|
||||||
|
|
||||||
|
/* Creating standard_surface */
|
||||||
|
NodeItem res = create_node("standard_surface", NodeItem::Type::SurfaceShader);
|
||||||
|
res.set_input("base", val(1.0f));
|
||||||
|
res.set_input("base_color", base_color);
|
||||||
|
res.set_input("diffuse_roughness", roughness);
|
||||||
|
if (normal) {
|
||||||
|
res.set_input("normal", normal);
|
||||||
|
}
|
||||||
|
if (tangent) {
|
||||||
|
res.set_input("tangent", tangent);
|
||||||
|
}
|
||||||
|
res.set_input("metalness", metallic);
|
||||||
|
|
||||||
|
res.set_input("specular", specular);
|
||||||
|
res.set_input("specular_color", base_color);
|
||||||
|
res.set_input("specular_roughness", roughness);
|
||||||
|
res.set_input("specular_IOR", ior);
|
||||||
|
res.set_input("specular_anisotropy", anisotropic);
|
||||||
|
res.set_input("specular_rotation", anisotropic_rotation);
|
||||||
|
|
||||||
|
res.set_input("transmission", transmission);
|
||||||
|
res.set_input("transmission_color", base_color);
|
||||||
|
res.set_input("transmission_extra_roughness", roughness);
|
||||||
|
|
||||||
|
res.set_input("subsurface", subsurface);
|
||||||
|
res.set_input("subsurface_color", subsurface_color);
|
||||||
|
res.set_input("subsurface_radius", subsurface_radius);
|
||||||
|
res.set_input("subsurface_anisotropy", anisotropic);
|
||||||
|
|
||||||
|
res.set_input("sheen", sheen);
|
||||||
|
res.set_input("sheen_color", base_color);
|
||||||
|
res.set_input("sheen_roughness", roughness);
|
||||||
|
|
||||||
|
res.set_input("coat", clearcoat);
|
||||||
|
res.set_input("coat_color", base_color);
|
||||||
|
res.set_input("coat_roughness", clearcoat_roughness);
|
||||||
|
res.set_input("coat_IOR", ior);
|
||||||
|
res.set_input("coat_anisotropy", anisotropic);
|
||||||
|
res.set_input("coat_rotation", anisotropic_rotation);
|
||||||
|
if (clearcoat_normal) {
|
||||||
|
res.set_input("coat_normal", clearcoat_normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.set_input("emission", emission_strength);
|
||||||
|
res.set_input("emission_color", emission);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_bsdf_principled_cc
|
} // namespace blender::nodes::node_shader_bsdf_principled_cc
|
||||||
|
|
||||||
/* node type definition */
|
/* node type definition */
|
||||||
@ -270,6 +363,7 @@ void register_node_type_sh_bsdf_principled()
|
|||||||
ntype.initfunc = file_ns::node_shader_init_principled;
|
ntype.initfunc = file_ns::node_shader_init_principled;
|
||||||
ntype.gpu_fn = file_ns::node_shader_gpu_bsdf_principled;
|
ntype.gpu_fn = file_ns::node_shader_gpu_bsdf_principled;
|
||||||
ntype.updatefunc = file_ns::node_shader_update_principled;
|
ntype.updatefunc = file_ns::node_shader_update_principled;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,25 @@ static void sh_node_clamp_build_multi_function(NodeMultiFunctionBuilder &builder
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
auto type = node_->custom1;
|
||||||
|
NodeItem value = get_input_value("Value", NodeItem::Type::Float);
|
||||||
|
NodeItem min = get_input_value("Min", NodeItem::Type::Float);
|
||||||
|
NodeItem max = get_input_value("Max", NodeItem::Type::Float);
|
||||||
|
|
||||||
|
NodeItem res = empty();
|
||||||
|
if (type == NODE_CLAMP_RANGE) {
|
||||||
|
res = min.if_else(
|
||||||
|
NodeItem::CompareOp::Less, max, value.clamp(min, max), value.clamp(max, min));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
res = value.clamp(min, max);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_clamp_cc
|
} // namespace blender::nodes::node_shader_clamp_cc
|
||||||
|
|
||||||
void register_node_type_sh_clamp()
|
void register_node_type_sh_clamp()
|
||||||
@ -84,6 +103,7 @@ void register_node_type_sh_clamp()
|
|||||||
ntype.initfunc = file_ns::node_shader_init_clamp;
|
ntype.initfunc = file_ns::node_shader_init_clamp;
|
||||||
ntype.gpu_fn = file_ns::gpu_shader_clamp;
|
ntype.gpu_fn = file_ns::gpu_shader_clamp;
|
||||||
ntype.build_multi_function = file_ns::sh_node_clamp_build_multi_function;
|
ntype.build_multi_function = file_ns::sh_node_clamp_build_multi_function;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
@ -136,6 +136,13 @@ static void sh_node_valtorgb_build_multi_function(nodes::NodeMultiFunctionBuilde
|
|||||||
builder.construct_and_set_matching_fn<ColorBandFunction>(*color_band);
|
builder.construct_and_set_matching_fn<ColorBandFunction>(*color_band);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
/* TODO: Implement */
|
||||||
|
return empty();
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_color_ramp_cc
|
} // namespace blender::nodes::node_shader_color_ramp_cc
|
||||||
|
|
||||||
void register_node_type_sh_valtorgb()
|
void register_node_type_sh_valtorgb()
|
||||||
@ -151,6 +158,7 @@ void register_node_type_sh_valtorgb()
|
|||||||
node_type_storage(&ntype, "ColorBand", node_free_standard_storage, node_copy_standard_storage);
|
node_type_storage(&ntype, "ColorBand", node_free_standard_storage, node_copy_standard_storage);
|
||||||
ntype.gpu_fn = file_ns::gpu_shader_valtorgb;
|
ntype.gpu_fn = file_ns::gpu_shader_valtorgb;
|
||||||
ntype.build_multi_function = file_ns::sh_node_valtorgb_build_multi_function;
|
ntype.build_multi_function = file_ns::sh_node_valtorgb_build_multi_function;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
#include "node_util.hh"
|
#include "node_util.hh"
|
||||||
|
|
||||||
namespace blender::nodes::node_shader_curves_cc {
|
namespace blender::nodes::node_shader_curves_cc::vec {
|
||||||
|
|
||||||
static void sh_node_curve_vec_declare(NodeDeclarationBuilder &b)
|
static void sh_node_curve_vec_declare(NodeDeclarationBuilder &b)
|
||||||
{
|
{
|
||||||
@ -109,11 +109,18 @@ static void sh_node_curve_vec_build_multi_function(NodeMultiFunctionBuilder &bui
|
|||||||
builder.construct_and_set_matching_fn<CurveVecFunction>(*cumap);
|
builder.construct_and_set_matching_fn<CurveVecFunction>(*cumap);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_curves_cc
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
/* TODO: implement */
|
||||||
|
return get_input_value("Value", NodeItem::Type::Vector3);
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
|
} // namespace blender::nodes::node_shader_curves_cc::vec
|
||||||
|
|
||||||
void register_node_type_sh_curve_vec()
|
void register_node_type_sh_curve_vec()
|
||||||
{
|
{
|
||||||
namespace file_ns = blender::nodes::node_shader_curves_cc;
|
namespace file_ns = blender::nodes::node_shader_curves_cc::vec;
|
||||||
|
|
||||||
static bNodeType ntype;
|
static bNodeType ntype;
|
||||||
|
|
||||||
@ -124,13 +131,14 @@ void register_node_type_sh_curve_vec()
|
|||||||
node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves);
|
node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves);
|
||||||
ntype.gpu_fn = file_ns::gpu_shader_curve_vec;
|
ntype.gpu_fn = file_ns::gpu_shader_curve_vec;
|
||||||
ntype.build_multi_function = file_ns::sh_node_curve_vec_build_multi_function;
|
ntype.build_multi_function = file_ns::sh_node_curve_vec_build_multi_function;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* **************** CURVE RGB ******************** */
|
/* **************** CURVE RGB ******************** */
|
||||||
|
|
||||||
namespace blender::nodes::node_shader_curves_cc {
|
namespace blender::nodes::node_shader_curves_cc::rgb {
|
||||||
|
|
||||||
static void sh_node_curve_rgb_declare(NodeDeclarationBuilder &b)
|
static void sh_node_curve_rgb_declare(NodeDeclarationBuilder &b)
|
||||||
{
|
{
|
||||||
@ -251,11 +259,18 @@ static void sh_node_curve_rgb_build_multi_function(NodeMultiFunctionBuilder &bui
|
|||||||
builder.construct_and_set_matching_fn<CurveRGBFunction>(*cumap);
|
builder.construct_and_set_matching_fn<CurveRGBFunction>(*cumap);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_curves_cc
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
/* TODO: implement */
|
||||||
|
return get_input_value("Color", NodeItem::Type::Color4);
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
|
} // namespace blender::nodes::node_shader_curves_cc::rgb
|
||||||
|
|
||||||
void register_node_type_sh_curve_rgb()
|
void register_node_type_sh_curve_rgb()
|
||||||
{
|
{
|
||||||
namespace file_ns = blender::nodes::node_shader_curves_cc;
|
namespace file_ns = blender::nodes::node_shader_curves_cc::rgb;
|
||||||
|
|
||||||
static bNodeType ntype;
|
static bNodeType ntype;
|
||||||
|
|
||||||
@ -266,13 +281,14 @@ void register_node_type_sh_curve_rgb()
|
|||||||
node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves);
|
node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves);
|
||||||
ntype.gpu_fn = file_ns::gpu_shader_curve_rgb;
|
ntype.gpu_fn = file_ns::gpu_shader_curve_rgb;
|
||||||
ntype.build_multi_function = file_ns::sh_node_curve_rgb_build_multi_function;
|
ntype.build_multi_function = file_ns::sh_node_curve_rgb_build_multi_function;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* **************** CURVE FLOAT ******************** */
|
/* **************** CURVE FLOAT ******************** */
|
||||||
|
|
||||||
namespace blender::nodes::node_shader_curves_cc {
|
namespace blender::nodes::node_shader_curves_cc::flt {
|
||||||
|
|
||||||
static void sh_node_curve_float_declare(NodeDeclarationBuilder &b)
|
static void sh_node_curve_float_declare(NodeDeclarationBuilder &b)
|
||||||
{
|
{
|
||||||
@ -369,11 +385,18 @@ static void sh_node_curve_float_build_multi_function(NodeMultiFunctionBuilder &b
|
|||||||
builder.construct_and_set_matching_fn<CurveFloatFunction>(*cumap);
|
builder.construct_and_set_matching_fn<CurveFloatFunction>(*cumap);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_curves_cc
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
/* TODO: implement */
|
||||||
|
return get_input_value("Value", NodeItem::Type::Float);
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
|
} // namespace blender::nodes::node_shader_curves_cc::flt
|
||||||
|
|
||||||
void register_node_type_sh_curve_float()
|
void register_node_type_sh_curve_float()
|
||||||
{
|
{
|
||||||
namespace file_ns = blender::nodes::node_shader_curves_cc;
|
namespace file_ns = blender::nodes::node_shader_curves_cc::flt;
|
||||||
|
|
||||||
static bNodeType ntype;
|
static bNodeType ntype;
|
||||||
|
|
||||||
@ -384,6 +407,7 @@ void register_node_type_sh_curve_float()
|
|||||||
node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves);
|
node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves);
|
||||||
ntype.gpu_fn = file_ns::gpu_shader_curve_float;
|
ntype.gpu_fn = file_ns::gpu_shader_curve_float;
|
||||||
ntype.build_multi_function = file_ns::sh_node_curve_float_build_multi_function;
|
ntype.build_multi_function = file_ns::sh_node_curve_float_build_multi_function;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,21 @@ static int node_shader_gpu_emission(GPUMaterial *mat,
|
|||||||
return GPU_stack_link(mat, node, "node_emission", in, out);
|
return GPU_stack_link(mat, node, "node_emission", in, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
if (to_type_ != NodeItem::Type::EDF) {
|
||||||
|
return empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
|
||||||
|
NodeItem strength = get_input_value("Strength", NodeItem::Type::Float);
|
||||||
|
|
||||||
|
NodeItem res = create_node("uniform_edf", NodeItem::Type::EDF);
|
||||||
|
res.set_input("color", color * strength);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_emission_cc
|
} // namespace blender::nodes::node_shader_emission_cc
|
||||||
|
|
||||||
/* node type definition */
|
/* node type definition */
|
||||||
@ -36,6 +51,7 @@ void register_node_type_sh_emission()
|
|||||||
sh_node_type_base(&ntype, SH_NODE_EMISSION, "Emission", NODE_CLASS_SHADER);
|
sh_node_type_base(&ntype, SH_NODE_EMISSION, "Emission", NODE_CLASS_SHADER);
|
||||||
ntype.declare = file_ns::node_declare;
|
ntype.declare = file_ns::node_declare;
|
||||||
ntype.gpu_fn = file_ns::node_shader_gpu_emission;
|
ntype.gpu_fn = file_ns::node_shader_gpu_emission;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,13 @@ static int node_shader_gpu_gamma(GPUMaterial *mat,
|
|||||||
{
|
{
|
||||||
return GPU_stack_link(mat, node, "node_gamma", in, out);
|
return GPU_stack_link(mat, node, "node_gamma", in, out);
|
||||||
}
|
}
|
||||||
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
NodeItem color = get_input_value("Color", NodeItem::Type::Color4);
|
||||||
|
NodeItem gamma = get_input_value("Gamma", NodeItem::Type::Float);
|
||||||
|
return color ^ gamma;
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_gamma_cc
|
} // namespace blender::nodes::node_shader_gamma_cc
|
||||||
|
|
||||||
@ -34,6 +41,7 @@ void register_node_type_sh_gamma()
|
|||||||
sh_node_type_base(&ntype, SH_NODE_GAMMA, "Gamma", NODE_CLASS_OP_COLOR);
|
sh_node_type_base(&ntype, SH_NODE_GAMMA, "Gamma", NODE_CLASS_OP_COLOR);
|
||||||
ntype.declare = file_ns::node_declare;
|
ntype.declare = file_ns::node_declare;
|
||||||
ntype.gpu_fn = file_ns::node_shader_gpu_gamma;
|
ntype.gpu_fn = file_ns::node_shader_gpu_gamma;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,30 @@ static int gpu_shader_hue_sat(GPUMaterial *mat,
|
|||||||
return GPU_stack_link(mat, node, "hue_sat", in, out);
|
return GPU_stack_link(mat, node, "hue_sat", in, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
/* TODO: implement fac */
|
||||||
|
NodeItem hue = get_input_value("Hue", NodeItem::Type::Float);
|
||||||
|
NodeItem saturation = get_input_value("Saturation", NodeItem::Type::Float);
|
||||||
|
NodeItem value = get_input_value("Value", NodeItem::Type::Float);
|
||||||
|
NodeItem fac = get_input_value("Fac", NodeItem::Type::Float);
|
||||||
|
NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
|
||||||
|
|
||||||
|
/* Modifier to follow Cycles result */
|
||||||
|
hue = hue - val(0.5f);
|
||||||
|
|
||||||
|
NodeItem combine = create_node("combine3", NodeItem::Type::Vector3);
|
||||||
|
combine.set_input("in1", hue);
|
||||||
|
combine.set_input("in2", saturation);
|
||||||
|
combine.set_input("in3", value);
|
||||||
|
|
||||||
|
NodeItem res = create_node("hsvadjust", NodeItem::Type::Color3);
|
||||||
|
res.set_input("in", color);
|
||||||
|
res.set_input("amount", combine);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_hueSatVal_cc
|
} // namespace blender::nodes::node_shader_hueSatVal_cc
|
||||||
|
|
||||||
void register_node_type_sh_hue_sat()
|
void register_node_type_sh_hue_sat()
|
||||||
@ -42,6 +66,7 @@ void register_node_type_sh_hue_sat()
|
|||||||
ntype.declare = file_ns::node_declare;
|
ntype.declare = file_ns::node_declare;
|
||||||
blender::bke::node_type_size_preset(&ntype, blender::bke::eNodeSizePreset::MIDDLE);
|
blender::bke::node_type_size_preset(&ntype, blender::bke::eNodeSizePreset::MIDDLE);
|
||||||
ntype.gpu_fn = file_ns::gpu_shader_hue_sat;
|
ntype.gpu_fn = file_ns::gpu_shader_hue_sat;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,14 @@ static int gpu_shader_invert(GPUMaterial *mat,
|
|||||||
return GPU_stack_link(mat, node, "invert", in, out);
|
return GPU_stack_link(mat, node, "invert", in, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
NodeItem fac = get_input_value("Fac", NodeItem::Type::Float);
|
||||||
|
NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
|
||||||
|
return fac.blend(color, fac.val(1.0f) - color);
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_invert_cc
|
} // namespace blender::nodes::node_shader_invert_cc
|
||||||
|
|
||||||
void register_node_type_sh_invert()
|
void register_node_type_sh_invert()
|
||||||
@ -37,6 +45,7 @@ void register_node_type_sh_invert()
|
|||||||
sh_node_type_base(&ntype, SH_NODE_INVERT, "Invert Color", NODE_CLASS_OP_COLOR);
|
sh_node_type_base(&ntype, SH_NODE_INVERT, "Invert Color", NODE_CLASS_OP_COLOR);
|
||||||
ntype.declare = file_ns::node_declare;
|
ntype.declare = file_ns::node_declare;
|
||||||
ntype.gpu_fn = file_ns::gpu_shader_invert;
|
ntype.gpu_fn = file_ns::gpu_shader_invert;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,17 @@ static int node_shader_gpu_light_falloff(GPUMaterial *mat,
|
|||||||
return GPU_stack_link(mat, node, "node_light_falloff", in, out);
|
return GPU_stack_link(mat, node, "node_light_falloff", in, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
NodeItem strength = get_input_value("Strength", NodeItem::Type::Float);
|
||||||
|
NodeItem smooth = get_input_value("Smooth", NodeItem::Type::Float);
|
||||||
|
|
||||||
|
/* This node isn't supported by MaterialX. This formula was given from OSL shader code in Cycles
|
||||||
|
* node_light_falloff.osl. Considered ray_length=1.0f. */
|
||||||
|
return strength * val(1.0f) / (smooth + val(1.0f));
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_light_falloff_cc
|
} // namespace blender::nodes::node_shader_light_falloff_cc
|
||||||
|
|
||||||
/* node type definition */
|
/* node type definition */
|
||||||
@ -37,6 +48,7 @@ void register_node_type_sh_light_falloff()
|
|||||||
ntype.declare = file_ns::node_declare;
|
ntype.declare = file_ns::node_declare;
|
||||||
blender::bke::node_type_size_preset(&ntype, blender::bke::eNodeSizePreset::MIDDLE);
|
blender::bke::node_type_size_preset(&ntype, blender::bke::eNodeSizePreset::MIDDLE);
|
||||||
ntype.gpu_fn = file_ns::node_shader_gpu_light_falloff;
|
ntype.gpu_fn = file_ns::node_shader_gpu_light_falloff;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,19 @@ static int node_shader_gpu_light_path(GPUMaterial *mat,
|
|||||||
return GPU_stack_link(mat, node, "node_light_path", in, out);
|
return GPU_stack_link(mat, node, "node_light_path", in, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
/* This node isn't supported by MaterialX. Only default values returned. */
|
||||||
|
if (STREQ(socket_out_->name, "Is Camera Ray")) {
|
||||||
|
return val(1.0f);
|
||||||
|
}
|
||||||
|
if (STREQ(socket_out_->name, "Ray Length")) {
|
||||||
|
return val(1.0f);
|
||||||
|
}
|
||||||
|
return val(0.0f);
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_light_path_cc
|
} // namespace blender::nodes::node_shader_light_path_cc
|
||||||
|
|
||||||
/* node type definition */
|
/* node type definition */
|
||||||
@ -44,6 +57,7 @@ void register_node_type_sh_light_path()
|
|||||||
sh_node_type_base(&ntype, SH_NODE_LIGHT_PATH, "Light Path", NODE_CLASS_INPUT);
|
sh_node_type_base(&ntype, SH_NODE_LIGHT_PATH, "Light Path", NODE_CLASS_INPUT);
|
||||||
ntype.declare = file_ns::node_declare;
|
ntype.declare = file_ns::node_declare;
|
||||||
ntype.gpu_fn = file_ns::node_shader_gpu_light_path;
|
ntype.gpu_fn = file_ns::node_shader_gpu_light_path;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
@ -442,6 +442,49 @@ static void sh_node_map_range_build_multi_function(NodeMultiFunctionBuilder &bui
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
/* TODO: Implement steps */
|
||||||
|
|
||||||
|
const NodeMapRange *map_range = static_cast<NodeMapRange *>(node_->storage);
|
||||||
|
NodeItem::Type type;
|
||||||
|
NodeItem value = empty();
|
||||||
|
NodeItem from_min = empty();
|
||||||
|
NodeItem from_max = empty();
|
||||||
|
NodeItem to_min = empty();
|
||||||
|
NodeItem to_max = empty();
|
||||||
|
switch (map_range->data_type) {
|
||||||
|
case CD_PROP_FLOAT:
|
||||||
|
type = NodeItem::Type::Float;
|
||||||
|
value = get_input_value("Value", type);
|
||||||
|
from_min = get_input_value(1, type);
|
||||||
|
from_max = get_input_value(2, type);
|
||||||
|
to_min = get_input_value(3, type);
|
||||||
|
to_max = get_input_value(4, type);
|
||||||
|
break;
|
||||||
|
case CD_PROP_FLOAT3:
|
||||||
|
type = NodeItem::Type::Vector3;
|
||||||
|
value = get_input_value("Vector", type);
|
||||||
|
from_min = get_input_value(7, type);
|
||||||
|
from_max = get_input_value(8, type);
|
||||||
|
to_min = get_input_value(9, type);
|
||||||
|
to_max = get_input_value(10, type);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem res = create_node("range", type);
|
||||||
|
res.set_input("in", value);
|
||||||
|
res.set_input("inlow", from_min);
|
||||||
|
res.set_input("inhigh", from_max);
|
||||||
|
res.set_input("outlow", to_min);
|
||||||
|
res.set_input("outhigh", to_max);
|
||||||
|
res.set_input("doclamp", val(bool(map_range->clamp)));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_map_range_cc
|
} // namespace blender::nodes::node_shader_map_range_cc
|
||||||
|
|
||||||
void register_node_type_sh_map_range()
|
void register_node_type_sh_map_range()
|
||||||
@ -461,5 +504,6 @@ void register_node_type_sh_map_range()
|
|||||||
ntype.gpu_fn = file_ns::gpu_shader_map_range;
|
ntype.gpu_fn = file_ns::gpu_shader_map_range;
|
||||||
ntype.build_multi_function = file_ns::sh_node_map_range_build_multi_function;
|
ntype.build_multi_function = file_ns::sh_node_map_range_build_multi_function;
|
||||||
ntype.gather_link_search_ops = file_ns::node_map_range_gather_link_searches;
|
ntype.gather_link_search_ops = file_ns::node_map_range_gather_link_searches;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
@ -177,6 +177,170 @@ static void sh_node_math_build_multi_function(NodeMultiFunctionBuilder &builder)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
CLG_LogRef *LOG_MATERIALX_SHADER = materialx::LOG_MATERIALX_SHADER;
|
||||||
|
|
||||||
|
/* TODO: finish some math operations */
|
||||||
|
NodeMathOperation op = NodeMathOperation(node_->custom1);
|
||||||
|
NodeItem res = empty();
|
||||||
|
|
||||||
|
/* Single operand operations */
|
||||||
|
NodeItem x = get_input_value(0, NodeItem::Type::Float);
|
||||||
|
/* TODO: Seems we have to use average if Vector or Color are added */
|
||||||
|
|
||||||
|
switch (op) {
|
||||||
|
case NODE_MATH_SINE:
|
||||||
|
res = x.sin();
|
||||||
|
break;
|
||||||
|
case NODE_MATH_COSINE:
|
||||||
|
res = x.cos();
|
||||||
|
break;
|
||||||
|
case NODE_MATH_TANGENT:
|
||||||
|
res = x.tan();
|
||||||
|
break;
|
||||||
|
case NODE_MATH_ARCSINE:
|
||||||
|
res = x.asin();
|
||||||
|
break;
|
||||||
|
case NODE_MATH_ARCCOSINE:
|
||||||
|
res = x.acos();
|
||||||
|
break;
|
||||||
|
case NODE_MATH_ARCTANGENT:
|
||||||
|
res = x.atan();
|
||||||
|
break;
|
||||||
|
case NODE_MATH_ROUND:
|
||||||
|
res = (x + val(0.5f)).floor();
|
||||||
|
break;
|
||||||
|
case NODE_MATH_ABSOLUTE:
|
||||||
|
res = x.abs();
|
||||||
|
break;
|
||||||
|
case NODE_MATH_FLOOR:
|
||||||
|
res = x.floor();
|
||||||
|
break;
|
||||||
|
case NODE_MATH_CEIL:
|
||||||
|
res = x.ceil();
|
||||||
|
break;
|
||||||
|
case NODE_MATH_FRACTION:
|
||||||
|
res = x % val(1.0f);
|
||||||
|
break;
|
||||||
|
case NODE_MATH_SQRT:
|
||||||
|
res = x.sqrt();
|
||||||
|
break;
|
||||||
|
case NODE_MATH_INV_SQRT:
|
||||||
|
res = val(1.0f) / x.sqrt();
|
||||||
|
break;
|
||||||
|
case NODE_MATH_SIGN:
|
||||||
|
res = x.sign();
|
||||||
|
break;
|
||||||
|
case NODE_MATH_EXPONENT:
|
||||||
|
res = x.exp();
|
||||||
|
break;
|
||||||
|
case NODE_MATH_RADIANS:
|
||||||
|
res = x * val(float(M_PI) / 180.0f);
|
||||||
|
break;
|
||||||
|
case NODE_MATH_DEGREES:
|
||||||
|
res = x * val(180.0f * float(M_1_PI));
|
||||||
|
break;
|
||||||
|
case NODE_MATH_SINH:
|
||||||
|
res = x.sinh();
|
||||||
|
break;
|
||||||
|
case NODE_MATH_COSH:
|
||||||
|
res = x.cosh();
|
||||||
|
break;
|
||||||
|
case NODE_MATH_TANH:
|
||||||
|
res = x.tanh();
|
||||||
|
break;
|
||||||
|
case NODE_MATH_TRUNC:
|
||||||
|
res = x.sign() * x.abs().floor();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: {
|
||||||
|
/* 2-operand operations */
|
||||||
|
NodeItem y = get_input_value(1, NodeItem::Type::Float);
|
||||||
|
switch (op) {
|
||||||
|
case NODE_MATH_ADD:
|
||||||
|
res = x + y;
|
||||||
|
break;
|
||||||
|
case NODE_MATH_SUBTRACT:
|
||||||
|
res = x - y;
|
||||||
|
break;
|
||||||
|
case NODE_MATH_MULTIPLY:
|
||||||
|
res = x * y;
|
||||||
|
break;
|
||||||
|
case NODE_MATH_DIVIDE:
|
||||||
|
res = x / y;
|
||||||
|
break;
|
||||||
|
case NODE_MATH_POWER:
|
||||||
|
res = x ^ y;
|
||||||
|
break;
|
||||||
|
case NODE_MATH_LOGARITHM:
|
||||||
|
res = x.ln() / y.ln();
|
||||||
|
break;
|
||||||
|
case NODE_MATH_MINIMUM:
|
||||||
|
res = x.min(y);
|
||||||
|
break;
|
||||||
|
case NODE_MATH_MAXIMUM:
|
||||||
|
res = x.max(y);
|
||||||
|
break;
|
||||||
|
case NODE_MATH_LESS_THAN:
|
||||||
|
res = x.if_else(NodeItem::CompareOp::Less, y, val(1.0f), val(0.0f));
|
||||||
|
break;
|
||||||
|
case NODE_MATH_GREATER_THAN:
|
||||||
|
res = x.if_else(NodeItem::CompareOp::Greater, y, val(1.0f), val(0.0f));
|
||||||
|
break;
|
||||||
|
case NODE_MATH_MODULO:
|
||||||
|
res = x % y;
|
||||||
|
break;
|
||||||
|
case NODE_MATH_ARCTAN2:
|
||||||
|
res = x.atan2(y);
|
||||||
|
break;
|
||||||
|
case NODE_MATH_SNAP:
|
||||||
|
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||||
|
break;
|
||||||
|
case NODE_MATH_PINGPONG:
|
||||||
|
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||||
|
break;
|
||||||
|
case NODE_MATH_FLOORED_MODULO:
|
||||||
|
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: {
|
||||||
|
/* 3-operand operations */
|
||||||
|
NodeItem z = get_input_value(2, NodeItem::Type::Float);
|
||||||
|
switch (op) {
|
||||||
|
case NODE_MATH_WRAP:
|
||||||
|
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||||
|
break;
|
||||||
|
case NODE_MATH_COMPARE:
|
||||||
|
res = z.if_else(NodeItem::CompareOp::Less, (x - y).abs(), val(1.0f), val(0.0f));
|
||||||
|
break;
|
||||||
|
case NODE_MATH_MULTIPLY_ADD:
|
||||||
|
res = x * y + z;
|
||||||
|
break;
|
||||||
|
case NODE_MATH_SMOOTH_MIN:
|
||||||
|
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||||
|
break;
|
||||||
|
case NODE_MATH_SMOOTH_MAX:
|
||||||
|
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool clamp_output = node_->custom2 != 0;
|
||||||
|
if (clamp_output && res) {
|
||||||
|
res = res.clamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_math_cc
|
} // namespace blender::nodes::node_shader_math_cc
|
||||||
|
|
||||||
void register_node_type_sh_math()
|
void register_node_type_sh_math()
|
||||||
@ -192,6 +356,7 @@ void register_node_type_sh_math()
|
|||||||
ntype.updatefunc = node_math_update;
|
ntype.updatefunc = node_math_update;
|
||||||
ntype.build_multi_function = file_ns::sh_node_math_build_multi_function;
|
ntype.build_multi_function = file_ns::sh_node_math_build_multi_function;
|
||||||
ntype.gather_link_search_ops = file_ns::sh_node_math_gather_link_searches;
|
ntype.gather_link_search_ops = file_ns::sh_node_math_gather_link_searches;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
@ -150,6 +150,13 @@ static void sh_node_mix_rgb_build_multi_function(NodeMultiFunctionBuilder &build
|
|||||||
builder.construct_and_set_matching_fn<MixRGBFunction>(clamp, mix_type);
|
builder.construct_and_set_matching_fn<MixRGBFunction>(clamp, mix_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
/* TODO: Implement */
|
||||||
|
return empty();
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_mix_rgb_cc
|
} // namespace blender::nodes::node_shader_mix_rgb_cc
|
||||||
|
|
||||||
void register_node_type_sh_mix_rgb()
|
void register_node_type_sh_mix_rgb()
|
||||||
@ -165,5 +172,6 @@ void register_node_type_sh_mix_rgb()
|
|||||||
ntype.build_multi_function = file_ns::sh_node_mix_rgb_build_multi_function;
|
ntype.build_multi_function = file_ns::sh_node_mix_rgb_build_multi_function;
|
||||||
ntype.gather_link_search_ops = nullptr;
|
ntype.gather_link_search_ops = nullptr;
|
||||||
ntype.gather_add_node_search_ops = nullptr;
|
ntype.gather_add_node_search_ops = nullptr;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,45 @@ static int node_shader_gpu_mix_shader(GPUMaterial *mat,
|
|||||||
return GPU_stack_link(mat, node, "node_mix_shader", in, out);
|
return GPU_stack_link(mat, node, "node_mix_shader", in, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
NodeItem res = empty();
|
||||||
|
switch (to_type_) {
|
||||||
|
case NodeItem::Type::BSDF:
|
||||||
|
case NodeItem::Type::EDF: {
|
||||||
|
NodeItem fac = get_input_value(0, NodeItem::Type::Float);
|
||||||
|
NodeItem shader1 = get_input_link(1, to_type_);
|
||||||
|
NodeItem shader2 = get_input_link(2, to_type_);
|
||||||
|
|
||||||
|
if (shader1 && !shader2) {
|
||||||
|
res = shader1 * (val(1.0f) - fac);
|
||||||
|
}
|
||||||
|
else if (!shader1 && shader2) {
|
||||||
|
res = shader2 * fac;
|
||||||
|
}
|
||||||
|
else if (shader1 && shader2) {
|
||||||
|
res = create_node("mix", to_type_);
|
||||||
|
res.set_input("fg", shader1);
|
||||||
|
res.set_input("bg", shader2);
|
||||||
|
res.set_input("mix", fac);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NodeItem::Type::SurfaceShader: {
|
||||||
|
/* SurfaceShaders can't be mixed, returning the first one connected */
|
||||||
|
res = get_input_link(1, NodeItem::Type::SurfaceShader);
|
||||||
|
if (!res) {
|
||||||
|
res = get_input_link(2, NodeItem::Type::SurfaceShader);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_mix_shader_cc
|
} // namespace blender::nodes::node_shader_mix_shader_cc
|
||||||
|
|
||||||
/* node type definition */
|
/* node type definition */
|
||||||
@ -35,6 +74,7 @@ void register_node_type_sh_mix_shader()
|
|||||||
sh_node_type_base(&ntype, SH_NODE_MIX_SHADER, "Mix Shader", NODE_CLASS_SHADER);
|
sh_node_type_base(&ntype, SH_NODE_MIX_SHADER, "Mix Shader", NODE_CLASS_SHADER);
|
||||||
ntype.declare = file_ns::node_declare;
|
ntype.declare = file_ns::node_declare;
|
||||||
ntype.gpu_fn = file_ns::node_shader_gpu_mix_shader;
|
ntype.gpu_fn = file_ns::node_shader_gpu_mix_shader;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
@ -122,6 +122,38 @@ static int gpu_shader_normal_map(GPUMaterial *mat,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
NodeShaderNormalMap *normal_map_node = static_cast<NodeShaderNormalMap *>(node_->storage);
|
||||||
|
NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
|
||||||
|
NodeItem strength = get_input_value("Strength", NodeItem::Type::Float);
|
||||||
|
|
||||||
|
std::string space;
|
||||||
|
switch (normal_map_node->space) {
|
||||||
|
case SHD_SPACE_TANGENT:
|
||||||
|
space = "tangent";
|
||||||
|
break;
|
||||||
|
case SHD_SPACE_OBJECT:
|
||||||
|
case SHD_SPACE_BLENDER_OBJECT:
|
||||||
|
space = "object";
|
||||||
|
break;
|
||||||
|
case SHD_SPACE_WORLD:
|
||||||
|
case SHD_SPACE_BLENDER_WORLD:
|
||||||
|
/* World isn't supported, tangent space will be used */
|
||||||
|
space = "tangent";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem res = create_node("normalmap", NodeItem::Type::Vector3);
|
||||||
|
res.set_input("in", color);
|
||||||
|
res.set_input("scale", strength);
|
||||||
|
res.set_input("space", val(space));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_normal_map_cc
|
} // namespace blender::nodes::node_shader_normal_map_cc
|
||||||
|
|
||||||
/* node type definition */
|
/* node type definition */
|
||||||
@ -139,6 +171,7 @@ void register_node_type_sh_normal_map()
|
|||||||
node_type_storage(
|
node_type_storage(
|
||||||
&ntype, "NodeShaderNormalMap", node_free_standard_storage, node_copy_standard_storage);
|
&ntype, "NodeShaderNormalMap", node_free_standard_storage, node_copy_standard_storage);
|
||||||
ntype.gpu_fn = file_ns::gpu_shader_normal_map;
|
ntype.gpu_fn = file_ns::gpu_shader_normal_map;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,29 @@ static int node_shader_gpu_output_material(GPUMaterial *mat,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
NodeItem bsdf = get_input_link("Surface", NodeItem::Type::BSDF);
|
||||||
|
NodeItem edf = get_input_link("Surface", NodeItem::Type::EDF);
|
||||||
|
NodeItem surface = empty();
|
||||||
|
if (bsdf || edf) {
|
||||||
|
surface = create_node("surface", NodeItem::Type::SurfaceShader);
|
||||||
|
if (bsdf) {
|
||||||
|
surface.set_input("bsdf", bsdf);
|
||||||
|
}
|
||||||
|
if (edf) {
|
||||||
|
surface.set_input("edf", edf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
surface = get_input_link("Surface", NodeItem::Type::SurfaceShader);
|
||||||
|
}
|
||||||
|
NodeItem res = create_node("surfacematerial", NodeItem::Type::Material);
|
||||||
|
res.set_input("surfaceshader", surface);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_output_material_cc
|
} // namespace blender::nodes::node_shader_output_material_cc
|
||||||
|
|
||||||
/* node type definition */
|
/* node type definition */
|
||||||
@ -56,6 +79,7 @@ void register_node_type_sh_output_material()
|
|||||||
ntype.declare = file_ns::node_declare;
|
ntype.declare = file_ns::node_declare;
|
||||||
ntype.add_ui_poll = object_shader_nodes_poll;
|
ntype.add_ui_poll = object_shader_nodes_poll;
|
||||||
ntype.gpu_fn = file_ns::node_shader_gpu_output_material;
|
ntype.gpu_fn = file_ns::node_shader_gpu_output_material;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
ntype.no_muting = true;
|
ntype.no_muting = true;
|
||||||
|
|
||||||
|
@ -27,6 +27,16 @@ static int gpu_shader_rgbtobw(GPUMaterial *mat,
|
|||||||
return GPU_stack_link(mat, node, "rgbtobw", in, out);
|
return GPU_stack_link(mat, node, "rgbtobw", in, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
NodeItem color = get_input_value("Color", NodeItem::Type::Color4);
|
||||||
|
|
||||||
|
NodeItem res = create_node("luminance", NodeItem::Type::Color4);
|
||||||
|
res.set_input("in", color);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_rgb_to_bw_cc
|
} // namespace blender::nodes::node_shader_rgb_to_bw_cc
|
||||||
|
|
||||||
void register_node_type_sh_rgbtobw()
|
void register_node_type_sh_rgbtobw()
|
||||||
@ -38,6 +48,7 @@ void register_node_type_sh_rgbtobw()
|
|||||||
sh_node_type_base(&ntype, SH_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTER);
|
sh_node_type_base(&ntype, SH_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTER);
|
||||||
ntype.declare = file_ns::sh_node_rgbtobw_declare;
|
ntype.declare = file_ns::sh_node_rgbtobw_declare;
|
||||||
ntype.gpu_fn = file_ns::gpu_shader_rgbtobw;
|
ntype.gpu_fn = file_ns::gpu_shader_rgbtobw;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
@ -68,6 +68,31 @@ static int gpu_shader_sepcolor(GPUMaterial *mat,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
int mode = static_cast<NodeCombSepColor *>(node_->storage)->mode;
|
||||||
|
NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
|
||||||
|
|
||||||
|
NodeItem convert = empty();
|
||||||
|
switch (mode) {
|
||||||
|
case NODE_COMBSEP_COLOR_RGB:
|
||||||
|
convert = color;
|
||||||
|
break;
|
||||||
|
case NODE_COMBSEP_COLOR_HSV:
|
||||||
|
case NODE_COMBSEP_COLOR_HSL:
|
||||||
|
/* NOTE: HSL is unsupported color model, using HSV instead */
|
||||||
|
convert = create_node("rgbtohsv", NodeItem::Type::Color3);
|
||||||
|
convert.set_input("in", color);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = STREQ(socket_out_->name, "Red") ? 0 : STREQ(socket_out_->name, "Green") ? 1 : 2;
|
||||||
|
return convert.extract(index);
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_separate_color_cc
|
} // namespace blender::nodes::node_shader_separate_color_cc
|
||||||
|
|
||||||
void register_node_type_sh_sepcolor()
|
void register_node_type_sh_sepcolor()
|
||||||
@ -83,6 +108,7 @@ void register_node_type_sh_sepcolor()
|
|||||||
node_type_storage(
|
node_type_storage(
|
||||||
&ntype, "NodeCombSepColor", node_free_standard_storage, node_copy_standard_storage);
|
&ntype, "NodeCombSepColor", node_free_standard_storage, node_copy_standard_storage);
|
||||||
ntype.gpu_fn = file_ns::gpu_shader_sepcolor;
|
ntype.gpu_fn = file_ns::gpu_shader_sepcolor;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
@ -136,6 +162,36 @@ static int gpu_shader_combcolor(GPUMaterial *mat,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
int mode = static_cast<NodeCombSepColor *>(node_->storage)->mode;
|
||||||
|
NodeItem red = get_input_value("Red", NodeItem::Type::Float);
|
||||||
|
NodeItem green = get_input_value("Green", NodeItem::Type::Float);
|
||||||
|
NodeItem blue = get_input_value("Blue", NodeItem::Type::Float);
|
||||||
|
|
||||||
|
NodeItem combine = create_node("combine3", NodeItem::Type::Color3);
|
||||||
|
combine.set_input("in1", red);
|
||||||
|
combine.set_input("in2", green);
|
||||||
|
combine.set_input("in3", blue);
|
||||||
|
|
||||||
|
NodeItem res = empty();
|
||||||
|
switch (mode) {
|
||||||
|
case NODE_COMBSEP_COLOR_RGB:
|
||||||
|
res = combine;
|
||||||
|
break;
|
||||||
|
case NODE_COMBSEP_COLOR_HSV:
|
||||||
|
case NODE_COMBSEP_COLOR_HSL:
|
||||||
|
/* NOTE: HSL is unsupported color model, using HSV instead */
|
||||||
|
res = create_node("hsvtorgb", NodeItem::Type::Color3);
|
||||||
|
res.set_input("in", combine);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_combine_color_cc
|
} // namespace blender::nodes::node_shader_combine_color_cc
|
||||||
|
|
||||||
void register_node_type_sh_combcolor()
|
void register_node_type_sh_combcolor()
|
||||||
@ -151,6 +207,7 @@ void register_node_type_sh_combcolor()
|
|||||||
node_type_storage(
|
node_type_storage(
|
||||||
&ntype, "NodeCombSepColor", node_free_standard_storage, node_copy_standard_storage);
|
&ntype, "NodeCombSepColor", node_free_standard_storage, node_copy_standard_storage);
|
||||||
ntype.gpu_fn = file_ns::gpu_shader_combcolor;
|
ntype.gpu_fn = file_ns::gpu_shader_combcolor;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
#include "NOD_multi_function.hh"
|
#include "NOD_multi_function.hh"
|
||||||
|
|
||||||
namespace blender::nodes::node_shader_sepcomb_xyz_cc {
|
namespace blender::nodes::node_shader_sepcomb_xyz_cc::sep {
|
||||||
|
|
||||||
static void sh_node_sepxyz_declare(NodeDeclarationBuilder &b)
|
static void sh_node_sepxyz_declare(NodeDeclarationBuilder &b)
|
||||||
{
|
{
|
||||||
@ -90,11 +90,19 @@ static void sh_node_sepxyz_build_multi_function(NodeMultiFunctionBuilder &builde
|
|||||||
builder.set_matching_fn(separate_fn);
|
builder.set_matching_fn(separate_fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_sepcomb_xyz_cc
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
NodeItem vector = get_input_value("Vector", NodeItem::Type::Vector3);
|
||||||
|
int index = STREQ(socket_out_->name, "X") ? 0 : STREQ(socket_out_->name, "Y") ? 1 : 2;
|
||||||
|
return vector.extract(index);
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
|
} // namespace blender::nodes::node_shader_sepcomb_xyz_cc::sep
|
||||||
|
|
||||||
void register_node_type_sh_sepxyz()
|
void register_node_type_sh_sepxyz()
|
||||||
{
|
{
|
||||||
namespace file_ns = blender::nodes::node_shader_sepcomb_xyz_cc;
|
namespace file_ns = blender::nodes::node_shader_sepcomb_xyz_cc::sep;
|
||||||
|
|
||||||
static bNodeType ntype;
|
static bNodeType ntype;
|
||||||
|
|
||||||
@ -102,11 +110,12 @@ void register_node_type_sh_sepxyz()
|
|||||||
ntype.declare = file_ns::sh_node_sepxyz_declare;
|
ntype.declare = file_ns::sh_node_sepxyz_declare;
|
||||||
ntype.gpu_fn = file_ns::gpu_shader_sepxyz;
|
ntype.gpu_fn = file_ns::gpu_shader_sepxyz;
|
||||||
ntype.build_multi_function = file_ns::sh_node_sepxyz_build_multi_function;
|
ntype.build_multi_function = file_ns::sh_node_sepxyz_build_multi_function;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace blender::nodes::node_shader_sepcomb_xyz_cc {
|
namespace blender::nodes::node_shader_sepcomb_xyz_cc::comb {
|
||||||
|
|
||||||
static void sh_node_combxyz_declare(NodeDeclarationBuilder &b)
|
static void sh_node_combxyz_declare(NodeDeclarationBuilder &b)
|
||||||
{
|
{
|
||||||
@ -135,11 +144,25 @@ static void sh_node_combxyz_build_multi_function(NodeMultiFunctionBuilder &build
|
|||||||
builder.set_matching_fn(fn);
|
builder.set_matching_fn(fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_sepcomb_xyz_cc
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
NodeItem x = get_input_value("X", NodeItem::Type::Float);
|
||||||
|
NodeItem y = get_input_value("Y", NodeItem::Type::Float);
|
||||||
|
NodeItem z = get_input_value("Z", NodeItem::Type::Float);
|
||||||
|
|
||||||
|
NodeItem res = create_node("combine3", NodeItem::Type::Vector3);
|
||||||
|
res.set_input("in1", x);
|
||||||
|
res.set_input("in2", y);
|
||||||
|
res.set_input("in3", z);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
|
} // namespace blender::nodes::node_shader_sepcomb_xyz_cc::comb
|
||||||
|
|
||||||
void register_node_type_sh_combxyz()
|
void register_node_type_sh_combxyz()
|
||||||
{
|
{
|
||||||
namespace file_ns = blender::nodes::node_shader_sepcomb_xyz_cc;
|
namespace file_ns = blender::nodes::node_shader_sepcomb_xyz_cc::comb;
|
||||||
|
|
||||||
static bNodeType ntype;
|
static bNodeType ntype;
|
||||||
|
|
||||||
@ -147,6 +170,7 @@ void register_node_type_sh_combxyz()
|
|||||||
ntype.declare = file_ns::sh_node_combxyz_declare;
|
ntype.declare = file_ns::sh_node_combxyz_declare;
|
||||||
ntype.gpu_fn = file_ns::gpu_shader_combxyz;
|
ntype.gpu_fn = file_ns::gpu_shader_combxyz;
|
||||||
ntype.build_multi_function = file_ns::sh_node_combxyz_build_multi_function;
|
ntype.build_multi_function = file_ns::sh_node_combxyz_build_multi_function;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
@ -102,6 +102,26 @@ static void sh_node_tex_checker_build_multi_function(NodeMultiFunctionBuilder &b
|
|||||||
builder.set_matching_fn(fn);
|
builder.set_matching_fn(fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector2);
|
||||||
|
if (!vector) {
|
||||||
|
vector = texcoord_node();
|
||||||
|
}
|
||||||
|
NodeItem value1 = val(1.0f);
|
||||||
|
NodeItem value2 = val(0.0f);
|
||||||
|
if (STREQ(socket_out_->name, "Color")) {
|
||||||
|
value1 = get_input_value("Color1", NodeItem::Type::Color4);
|
||||||
|
value2 = get_input_value("Color2", NodeItem::Type::Color4);
|
||||||
|
}
|
||||||
|
NodeItem scale = get_input_value("Scale", NodeItem::Type::Float);
|
||||||
|
|
||||||
|
vector = (vector * scale) % val(2.0f);
|
||||||
|
return (vector.extract(0).floor() + vector.extract(1).floor())
|
||||||
|
.if_else(NodeItem::CompareOp::Eq, val(1.0f), value1, value2);
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_tex_checker_cc
|
} // namespace blender::nodes::node_shader_tex_checker_cc
|
||||||
|
|
||||||
void register_node_type_sh_tex_checker()
|
void register_node_type_sh_tex_checker()
|
||||||
@ -117,6 +137,7 @@ void register_node_type_sh_tex_checker()
|
|||||||
&ntype, "NodeTexChecker", node_free_standard_storage, node_copy_standard_storage);
|
&ntype, "NodeTexChecker", node_free_standard_storage, node_copy_standard_storage);
|
||||||
ntype.gpu_fn = file_ns::node_shader_gpu_tex_checker;
|
ntype.gpu_fn = file_ns::node_shader_gpu_tex_checker;
|
||||||
ntype.build_multi_function = file_ns::sh_node_tex_checker_build_multi_function;
|
ntype.build_multi_function = file_ns::sh_node_tex_checker_build_multi_function;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
@ -127,6 +127,13 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
/* TODO: Implement */
|
||||||
|
return empty();
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_tex_environment_cc
|
} // namespace blender::nodes::node_shader_tex_environment_cc
|
||||||
|
|
||||||
/* node type definition */
|
/* node type definition */
|
||||||
@ -144,6 +151,7 @@ void register_node_type_sh_tex_environment()
|
|||||||
ntype.gpu_fn = file_ns::node_shader_gpu_tex_environment;
|
ntype.gpu_fn = file_ns::node_shader_gpu_tex_environment;
|
||||||
ntype.labelfunc = node_image_label;
|
ntype.labelfunc = node_image_label;
|
||||||
blender::bke::node_type_size_preset(&ntype, blender::bke::eNodeSizePreset::LARGE);
|
blender::bke::node_type_size_preset(&ntype, blender::bke::eNodeSizePreset::LARGE);
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,10 @@
|
|||||||
|
|
||||||
#include "IMB_colormanagement.h"
|
#include "IMB_colormanagement.h"
|
||||||
|
|
||||||
|
#include "hydra/image.h"
|
||||||
|
|
||||||
|
#include "DEG_depsgraph_query.h"
|
||||||
|
|
||||||
namespace blender::nodes::node_shader_tex_image_cc {
|
namespace blender::nodes::node_shader_tex_image_cc {
|
||||||
|
|
||||||
static void sh_node_tex_image_declare(NodeDeclarationBuilder &b)
|
static void sh_node_tex_image_declare(NodeDeclarationBuilder &b)
|
||||||
@ -172,6 +176,75 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
NodeItem res = val(MaterialX::Color4(1.0f, 0.0f, 1.0f, 1.0f));
|
||||||
|
|
||||||
|
Image *image = (Image *)node_->id;
|
||||||
|
if (image) {
|
||||||
|
NodeTexImage *tex_image = static_cast<NodeTexImage *>(node_->storage);
|
||||||
|
Scene *scene = DEG_get_input_scene(depsgraph_);
|
||||||
|
Main *bmain = DEG_get_bmain(depsgraph_);
|
||||||
|
|
||||||
|
/* TODO: What if Blender built without Hydra? Also io::hydra::cache_or_get_image_file contains
|
||||||
|
* pretty general code, so could be moved from bf_usd project. */
|
||||||
|
std::string image_path = io::hydra::cache_or_get_image_file(
|
||||||
|
bmain, scene, image, &tex_image->iuser);
|
||||||
|
|
||||||
|
NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector2);
|
||||||
|
if (!vector) {
|
||||||
|
vector = texcoord_node();
|
||||||
|
}
|
||||||
|
/* TODO: add math to vector depending of tex_image->projection */
|
||||||
|
|
||||||
|
std::string filtertype;
|
||||||
|
switch (tex_image->interpolation) {
|
||||||
|
case SHD_INTERP_LINEAR:
|
||||||
|
filtertype = "linear";
|
||||||
|
break;
|
||||||
|
case SHD_INTERP_CLOSEST:
|
||||||
|
filtertype = "closest";
|
||||||
|
break;
|
||||||
|
case SHD_INTERP_CUBIC:
|
||||||
|
case SHD_INTERP_SMART:
|
||||||
|
filtertype = "cubic";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
std::string addressmode;
|
||||||
|
switch (tex_image->extension) {
|
||||||
|
case SHD_IMAGE_EXTENSION_REPEAT:
|
||||||
|
addressmode = "periodic";
|
||||||
|
break;
|
||||||
|
case SHD_IMAGE_EXTENSION_EXTEND:
|
||||||
|
addressmode = "clamp";
|
||||||
|
break;
|
||||||
|
case SHD_IMAGE_EXTENSION_CLIP:
|
||||||
|
addressmode = "constant";
|
||||||
|
break;
|
||||||
|
case SHD_IMAGE_EXTENSION_MIRROR:
|
||||||
|
addressmode = "mirror";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
res = create_node("image", NodeItem::Type::Color4);
|
||||||
|
res.set_input("file", image_path, NodeItem::Type::Filename);
|
||||||
|
res.set_input("texcoord", vector);
|
||||||
|
res.set_input("filtertype", val(filtertype));
|
||||||
|
res.set_input("uaddressmode", val(addressmode));
|
||||||
|
res.set_input("vaddressmode", val(addressmode));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (STREQ(socket_out_->name, "Alpha")) {
|
||||||
|
res = res.extract(3);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_tex_image_cc
|
} // namespace blender::nodes::node_shader_tex_image_cc
|
||||||
|
|
||||||
void register_node_type_sh_tex_image()
|
void register_node_type_sh_tex_image()
|
||||||
@ -188,6 +261,7 @@ void register_node_type_sh_tex_image()
|
|||||||
ntype.gpu_fn = file_ns::node_shader_gpu_tex_image;
|
ntype.gpu_fn = file_ns::node_shader_gpu_tex_image;
|
||||||
ntype.labelfunc = node_image_label;
|
ntype.labelfunc = node_image_label;
|
||||||
blender::bke::node_type_size_preset(&ntype, blender::bke::eNodeSizePreset::LARGE);
|
blender::bke::node_type_size_preset(&ntype, blender::bke::eNodeSizePreset::LARGE);
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
@ -257,6 +257,25 @@ static void sh_node_noise_build_multi_function(NodeMultiFunctionBuilder &builder
|
|||||||
builder.construct_and_set_matching_fn<NoiseFunction>(storage.dimensions, storage.normalize);
|
builder.construct_and_set_matching_fn<NoiseFunction>(storage.dimensions, storage.normalize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
NodeItem scale = get_input_value("Scale", NodeItem::Type::Float);
|
||||||
|
NodeItem detail = get_input_value("Detail", NodeItem::Type::Float);
|
||||||
|
NodeItem lacunarity = get_input_value("Lacunarity", NodeItem::Type::Float);
|
||||||
|
|
||||||
|
NodeItem position = create_node("position", NodeItem::Type::Vector3);
|
||||||
|
position = position * scale;
|
||||||
|
|
||||||
|
NodeItem res = create_node("fractal3d", NodeItem::Type::Color3);
|
||||||
|
res.set_input("position", position);
|
||||||
|
if (detail.value) {
|
||||||
|
res.set_input("octaves", val(int(detail.value->asA<float>())));
|
||||||
|
}
|
||||||
|
res.set_input("lacunarity", lacunarity);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_tex_noise_cc
|
} // namespace blender::nodes::node_shader_tex_noise_cc
|
||||||
|
|
||||||
void register_node_type_sh_tex_noise()
|
void register_node_type_sh_tex_noise()
|
||||||
@ -274,6 +293,7 @@ void register_node_type_sh_tex_noise()
|
|||||||
ntype.gpu_fn = file_ns::node_shader_gpu_tex_noise;
|
ntype.gpu_fn = file_ns::node_shader_gpu_tex_noise;
|
||||||
ntype.updatefunc = file_ns::node_shader_update_tex_noise;
|
ntype.updatefunc = file_ns::node_shader_update_tex_noise;
|
||||||
ntype.build_multi_function = file_ns::sh_node_noise_build_multi_function;
|
ntype.build_multi_function = file_ns::sh_node_noise_build_multi_function;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
@ -316,6 +316,121 @@ static void sh_node_vector_math_build_multi_function(NodeMultiFunctionBuilder &b
|
|||||||
builder.set_matching_fn(fn);
|
builder.set_matching_fn(fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
|
{
|
||||||
|
CLG_LogRef *LOG_MATERIALX_SHADER = materialx::LOG_MATERIALX_SHADER;
|
||||||
|
|
||||||
|
/* TODO: finish some math operations */
|
||||||
|
auto op = node_->custom1;
|
||||||
|
NodeItem res = empty();
|
||||||
|
|
||||||
|
/* Single operand operations */
|
||||||
|
NodeItem x = get_input_value(0, NodeItem::Type::Vector3);
|
||||||
|
switch (op) {
|
||||||
|
case NODE_VECTOR_MATH_SINE:
|
||||||
|
res = x.sin();
|
||||||
|
break;
|
||||||
|
case NODE_VECTOR_MATH_COSINE:
|
||||||
|
res = x.cos();
|
||||||
|
break;
|
||||||
|
case NODE_VECTOR_MATH_TANGENT:
|
||||||
|
res = x.tan();
|
||||||
|
break;
|
||||||
|
case NODE_VECTOR_MATH_ABSOLUTE:
|
||||||
|
res = x.abs();
|
||||||
|
break;
|
||||||
|
case NODE_VECTOR_MATH_FLOOR:
|
||||||
|
res = x.floor();
|
||||||
|
break;
|
||||||
|
case NODE_VECTOR_MATH_CEIL:
|
||||||
|
res = x.ceil();
|
||||||
|
break;
|
||||||
|
case NODE_VECTOR_MATH_FRACTION:
|
||||||
|
res = x % val(1.0f);
|
||||||
|
break;
|
||||||
|
case NODE_VECTOR_MATH_LENGTH:
|
||||||
|
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||||
|
break;
|
||||||
|
case NODE_VECTOR_MATH_NORMALIZE:
|
||||||
|
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: {
|
||||||
|
/* 2-operand operations */
|
||||||
|
NodeItem y = get_input_value(1, NodeItem::Type::Vector3);
|
||||||
|
switch (op) {
|
||||||
|
case NODE_VECTOR_MATH_ADD:
|
||||||
|
res = x + y;
|
||||||
|
break;
|
||||||
|
case NODE_VECTOR_MATH_SUBTRACT:
|
||||||
|
res = x - y;
|
||||||
|
break;
|
||||||
|
case NODE_VECTOR_MATH_MULTIPLY:
|
||||||
|
res = x * y;
|
||||||
|
break;
|
||||||
|
case NODE_VECTOR_MATH_DIVIDE:
|
||||||
|
res = x / y;
|
||||||
|
break;
|
||||||
|
case NODE_VECTOR_MATH_MINIMUM:
|
||||||
|
res = x.min(y);
|
||||||
|
break;
|
||||||
|
case NODE_VECTOR_MATH_MAXIMUM:
|
||||||
|
res = x.max(y);
|
||||||
|
break;
|
||||||
|
case NODE_VECTOR_MATH_MODULO:
|
||||||
|
res = x % y;
|
||||||
|
break;
|
||||||
|
case NODE_VECTOR_MATH_SNAP:
|
||||||
|
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||||
|
break;
|
||||||
|
case NODE_VECTOR_MATH_CROSS_PRODUCT:
|
||||||
|
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||||
|
break;
|
||||||
|
case NODE_VECTOR_MATH_DOT_PRODUCT:
|
||||||
|
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||||
|
break;
|
||||||
|
case NODE_VECTOR_MATH_PROJECT:
|
||||||
|
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||||
|
break;
|
||||||
|
case NODE_VECTOR_MATH_REFLECT:
|
||||||
|
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||||
|
break;
|
||||||
|
case NODE_VECTOR_MATH_DISTANCE:
|
||||||
|
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||||
|
break;
|
||||||
|
case NODE_VECTOR_MATH_SCALE:
|
||||||
|
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: {
|
||||||
|
/* 3-operand operations */
|
||||||
|
NodeItem z = get_input_value(2, NodeItem::Type::Vector3);
|
||||||
|
switch (op) {
|
||||||
|
case NODE_VECTOR_MATH_MULTIPLY_ADD:
|
||||||
|
res = x * y + z;
|
||||||
|
break;
|
||||||
|
case NODE_VECTOR_MATH_REFRACT:
|
||||||
|
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||||
|
break;
|
||||||
|
case NODE_VECTOR_MATH_FACEFORWARD:
|
||||||
|
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||||
|
break;
|
||||||
|
case NODE_VECTOR_MATH_WRAP:
|
||||||
|
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
NODE_SHADER_MATERIALX_END
|
||||||
|
|
||||||
} // namespace blender::nodes::node_shader_vector_math_cc
|
} // namespace blender::nodes::node_shader_vector_math_cc
|
||||||
|
|
||||||
void register_node_type_sh_vect_math()
|
void register_node_type_sh_vect_math()
|
||||||
@ -332,6 +447,7 @@ void register_node_type_sh_vect_math()
|
|||||||
ntype.updatefunc = file_ns::node_shader_update_vector_math;
|
ntype.updatefunc = file_ns::node_shader_update_vector_math;
|
||||||
ntype.build_multi_function = file_ns::sh_node_vector_math_build_multi_function;
|
ntype.build_multi_function = file_ns::sh_node_vector_math_build_multi_function;
|
||||||
ntype.gather_link_search_ops = file_ns::sh_node_vector_math_gather_link_searches;
|
ntype.gather_link_search_ops = file_ns::sh_node_vector_math_gather_link_searches;
|
||||||
|
ntype.materialx_fn = file_ns::node_shader_materialx;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user