Add Chromium-only Blender WebEngine parity work

This commit is contained in:
mes123456
2026-08-12 04:47:48 -04:00
commit 9fd26010f6
18225 changed files with 11622124 additions and 0 deletions

View File

@@ -0,0 +1,68 @@
# SPDX-FileCopyrightText: 2023 Blender Authors
#
# SPDX-License-Identifier: GPL-2.0-or-later
set(INC
.
..
../intern
../../editors/include
../../makesrna
# RNA_prototypes.hh
${CMAKE_BINARY_DIR}/source/blender/makesrna
)
set(INC_SYS
)
set(SRC
nodes/node_texture_at.cc
nodes/node_texture_bricks.cc
nodes/node_texture_checker.cc
nodes/node_texture_combine_color.cc
nodes/node_texture_common.cc
nodes/node_texture_coord.cc
nodes/node_texture_curves.cc
nodes/node_texture_distance.cc
nodes/node_texture_hueSatVal.cc
nodes/node_texture_image.cc
nodes/node_texture_invert.cc
nodes/node_texture_math.cc
nodes/node_texture_mixRgb.cc
nodes/node_texture_output.cc
nodes/node_texture_proc.cc
nodes/node_texture_rotate.cc
nodes/node_texture_scale.cc
nodes/node_texture_separate_color.cc
nodes/node_texture_texture.cc
nodes/node_texture_translate.cc
nodes/node_texture_valToNor.cc
nodes/node_texture_valToRgb.cc
nodes/node_texture_viewer.cc
node_texture_register.cc
node_texture_tree.cc
node_texture_util.cc
node_texture_register.hh
node_texture_util.hh
)
set(LIB
PRIVATE bf::blenkernel
PRIVATE bf::blenlib
PRIVATE bf::blentranslation
PRIVATE bf::bmesh
PRIVATE bf::depsgraph
PRIVATE bf::dna
PRIVATE bf::imbuf
PRIVATE bf::intern::guardedalloc
bf_nodes
PRIVATE bf::render
PRIVATE bf::windowmanager
)
blender_add_lib(bf_nodes_texture "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
# RNA_prototypes.hh
add_dependencies(bf_nodes_texture bf_rna)

View File

@@ -0,0 +1,52 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "NOD_register.hh"
#include "node_texture_register.hh"
namespace blender {
void register_texture_nodes()
{
register_node_tree_type_tex();
register_node_type_tex_group();
register_node_type_tex_at();
register_node_type_tex_bricks();
register_node_type_tex_checker();
register_node_type_tex_combine_color();
register_node_type_tex_coord();
register_node_type_tex_curve_rgb();
register_node_type_tex_curve_time();
register_node_type_tex_distance();
register_node_type_tex_hue_sat();
register_node_type_tex_image();
register_node_type_tex_invert();
register_node_type_tex_math();
register_node_type_tex_mix_rgb();
register_node_type_tex_output();
register_node_type_tex_proc_blend();
register_node_type_tex_proc_clouds();
register_node_type_tex_proc_distnoise();
register_node_type_tex_proc_magic();
register_node_type_tex_proc_marble();
register_node_type_tex_proc_musgrave();
register_node_type_tex_proc_noise();
register_node_type_tex_proc_stucci();
register_node_type_tex_proc_voronoi();
register_node_type_tex_proc_wood();
register_node_type_tex_rgbtobw();
register_node_type_tex_rotate();
register_node_type_tex_scale();
register_node_type_tex_separate_color();
register_node_type_tex_texture();
register_node_type_tex_translate();
register_node_type_tex_valtonor();
register_node_type_tex_valtorgb();
register_node_type_tex_viewer();
}
} // namespace blender

View File

@@ -0,0 +1,47 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
namespace blender {
void register_node_tree_type_tex();
void register_node_type_tex_group();
void register_node_type_tex_at();
void register_node_type_tex_bricks();
void register_node_type_tex_checker();
void register_node_type_tex_combine_color();
void register_node_type_tex_coord();
void register_node_type_tex_curve_rgb();
void register_node_type_tex_curve_time();
void register_node_type_tex_distance();
void register_node_type_tex_hue_sat();
void register_node_type_tex_image();
void register_node_type_tex_invert();
void register_node_type_tex_math();
void register_node_type_tex_mix_rgb();
void register_node_type_tex_output();
void register_node_type_tex_proc_blend();
void register_node_type_tex_proc_clouds();
void register_node_type_tex_proc_distnoise();
void register_node_type_tex_proc_magic();
void register_node_type_tex_proc_marble();
void register_node_type_tex_proc_musgrave();
void register_node_type_tex_proc_noise();
void register_node_type_tex_proc_stucci();
void register_node_type_tex_proc_voronoi();
void register_node_type_tex_proc_wood();
void register_node_type_tex_rgbtobw();
void register_node_type_tex_rotate();
void register_node_type_tex_scale();
void register_node_type_tex_separate_color();
void register_node_type_tex_texture();
void register_node_type_tex_translate();
void register_node_type_tex_valtonor();
void register_node_type_tex_valtorgb();
void register_node_type_tex_viewer();
} // namespace blender

View File

@@ -0,0 +1,356 @@
/* SPDX-FileCopyrightText: 2007 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup nodes
*/
#include <cstring>
#include "DNA_node_types.h"
#include "DNA_space_types.h"
#include "DNA_texture_types.h"
#include "BLI_listbase.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
#include "BKE_context.hh"
#include "BKE_layer.hh"
#include "BKE_linestyle.h"
#include "BKE_node.hh"
#include "BKE_node_runtime.hh"
#include "BKE_paint.hh"
#include "BKE_texture.h"
#include "NOD_texture.h"
#include "node_common.h"
#include "node_exec.hh"
#include "node_texture_util.hh"
#include "node_util.hh"
#include "RNA_prototypes.hh"
#include "UI_resources.hh"
namespace blender {
static void texture_get_from_context(const bContext *C,
bke::bNodeTreeType * /*treetype*/,
bNodeTree **r_ntree,
ID **r_id,
ID **r_from)
{
const Main *bmain = CTX_data_main(C);
SpaceNode *snode = CTX_wm_space_node(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
BKE_view_layer_synced_ensure(*bmain, scene, view_layer);
Object *ob = BKE_view_layer_active_object_get(view_layer);
Tex *tx = nullptr;
if (snode->texfrom == SNODE_TEX_BRUSH) {
Brush *brush = nullptr;
if (ob && (ob->mode & OB_MODE_SCULPT)) {
brush = BKE_paint_brush(&scene->toolsettings->sculpt->paint);
}
else {
brush = BKE_paint_brush(&scene->toolsettings->imapaint.paint);
}
if (brush) {
*r_from = reinterpret_cast<ID *>(brush);
tx = give_current_brush_texture(brush);
if (tx) {
*r_id = &tx->id;
*r_ntree = tx->nodetree;
}
}
}
else if (snode->texfrom == SNODE_TEX_LINESTYLE) {
FreestyleLineStyle *linestyle = BKE_linestyle_active_from_view_layer(view_layer);
if (linestyle) {
*r_from = id_cast<ID *>(linestyle);
tx = give_current_linestyle_texture(linestyle);
if (tx) {
*r_id = &tx->id;
*r_ntree = tx->nodetree;
}
}
}
}
static void foreach_nodeclass(void *calldata, bke::bNodeClassCallback func)
{
func(calldata, NODE_CLASS_INPUT, N_("Input"));
func(calldata, NODE_CLASS_OUTPUT, N_("Output"));
func(calldata, NODE_CLASS_OP_COLOR, N_("Color"));
func(calldata, NODE_CLASS_PATTERN, N_("Patterns"));
func(calldata, NODE_CLASS_TEXTURE, N_("Textures"));
func(calldata, NODE_CLASS_CONVERTER, N_("Converter"));
func(calldata, NODE_CLASS_DISTORT, N_("Distort"));
func(calldata, NODE_CLASS_GROUP, N_("Group"));
func(calldata, NODE_CLASS_INTERFACE, N_("Interface"));
func(calldata, NODE_CLASS_LAYOUT, N_("Layout"));
}
/* XXX muting disabled in previews because of threading issues with the main execution
* it works here, but disabled for consistency
*/
#if 1
static void localize(bNodeTree *localtree, bNodeTree * /*ntree*/)
{
bNode *node, *node_next;
/* replace muted nodes and reroute nodes by internal links */
for (node = static_cast<bNode *>(localtree->nodes.first); node; node = node_next) {
node_next = node->next;
if (node->is_muted() || node->is_reroute()) {
bke::node_internal_relink(*localtree, *node);
bke::node_tree_free_local_node(*localtree, *node);
}
}
}
#else
static void localize(bNodeTree * /*localtree*/, bNodeTree * /*ntree*/) {}
#endif
static void update(bNodeTree *ntree)
{
ntree_update_reroute_nodes(ntree);
}
static bool texture_node_tree_socket_type_valid(bke::bNodeTreeType * /*ntreetype*/,
bke::bNodeSocketType *socket_type)
{
return bke::node_is_static_socket_type(*socket_type) &&
ELEM(socket_type->type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA);
}
bke::bNodeTreeType *ntreeType_Texture;
void register_node_tree_type_tex()
{
bke::bNodeTreeType *tt = ntreeType_Texture = MEM_new<bke::bNodeTreeType>(__func__);
tt->type = NTREE_TEXTURE;
tt->idname = "TextureNodeTree"_ustr;
tt->group_idname = "TextureNodeGroup"_ustr;
tt->ui_name = N_("Texture Node Editor");
tt->ui_icon = ICON_NODE_TEXTURE; /* Defined in `drawnode.cc`. */
tt->ui_description = N_("Edit textures using nodes");
/* Don't define this yet since we don't know which exact catalog name to use yet. Otherwise this
* has to be kept for compatibility. */
// tt->asset_catalog_path_prefix = "Textures";
tt->foreach_nodeclass = foreach_nodeclass;
tt->update = update;
tt->localize = localize;
tt->get_from_context = texture_get_from_context;
tt->valid_socket_type = texture_node_tree_socket_type_valid;
tt->rna_ext.srna = RNA_TextureNodeTree;
bke::node_tree_type_add(*tt);
}
/**** Material/Texture trees ****/
bNodeThreadStack *ntreeGetThreadStack(bNodeTreeExec *exec, int thread)
{
ListBaseT<bNodeThreadStack> *lb = &exec->threadstack[thread];
bNodeThreadStack *nts;
for (nts = static_cast<bNodeThreadStack *>(lb->first); nts; nts = nts->next) {
if (!nts->used) {
nts->used = true;
break;
}
}
if (!nts) {
nts = MEM_new_zeroed<bNodeThreadStack>("bNodeThreadStack");
nts->stack = MEM_dupalloc(exec->stack);
nts->used = true;
BLI_addtail(lb, nts);
}
return nts;
}
void ntreeReleaseThreadStack(bNodeThreadStack *nts)
{
nts->used = false;
}
bool ntreeExecThreadNodes(bNodeTreeExec *exec, bNodeThreadStack *nts, void *callerdata, int thread)
{
bNodeStack *nsin[MAX_SOCKET] = {nullptr}; /* arbitrary... watch this */
bNodeStack *nsout[MAX_SOCKET] = {nullptr}; /* arbitrary... watch this */
bNodeExec *nodeexec;
bNode *node;
int n;
/* nodes are presorted, so exec is in order of list */
for (n = 0, nodeexec = exec->nodeexec; n < exec->totnodes; n++, nodeexec++) {
node = nodeexec->node;
if (node->runtime->need_exec) {
node_get_stack(node, nts->stack, nsin, nsout);
/* Handle muted nodes...
* If the mute func is not set, assume the node should never be muted,
* and hence execute it!
*/
if (node->typeinfo->exec_fn && !node->is_muted()) {
node->typeinfo->exec_fn(callerdata, thread, node, &nodeexec->data, nsin, nsout);
}
}
}
/* signal to that all went OK, for render */
return true;
}
bNodeTreeExec *ntreeTexBeginExecTree_internal(bNodeExecContext *context,
bNodeTree *ntree,
bNodeInstanceKey parent_key)
{
bNodeTreeExec *exec;
/* common base initialization */
exec = ntree_exec_begin(context, ntree, parent_key);
/* allocate the thread stack listbase array */
exec->threadstack = MEM_new_array_zeroed<ListBaseT<bNodeThreadStack>>(BLENDER_MAX_THREADS,
"thread stack array");
for (bNode &node : exec->nodetree->nodes) {
node.runtime->need_exec = 1;
}
return exec;
}
bNodeTreeExec *ntreeTexBeginExecTree(bNodeTree *ntree)
{
bNodeExecContext context;
bNodeTreeExec *exec;
/* XXX hack: prevent exec data from being generated twice.
* this should be handled by the renderer!
*/
if (ntree->runtime->execdata) {
return ntree->runtime->execdata;
}
exec = ntreeTexBeginExecTree_internal(&context, ntree, bke::NODE_INSTANCE_KEY_BASE);
/* XXX this should not be necessary, but is still used for compositor/shading/texture nodes,
* which only store the ntree pointer. Should be fixed at some point!
*/
ntree->runtime->execdata = exec;
return exec;
}
/* free texture delegates */
static void tex_free_delegates(bNodeTreeExec *exec)
{
bNodeStack *ns;
int th, a;
for (th = 0; th < BLENDER_MAX_THREADS; th++) {
for (bNodeThreadStack &nts : exec->threadstack[th]) {
for (ns = nts.stack, a = 0; a < exec->stacksize; a++, ns++) {
if (ns->data && !ns->is_copy) {
MEM_delete(static_cast<TexDelegate *>(ns->data));
}
}
}
}
}
void ntreeTexEndExecTree_internal(bNodeTreeExec *exec)
{
int a;
if (exec->threadstack) {
tex_free_delegates(exec);
for (a = 0; a < BLENDER_MAX_THREADS; a++) {
for (bNodeThreadStack &nts : exec->threadstack[a]) {
if (nts.stack) {
MEM_delete(nts.stack);
}
}
BLI_freelistN(&exec->threadstack[a]);
}
MEM_delete(exec->threadstack);
exec->threadstack = nullptr;
}
ntree_exec_end(exec);
}
void ntreeTexEndExecTree(bNodeTreeExec *exec)
{
if (exec) {
/* exec may get freed, so assign ntree */
bNodeTree *ntree = exec->nodetree;
ntreeTexEndExecTree_internal(exec);
/* XXX: clear node-tree back-pointer to exec data,
* same problem as noted in #ntreeBeginExecTree. */
ntree->runtime->execdata = nullptr;
}
}
int ntreeTexExecTree(bNodeTree *ntree,
TexResult *target,
const float co[3],
const short thread,
const Tex * /*tex*/,
short which_output,
int cfra,
int preview,
MTex *mtex)
{
TexCallData data;
int retval = TEX_INT;
bNodeThreadStack *nts = nullptr;
bNodeTreeExec *exec = ntree->runtime->execdata;
data.co = co;
data.target = target;
data.do_preview = preview;
data.do_manage = true;
data.thread = thread;
data.which_output = which_output;
data.cfra = cfra;
data.mtex = mtex;
/* ensure execdata is only initialized once */
if (!exec) {
BLI_thread_lock(LOCK_NODES);
if (!ntree->runtime->execdata) {
ntreeTexBeginExecTree(ntree);
}
BLI_thread_unlock(LOCK_NODES);
exec = ntree->runtime->execdata;
}
nts = ntreeGetThreadStack(exec, thread);
ntreeExecThreadNodes(exec, nts, &data, thread);
ntreeReleaseThreadStack(nts);
retval |= TEX_RGB;
return retval;
}
} // namespace blender

View File

@@ -0,0 +1,170 @@
/* SPDX-FileCopyrightText: 2005 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup nodes
*/
/*
* HOW TEXTURE NODES WORK
*
* In contrast to Shader nodes, which place a color into the output
* stack when executed, Texture nodes place a TexDelegate* there. To
* obtain a color value from this, a node further up the chain reads
* the TexDelegate* from its input stack, and uses tex_call_delegate to
* retrieve the color from the delegate.
*
* comments: (ton)
*
* This system needs recode, a node system should rely on the stack, and
* callbacks for nodes only should evaluate their own node, not recursively go
* over other previous ones.
*/
#include "BLI_listbase.h"
#include "BKE_node_runtime.hh"
#include "NOD_texture.h"
#include "node_texture_util.hh"
#include "node_util.hh"
#include <optional>
namespace blender {
bool tex_node_poll_default(const bke::bNodeType * /*ntype*/,
const bNodeTree *ntree,
const char **r_disabled_hint)
{
if (!STREQ(ntree->idname, "TextureNodeTree")) {
*r_disabled_hint = RPT_("Not a texture node tree");
return false;
}
return true;
}
void tex_node_type_base(bke::bNodeType *ntype,
UString idname,
const std::optional<int16_t> legacy_type)
{
bke::node_type_base(*ntype, idname, legacy_type);
ntype->poll = tex_node_poll_default;
ntype->insert_link = node_insert_link_default;
}
static void tex_call_delegate(TexDelegate *dg, float *out, TexParams *params, short thread)
{
if (dg->node->runtime->need_exec) {
dg->fn(out, params, dg->node, dg->in, thread);
}
}
static void tex_input(float *out, int num, bNodeStack *in, TexParams *params, short thread)
{
TexDelegate *dg = static_cast<TexDelegate *>(in->data);
if (dg) {
tex_call_delegate(dg, in->vec, params, thread);
if (in->hasoutput && in->sockettype == SOCK_FLOAT) {
in->vec[1] = in->vec[2] = in->vec[0];
}
}
memcpy(out, in->vec, num * sizeof(float));
}
void tex_input_vec(float *out, bNodeStack *in, TexParams *params, short thread)
{
tex_input(out, 3, in, params, thread);
}
void tex_input_rgba(float *out, bNodeStack *in, TexParams *params, short thread)
{
tex_input(out, 4, in, params, thread);
if (in->hasoutput && in->sockettype == SOCK_FLOAT) {
out[1] = out[2] = out[0];
out[3] = 1;
}
if (in->hasoutput && in->sockettype == SOCK_VECTOR) {
out[0] = out[0] * 0.5f + 0.5f;
out[1] = out[1] * 0.5f + 0.5f;
out[2] = out[2] * 0.5f + 0.5f;
out[3] = 1;
}
}
float tex_input_value(bNodeStack *in, TexParams *params, short thread)
{
float out[4];
tex_input_vec(out, in, params, thread);
return out[0];
}
void params_from_cdata(TexParams *out, TexCallData *in)
{
out->co = in->co;
out->previewco = in->co;
out->cfra = in->cfra;
out->mtex = in->mtex;
}
void tex_output(bNode *node,
bNodeExecData * /*execdata*/,
bNodeStack **in,
bNodeStack *out,
TexFn texfn,
TexCallData *cdata)
{
TexDelegate *dg;
if (node->is_muted()) {
/* do not add a delegate if the node is muted */
return;
}
if (!out->data) {
/* Freed in tex_end_exec (node.cc) */
dg = MEM_new_zeroed<TexDelegate>("tex delegate");
out->data = dg;
}
else {
dg = static_cast<TexDelegate *>(out->data);
}
dg->cdata = cdata;
dg->fn = texfn;
dg->node = node;
memcpy(dg->in, in, MAX_SOCKET * sizeof(bNodeStack *));
dg->type = out->sockettype;
}
void ntreeTexCheckCyclics(bNodeTree *ntree)
{
for (bNode &node : ntree->nodes) {
if (node.type_legacy == TEX_NODE_TEXTURE && node.id) {
/* custom2 stops the node from rendering */
if (node.custom1) {
node.custom2 = 1;
node.custom1 = 0;
}
else {
Tex *tex = id_cast<Tex *>(node.id);
node.custom2 = 0;
node.custom1 = 1;
if (tex->use_nodes && tex->nodetree) {
ntreeTexCheckCyclics(tex->nodetree);
}
node.custom1 = 0;
}
}
}
}
} // namespace blender

View File

@@ -0,0 +1,92 @@
/* SPDX-FileCopyrightText: 2005 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup nodes
*/
#pragma once
#include <optional>
#include "BKE_node.hh"
#include "BKE_node_legacy_types.hh" // IWYU pragma: export
#include "node_texture_register.hh" // IWYU pragma: export
#include "BLT_translation.hh" // IWYU pragma: export
#include "RE_texture.h"
namespace blender {
struct bNodeThreadStack;
struct TexCallData {
TexResult *target;
/* float[3] */
const float *co;
bool do_preview;
bool do_manage;
short thread;
short which_output;
int cfra;
const MTex *mtex;
};
struct TexParams {
const float *co;
const float *previewco;
int cfra;
/* optional. we don't really want these here, but image
* textures need to do mapping & color correction */
const MTex *mtex;
};
using TexFn = void (*)(float *out, TexParams *params, bNode *node, bNodeStack **in, short thread);
struct TexDelegate {
TexCallData *cdata;
TexFn fn;
bNode *node;
bNodeStack *in[MAX_SOCKET];
int type;
};
bool tex_node_poll_default(const bke::bNodeType *ntype,
const bNodeTree *ntree,
const char **r_disabled_hint);
void tex_node_type_base(bke::bNodeType *ntype,
UString idname,
std::optional<int16_t> legacy_type = std::nullopt);
void tex_input_rgba(float *out, bNodeStack *in, TexParams *params, short thread);
void tex_input_vec(float *out, bNodeStack *in, TexParams *params, short thread);
float tex_input_value(bNodeStack *in, TexParams *params, short thread);
void tex_output(bNode *node,
bNodeExecData *execdata,
bNodeStack **in,
bNodeStack *out,
TexFn texfn,
TexCallData *data);
void params_from_cdata(TexParams *out, TexCallData *in);
bNodeThreadStack *ntreeGetThreadStack(bNodeTreeExec *exec, int thread);
void ntreeReleaseThreadStack(bNodeThreadStack *nts);
bool ntreeExecThreadNodes(bNodeTreeExec *exec,
bNodeThreadStack *nts,
void *callerdata,
int thread);
bNodeTreeExec *ntreeTexBeginExecTree_internal(bNodeExecContext *context,
bNodeTree *ntree,
bNodeInstanceKey parent_key);
void ntreeTexEndExecTree_internal(bNodeTreeExec *exec);
} // namespace blender

View File

@@ -0,0 +1,57 @@
/* SPDX-FileCopyrightText: 2005 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup texnodes
*/
#include "node_texture_util.hh"
namespace blender {
static bke::bNodeSocketTemplate inputs[] = {
{SOCK_RGBA, N_("Texture"), 0.0f, 0.0f, 0.0f, 1.0f},
{SOCK_VECTOR, N_("Coordinates"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, PROP_NONE},
{-1, ""},
};
static bke::bNodeSocketTemplate outputs[] = {
{SOCK_RGBA, N_("Texture")},
{-1, ""},
};
static void colorfn(float *out, TexParams *p, bNode * /*node*/, bNodeStack **in, short thread)
{
TexParams np = *p;
float new_co[3];
np.co = new_co;
tex_input_vec(new_co, in[1], p, thread);
tex_input_rgba(out, in[0], &np, thread);
}
static void exec(void *data,
int /*thread*/,
bNode *node,
bNodeExecData *execdata,
bNodeStack **in,
bNodeStack **out)
{
tex_output(node, execdata, in, out[0], &colorfn, static_cast<TexCallData *>(data));
}
void register_node_type_tex_at()
{
static bke::bNodeType ntype;
tex_node_type_base(&ntype, "TextureNodeAt"_ustr, TEX_NODE_AT);
ntype.ui_name = "At";
ntype.enum_name_legacy = "AT";
ntype.nclass = NODE_CLASS_DISTORT;
bke::node_type_socket_templates(&ntype, inputs, outputs);
ntype.exec_fn = exec;
bke::node_register_type(ntype);
}
} // namespace blender

View File

@@ -0,0 +1,125 @@
/* SPDX-FileCopyrightText: 2005 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup texnodes
*/
#include "BKE_material.hh"
#include "BLI_math_vector.h"
#include "DNA_material_types.h"
#include "node_texture_util.hh"
#include <cmath>
namespace blender {
static bke::bNodeSocketTemplate inputs[] = {
{SOCK_RGBA, N_("Bricks 1"), 0.596f, 0.282f, 0.0f, 1.0f},
{SOCK_RGBA, N_("Bricks 2"), 0.632f, 0.504f, 0.05f, 1.0f},
{SOCK_RGBA, N_("Mortar"), 0.0f, 0.0f, 0.0f, 1.0f},
{SOCK_FLOAT, N_("Thickness"), 0.02f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_UNSIGNED},
{SOCK_FLOAT, N_("Bias"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, PROP_NONE},
{SOCK_FLOAT, N_("Brick Width"), 0.5f, 0.0f, 0.0f, 0.0f, 0.001f, 99.0f, PROP_UNSIGNED},
{SOCK_FLOAT, N_("Row Height"), 0.25f, 0.0f, 0.0f, 0.0f, 0.001f, 99.0f, PROP_UNSIGNED},
{-1, ""},
};
static bke::bNodeSocketTemplate outputs[] = {
{SOCK_RGBA, N_("Color")},
{-1, ""},
};
static void init(bNodeTree * /*ntree*/, bNode *node)
{
node->custom3 = 0.5; /* offset */
node->custom4 = 1.0; /* squash */
}
static float noise(int n) /* fast integer noise */
{
int nn;
n = (n >> 13) ^ n;
nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
return 0.5f * (float(nn) / 1073741824.0f);
}
static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread)
{
const float *co = p->co;
float x = co[0];
float y = co[1];
int bricknum, rownum;
float offset = 0;
float ins_x, ins_y;
float tint;
float bricks1[4];
float bricks2[4];
float mortar[4];
float mortar_thickness = tex_input_value(in[3], p, thread);
float bias = tex_input_value(in[4], p, thread);
float brick_width = tex_input_value(in[5], p, thread);
float row_height = tex_input_value(in[6], p, thread);
tex_input_rgba(bricks1, in[0], p, thread);
tex_input_rgba(bricks2, in[1], p, thread);
tex_input_rgba(mortar, in[2], p, thread);
rownum = int(floor(y / row_height));
if (node->custom1 && node->custom2) {
brick_width *= (rownum % node->custom2) ? 1.0f : node->custom4; /* squash */
offset = (rownum % node->custom1) ? 0 : (brick_width * node->custom3); /* offset */
}
bricknum = int(floor((x + offset) / brick_width));
ins_x = (x + offset) - brick_width * bricknum;
ins_y = y - row_height * rownum;
tint = noise((rownum << 16) + (bricknum & 0xFFFF)) + bias;
CLAMP(tint, 0.0f, 1.0f);
if (ins_x < mortar_thickness || ins_y < mortar_thickness ||
ins_x > (brick_width - mortar_thickness) || ins_y > (row_height - mortar_thickness))
{
copy_v4_v4(out, mortar);
}
else {
copy_v4_v4(out, bricks1);
ramp_blend(MA_RAMP_BLEND, out, tint, bricks2);
}
}
static void exec(void *data,
int /*thread*/,
bNode *node,
bNodeExecData *execdata,
bNodeStack **in,
bNodeStack **out)
{
tex_output(node, execdata, in, out[0], &colorfn, static_cast<TexCallData *>(data));
}
void register_node_type_tex_bricks()
{
static bke::bNodeType ntype;
tex_node_type_base(&ntype, "TextureNodeBricks"_ustr, TEX_NODE_BRICKS);
ntype.ui_name = "Bricks";
ntype.enum_name_legacy = "BRICKS";
ntype.nclass = NODE_CLASS_PATTERN;
bke::node_type_socket_templates(&ntype, inputs, outputs);
ntype.default_width = bke::NodeWidth::_160;
ntype.initfunc = init;
ntype.exec_fn = exec;
ntype.flag |= NODE_PREVIEW;
bke::node_register_type(ntype);
}
} // namespace blender

View File

@@ -0,0 +1,70 @@
/* SPDX-FileCopyrightText: 2005 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup texnodes
*/
#include "node_texture_util.hh"
#include <cmath>
namespace blender {
static bke::bNodeSocketTemplate inputs[] = {
{SOCK_RGBA, N_("Color1"), 1.0f, 0.0f, 0.0f, 1.0f},
{SOCK_RGBA, N_("Color2"), 1.0f, 1.0f, 1.0f, 1.0f},
{SOCK_FLOAT, N_("Size"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 100.0f, PROP_UNSIGNED},
{-1, ""},
};
static bke::bNodeSocketTemplate outputs[] = {
{SOCK_RGBA, N_("Color")},
{-1, ""},
};
static void colorfn(float *out, TexParams *p, bNode * /*node*/, bNodeStack **in, short thread)
{
float x = p->co[0];
float y = p->co[1];
float z = p->co[2];
float sz = tex_input_value(in[2], p, thread);
/* 0.00001 because of unit sized stuff */
int xi = int(fabs(floor(0.00001f + x / sz)));
int yi = int(fabs(floor(0.00001f + y / sz)));
int zi = int(fabs(floor(0.00001f + z / sz)));
if ((xi % 2 == yi % 2) == (zi % 2)) {
tex_input_rgba(out, in[0], p, thread);
}
else {
tex_input_rgba(out, in[1], p, thread);
}
}
static void exec(void *data,
int /*thread*/,
bNode *node,
bNodeExecData *execdata,
bNodeStack **in,
bNodeStack **out)
{
tex_output(node, execdata, in, out[0], &colorfn, static_cast<TexCallData *>(data));
}
void register_node_type_tex_checker()
{
static bke::bNodeType ntype;
tex_node_type_base(&ntype, "TextureNodeChecker"_ustr, TEX_NODE_CHECKER);
ntype.ui_name = "Checker";
ntype.enum_name_legacy = "CHECKER";
ntype.nclass = NODE_CLASS_PATTERN;
bke::node_type_socket_templates(&ntype, inputs, outputs);
ntype.exec_fn = exec;
ntype.flag |= NODE_PREVIEW;
bke::node_register_type(ntype);
}
} // namespace blender

View File

@@ -0,0 +1,84 @@
/* SPDX-FileCopyrightText: 2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup texnodes
*/
#include "BLI_math_color.h"
#include "node_texture_util.hh"
#include "node_util.hh"
namespace blender {
static bke::bNodeSocketTemplate inputs[] = {
{SOCK_FLOAT, N_("Red"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{SOCK_FLOAT, N_("Green"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{SOCK_FLOAT, N_("Blue"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{SOCK_FLOAT, N_("Alpha"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{-1, ""},
};
static bke::bNodeSocketTemplate outputs[] = {
{SOCK_RGBA, N_("Color")},
{-1, ""},
};
static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread)
{
int i;
for (i = 0; i < 4; i++) {
out[i] = tex_input_value(in[i], p, thread);
}
/* Apply color space if required. */
switch (node->custom1) {
case NODE_COMBSEP_COLOR_RGB: {
/* Pass */
break;
}
case NODE_COMBSEP_COLOR_HSV: {
hsv_to_rgb_v(out, out);
break;
}
case NODE_COMBSEP_COLOR_HSL: {
hsl_to_rgb_v(out, out);
break;
}
default: {
BLI_assert_unreachable();
break;
}
}
}
static void update(bNodeTree * /*ntree*/, bNode *node)
{
node_combsep_color_label(&node->inputs, NodeCombSepColorMode(node->custom1));
}
static void exec(void *data,
int /*thread*/,
bNode *node,
bNodeExecData *execdata,
bNodeStack **in,
bNodeStack **out)
{
tex_output(node, execdata, in, out[0], &colorfn, static_cast<TexCallData *>(data));
}
void register_node_type_tex_combine_color()
{
static bke::bNodeType ntype;
tex_node_type_base(&ntype, "TextureNodeCombineColor"_ustr, TEX_NODE_COMBINE_COLOR);
ntype.ui_name = "Combine Color";
ntype.enum_name_legacy = "COMBINE_COLOR";
ntype.nclass = NODE_CLASS_OP_COLOR;
bke::node_type_socket_templates(&ntype, inputs, outputs);
ntype.exec_fn = exec;
ntype.updatefunc = update;
bke::node_register_type(ntype);
}
} // namespace blender

View File

@@ -0,0 +1,170 @@
/* SPDX-FileCopyrightText: 2006 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup texnodes
*/
#include "DNA_node_types.h"
#include "BLI_listbase.h"
#include "BLI_math_vector.h"
#include "BKE_node.hh"
#include "BKE_node_runtime.hh"
#include "NOD_common.hh"
#include "node_common.h"
#include "node_exec.hh"
#include "node_texture_util.hh"
#include "RNA_access.hh"
namespace blender {
static void copy_stack(bNodeStack *to, bNodeStack *from)
{
if (to != from) {
copy_v4_v4(to->vec, from->vec);
to->data = from->data;
to->datatype = from->datatype;
/* tag as copy to prevent freeing */
to->is_copy = 1;
}
}
/**** GROUP ****/
static void *group_initexec(bNodeExecContext *context, bNode *node, bNodeInstanceKey key)
{
bNodeTree *ngroup = id_cast<bNodeTree *>(node->id);
void *exec;
if (!ngroup) {
return nullptr;
}
/* initialize the internal node tree execution */
exec = ntreeTexBeginExecTree_internal(context, ngroup, key);
return exec;
}
static void group_freeexec(void *nodedata)
{
bNodeTreeExec *gexec = static_cast<bNodeTreeExec *>(nodedata);
ntreeTexEndExecTree_internal(gexec);
}
/* Copy inputs to the internal stack.
* This is a shallow copy, no buffers are duplicated here!
*/
static void group_copy_inputs(bNode *gnode, bNodeStack **in, bNodeStack *gstack)
{
bNodeTree *ngroup = id_cast<bNodeTree *>(gnode->id);
bNodeSocket *sock;
bNodeStack *ns;
int a;
for (bNode &node : ngroup->nodes) {
if (node.is_group_input()) {
for (sock = static_cast<bNodeSocket *>(node.outputs.first), a = 0; sock;
sock = sock->next, a++)
{
if (in[a]) { /* shouldn't need to check this #36694. */
ns = node_get_socket_stack(gstack, sock);
if (ns) {
copy_stack(ns, in[a]);
}
}
}
}
}
}
/* Copy internal results to the external outputs.
*/
static void group_copy_outputs(bNode *gnode, bNodeStack **out, bNodeStack *gstack)
{
bNodeTree &ngroup = *reinterpret_cast<bNodeTree *>(gnode->id);
ngroup.ensure_topology_cache();
bNode *group_output_node = ngroup.group_output_node();
if (!group_output_node) {
return;
}
for (auto [a, sock] : group_output_node->inputs.enumerate()) {
if (!out[a]) {
/* shouldn't need to check this #36694. */
continue;
}
bNodeStack *ns = node_get_socket_stack(gstack, &sock);
if (ns) {
copy_stack(out[a], ns);
}
}
}
static void group_execute(void *data,
int thread,
bNode *node,
bNodeExecData *execdata,
bNodeStack **in,
bNodeStack **out)
{
bNodeTreeExec *exec = static_cast<bNodeTreeExec *>(execdata->data);
bNodeThreadStack *nts;
if (!exec) {
return;
}
/* XXX same behavior as trunk: all nodes inside group are executed.
* it's stupid, but just makes it work. compo redesign will do this better.
*/
for (bNode &inode : exec->nodetree->nodes) {
inode.runtime->need_exec = 1;
}
nts = ntreeGetThreadStack(exec, thread);
group_copy_inputs(node, in, nts->stack);
ntreeExecThreadNodes(exec, nts, data, thread);
group_copy_outputs(node, out, nts->stack);
ntreeReleaseThreadStack(nts);
}
void register_node_type_tex_group()
{
static bke::bNodeType ntype;
/* NOTE: Cannot use #sh_node_type_base for node group, because it would map the node type
* to the shared #NODE_GROUP integer type id. */
bke::node_type_base_custom(ntype, "TextureNodeGroup", "Group", "GROUP", NODE_CLASS_GROUP);
ntype.enum_name_legacy = "GROUP";
ntype.type_legacy = NODE_GROUP;
ntype.poll = tex_node_poll_default;
ntype.poll_instance = node_group_poll_instance;
ntype.insert_link = node_insert_link_default;
ntype.rna_ext.srna = RNA_struct_find("TextureNodeGroup");
BLI_assert(ntype.rna_ext.srna != nullptr);
RNA_struct_blender_type_set(ntype.rna_ext.srna, &ntype);
ntype.minwidth = bke::NodeWidth::GroupMin;
ntype.labelfunc = node_group_label;
ntype.declare = nodes::node_group_declare;
ntype.init_exec_fn = group_initexec;
ntype.free_exec_fn = group_freeexec;
ntype.exec_fn = group_execute;
bke::node_register_type(ntype);
}
} // namespace blender

View File

@@ -0,0 +1,49 @@
/* SPDX-FileCopyrightText: 2005 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup texnodes
*/
#include "BLI_math_vector.h"
#include "node_texture_util.hh"
namespace blender {
static bke::bNodeSocketTemplate outputs[] = {
{SOCK_VECTOR, N_("Coordinates")},
{-1, ""},
};
static void vectorfn(
float *out, TexParams *p, bNode * /*node*/, bNodeStack ** /*in*/, short /*thread*/)
{
copy_v3_v3(out, p->co);
}
static void exec(void *data,
int /*thread*/,
bNode *node,
bNodeExecData *execdata,
bNodeStack **in,
bNodeStack **out)
{
tex_output(node, execdata, in, out[0], &vectorfn, static_cast<TexCallData *>(data));
}
void register_node_type_tex_coord()
{
static bke::bNodeType ntype;
tex_node_type_base(&ntype, "TextureNodeCoordinates"_ustr, TEX_NODE_COORD);
ntype.ui_name = "Coordinates";
ntype.enum_name_legacy = "COORD";
ntype.nclass = NODE_CLASS_INPUT;
bke::node_type_socket_templates(&ntype, nullptr, outputs);
ntype.exec_fn = exec;
bke::node_register_type(ntype);
}
} // namespace blender

View File

@@ -0,0 +1,126 @@
/* SPDX-FileCopyrightText: 2005 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup texnodes
*/
#include <algorithm>
#include "BKE_colortools.hh"
#include "node_texture_util.hh"
#include "node_util.hh"
namespace blender {
/* **************** CURVE Time ******************** */
/* custom1 = start-frame, custom2 = end-frame. */
static bke::bNodeSocketTemplate time_outputs[] = {{SOCK_FLOAT, N_("Value")}, {-1, ""}};
static void time_colorfn(
float *out, TexParams *p, bNode *node, bNodeStack ** /*in*/, short /*thread*/)
{
/* stack order output: fac */
float fac = 0.0f;
if (node->custom1 < node->custom2) {
fac = (p->cfra - node->custom1) / float(node->custom2 - node->custom1);
}
CurveMapping *mapping = static_cast<CurveMapping *>(node->storage);
BKE_curvemapping_init(mapping);
fac = BKE_curvemapping_evaluateF(mapping, 0, fac);
out[0] = std::clamp(fac, 0.0f, 1.0f);
}
static void time_exec(void *data,
int /*thread*/,
bNode *node,
bNodeExecData *execdata,
bNodeStack **in,
bNodeStack **out)
{
tex_output(node, execdata, in, out[0], &time_colorfn, static_cast<TexCallData *>(data));
}
static void time_init(bNodeTree * /*ntree*/, bNode *node)
{
node->custom1 = 1;
node->custom2 = 250;
node->storage = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
}
void register_node_type_tex_curve_time()
{
static bke::bNodeType ntype;
tex_node_type_base(&ntype, "TextureNodeCurveTime"_ustr, TEX_NODE_CURVE_TIME);
ntype.ui_name = "Time";
ntype.enum_name_legacy = "CURVE_TIME";
ntype.nclass = NODE_CLASS_INPUT;
bke::node_type_socket_templates(&ntype, nullptr, time_outputs);
ntype.default_width = bke::NodeWidth::_240;
ntype.initfunc = time_init;
bke::node_type_storage(ntype, "CurveMapping", node_free_curves, node_copy_curves);
ntype.init_exec_fn = node_initexec_curves;
ntype.exec_fn = time_exec;
bke::node_register_type(ntype);
}
/* **************** CURVE RGB ******************** */
static bke::bNodeSocketTemplate rgb_inputs[] = {
{SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f},
{-1, ""},
};
static bke::bNodeSocketTemplate rgb_outputs[] = {
{SOCK_RGBA, N_("Color")},
{-1, ""},
};
static void rgb_colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread)
{
float cin[4];
tex_input_rgba(cin, in[0], p, thread);
BKE_curvemapping_evaluateRGBF(static_cast<CurveMapping *>(node->storage), out, cin);
out[3] = cin[3];
}
static void rgb_exec(void *data,
int /*thread*/,
bNode *node,
bNodeExecData *execdata,
bNodeStack **in,
bNodeStack **out)
{
tex_output(node, execdata, in, out[0], &rgb_colorfn, static_cast<TexCallData *>(data));
}
static void rgb_init(bNodeTree * /*ntree*/, bNode *node)
{
node->storage = BKE_curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
}
void register_node_type_tex_curve_rgb()
{
static bke::bNodeType ntype;
tex_node_type_base(&ntype, "TextureNodeCurveRGB"_ustr, TEX_NODE_CURVE_RGB);
ntype.ui_name = "RGB Curves";
ntype.enum_name_legacy = "CURVE_RGB";
ntype.nclass = NODE_CLASS_OP_COLOR;
bke::node_type_socket_templates(&ntype, rgb_inputs, rgb_outputs);
ntype.default_width = bke::NodeWidth::_240;
ntype.initfunc = rgb_init;
bke::node_type_storage(ntype, "CurveMapping", node_free_curves, node_copy_curves);
ntype.init_exec_fn = node_initexec_curves;
ntype.exec_fn = rgb_exec;
bke::node_register_type(ntype);
}
} // namespace blender

View File

@@ -0,0 +1,59 @@
/* SPDX-FileCopyrightText: 2005 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup texnodes
*/
#include "BLI_math_vector.h"
#include "node_texture_util.hh"
namespace blender {
static bke::bNodeSocketTemplate inputs[] = {
{SOCK_VECTOR, N_("Coordinate 1"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, PROP_NONE},
{SOCK_VECTOR, N_("Coordinate 2"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, PROP_NONE},
{-1, ""},
};
static bke::bNodeSocketTemplate outputs[] = {
{SOCK_FLOAT, N_("Value")},
{-1, ""},
};
static void valuefn(float *out, TexParams *p, bNode * /*node*/, bNodeStack **in, short thread)
{
float co1[3], co2[3];
tex_input_vec(co1, in[0], p, thread);
tex_input_vec(co2, in[1], p, thread);
*out = len_v3v3(co2, co1);
}
static void exec(void *data,
int /*thread*/,
bNode *node,
bNodeExecData *execdata,
bNodeStack **in,
bNodeStack **out)
{
tex_output(node, execdata, in, out[0], &valuefn, static_cast<TexCallData *>(data));
}
void register_node_type_tex_distance()
{
static bke::bNodeType ntype;
tex_node_type_base(&ntype, "TextureNodeDistance"_ustr, TEX_NODE_DISTANCE);
ntype.ui_name = "Distance";
ntype.enum_name_legacy = "DISTANCE";
ntype.nclass = NODE_CLASS_CONVERTER;
bke::node_type_socket_templates(&ntype, inputs, outputs);
ntype.exec_fn = exec;
bke::node_register_type(ntype);
}
} // namespace blender

View File

@@ -0,0 +1,109 @@
/* SPDX-FileCopyrightText: 2006 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup texnodes
*/
#include "BLI_math_color.h"
#include "BLI_math_vector.h"
#include "node_texture_util.hh"
namespace blender {
static bke::bNodeSocketTemplate inputs[] = {
{SOCK_FLOAT, N_("Hue"), 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.5f, PROP_NONE},
{SOCK_FLOAT, N_("Saturation"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, PROP_NONE},
{SOCK_FLOAT, N_("Value"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, PROP_NONE},
{SOCK_FLOAT, N_("Factor"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE},
{SOCK_RGBA, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f},
{-1, ""},
};
static bke::bNodeSocketTemplate outputs[] = {
{SOCK_RGBA, N_("Color")},
{-1, ""},
};
static void do_hue_sat_fac(
bNode * /*node*/, float *out, float hue, float sat, float val, float *in, float fac)
{
if (fac != 0 && (hue != 0.5f || sat != 1 || val != 1)) {
float col[3], hsv[3], mfac = 1.0f - fac;
rgb_to_hsv(in[0], in[1], in[2], hsv, hsv + 1, hsv + 2);
hsv[0] += (hue - 0.5f);
if (hsv[0] > 1.0f) {
hsv[0] -= 1.0f;
}
else if (hsv[0] < 0.0f) {
hsv[0] += 1.0f;
}
hsv[1] *= sat;
if (hsv[1] > 1.0f) {
hsv[1] = 1.0f;
}
else if (hsv[1] < 0.0f) {
hsv[1] = 0.0f;
}
hsv[2] *= val;
if (hsv[2] > 1.0f) {
hsv[2] = 1.0f;
}
else if (hsv[2] < 0.0f) {
hsv[2] = 0.0f;
}
hsv_to_rgb(hsv[0], hsv[1], hsv[2], col, col + 1, col + 2);
out[0] = mfac * in[0] + fac * col[0];
out[1] = mfac * in[1] + fac * col[1];
out[2] = mfac * in[2] + fac * col[2];
}
else {
copy_v4_v4(out, in);
}
}
static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread)
{
float hue = tex_input_value(in[0], p, thread);
float sat = tex_input_value(in[1], p, thread);
float val = tex_input_value(in[2], p, thread);
float fac = tex_input_value(in[3], p, thread);
float col[4];
tex_input_rgba(col, in[4], p, thread);
hue += 0.5f; /* [-0.5, 0.5] -> [0, 1] */
do_hue_sat_fac(node, out, hue, sat, val, col, fac);
out[3] = col[3];
}
static void exec(void *data,
int /*thread*/,
bNode *node,
bNodeExecData *execdata,
bNodeStack **in,
bNodeStack **out)
{
tex_output(node, execdata, in, out[0], &colorfn, static_cast<TexCallData *>(data));
}
void register_node_type_tex_hue_sat()
{
static bke::bNodeType ntype;
tex_node_type_base(&ntype, "TextureNodeHueSaturation"_ustr, TEX_NODE_HUE_SAT);
ntype.ui_name = "Hue/Saturation/Value";
ntype.enum_name_legacy = "HUE_SAT";
ntype.nclass = NODE_CLASS_OP_COLOR;
bke::node_type_socket_templates(&ntype, inputs, outputs);
ntype.default_width = bke::NodeWidth::_160;
ntype.exec_fn = exec;
bke::node_register_type(ntype);
}
} // namespace blender

View File

@@ -0,0 +1,119 @@
/* SPDX-FileCopyrightText: 2006 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup texnodes
*/
#include "BLI_math_vector.h"
#include "BLI_threads.h"
#include "IMB_imbuf.hh"
#include "BKE_image.hh"
#include "node_texture_util.hh"
#include "node_util.hh"
namespace blender {
static bke::bNodeSocketTemplate outputs[] = {
{SOCK_RGBA, N_("Image")},
{-1, ""},
};
static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack ** /*in*/, short /*thread*/)
{
float x = p->co[0];
float y = p->co[1];
Image *ima = id_cast<Image *>(node->id);
ImageUser *iuser = static_cast<ImageUser *>(node->storage);
if (ima) {
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, nullptr);
if (ibuf) {
float xsize, ysize;
float xoff, yoff;
int px, py;
const float *result;
xsize = ibuf->x / 2;
ysize = ibuf->y / 2;
xoff = yoff = -1;
px = int((x - xoff) * xsize);
py = int((y - yoff) * ysize);
if ((!xsize) || (!ysize)) {
return;
}
if (!ibuf->float_data()) {
BLI_thread_lock(LOCK_IMAGE);
if (!ibuf->float_data()) {
IMB_float_from_byte(ibuf);
}
BLI_thread_unlock(LOCK_IMAGE);
}
while (px < 0) {
px += ibuf->x;
}
while (py < 0) {
py += ibuf->y;
}
while (px >= ibuf->x) {
px -= ibuf->x;
}
while (py >= ibuf->y) {
py -= ibuf->y;
}
result = ibuf->float_data() + py * ibuf->x * 4 + px * 4;
copy_v4_v4(out, result);
BKE_image_release_ibuf(ima, ibuf, nullptr);
}
}
}
static void exec(void *data,
int /*thread*/,
bNode *node,
bNodeExecData *execdata,
bNodeStack **in,
bNodeStack **out)
{
tex_output(node, execdata, in, out[0], &colorfn, static_cast<TexCallData *>(data));
}
static void init(bNodeTree * /*ntree*/, bNode *node)
{
ImageUser *iuser = MEM_new<ImageUser>("node image user");
node->storage = iuser;
iuser->sfra = 1;
iuser->flag |= IMA_ANIM_ALWAYS;
}
void register_node_type_tex_image()
{
static bke::bNodeType ntype;
tex_node_type_base(&ntype, "TextureNodeImage"_ustr, TEX_NODE_IMAGE);
ntype.ui_name = "Image";
ntype.enum_name_legacy = "IMAGE";
ntype.nclass = NODE_CLASS_INPUT;
bke::node_type_socket_templates(&ntype, nullptr, outputs);
ntype.initfunc = init;
bke::node_type_storage(
ntype, "ImageUser", node_free_standard_storage, node_copy_standard_storage);
ntype.exec_fn = exec;
ntype.labelfunc = node_image_label;
ntype.flag |= NODE_PREVIEW;
bke::node_register_type(ntype);
}
} // namespace blender

View File

@@ -0,0 +1,63 @@
/* SPDX-FileCopyrightText: 2005 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup texnodes
*/
#include "BLI_math_vector.h"
#include "node_texture_util.hh"
namespace blender {
/* **************** INVERT ******************** */
static bke::bNodeSocketTemplate inputs[] = {
{SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f},
{-1, ""},
};
static bke::bNodeSocketTemplate outputs[] = {
{SOCK_RGBA, N_("Color")},
{-1, ""},
};
static void colorfn(float *out, TexParams *p, bNode * /*node*/, bNodeStack **in, short thread)
{
float col[4];
tex_input_rgba(col, in[0], p, thread);
col[0] = 1.0f - col[0];
col[1] = 1.0f - col[1];
col[2] = 1.0f - col[2];
copy_v3_v3(out, col);
out[3] = col[3];
}
static void exec(void *data,
int /*thread*/,
bNode *node,
bNodeExecData *execdata,
bNodeStack **in,
bNodeStack **out)
{
tex_output(node, execdata, in, out[0], &colorfn, static_cast<TexCallData *>(data));
}
void register_node_type_tex_invert()
{
static bke::bNodeType ntype;
tex_node_type_base(&ntype, "TextureNodeInvert"_ustr, TEX_NODE_INVERT);
ntype.ui_name = "Invert Color";
ntype.enum_name_legacy = "INVERT";
ntype.nclass = NODE_CLASS_OP_COLOR;
bke::node_type_socket_templates(&ntype, inputs, outputs);
ntype.exec_fn = exec;
bke::node_register_type(ntype);
}
} // namespace blender

View File

@@ -0,0 +1,403 @@
/* SPDX-FileCopyrightText: 2005 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup texnodes
*/
#include "BLI_listbase.h"
#include "BLI_math_rotation.h"
#include "node_texture_util.hh"
#include "node_util.hh"
namespace blender {
/* **************** SCALAR MATH ******************** */
static bke::bNodeSocketTemplate inputs[] = {
{SOCK_FLOAT, N_("Value"), 0.5f, 0.5f, 0.5f, 1.0f, -100.0f, 100.0f, PROP_NONE},
{SOCK_FLOAT, N_("Value"), 0.5f, 0.5f, 0.5f, 1.0f, -100.0f, 100.0f, PROP_NONE},
{SOCK_FLOAT, N_("Value"), 0.0f, 0.5f, 0.5f, 1.0f, -100.0f, 100.0f, PROP_NONE},
{-1, ""},
};
static bke::bNodeSocketTemplate outputs[] = {
{SOCK_FLOAT, N_("Value")},
{-1, ""},
};
static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread)
{
float in0 = tex_input_value(in[0], p, thread);
float in1 = tex_input_value(in[1], p, thread);
switch (node->custom1) {
case NODE_MATH_ADD:
*out = in0 + in1;
break;
case NODE_MATH_SUBTRACT:
*out = in0 - in1;
break;
case NODE_MATH_MULTIPLY:
*out = in0 * in1;
break;
case NODE_MATH_DIVIDE: {
if (in1 == 0) {
/* We don't want to divide by zero. */
*out = 0.0;
}
else {
*out = in0 / in1;
}
break;
}
case NODE_MATH_SINE: {
*out = sinf(in0);
break;
}
case NODE_MATH_COSINE: {
*out = cosf(in0);
break;
}
case NODE_MATH_TANGENT: {
*out = tanf(in0);
break;
}
case NODE_MATH_SINH: {
*out = sinhf(in0);
break;
}
case NODE_MATH_COSH: {
*out = coshf(in0);
break;
}
case NODE_MATH_TANH: {
*out = tanhf(in0);
break;
}
case NODE_MATH_ARCSINE: {
/* Can't do the impossible... */
if (in0 <= 1 && in0 >= -1) {
*out = asinf(in0);
}
else {
*out = 0.0;
}
break;
}
case NODE_MATH_ARCCOSINE: {
/* Can't do the impossible... */
if (in0 <= 1 && in0 >= -1) {
*out = acosf(in0);
}
else {
*out = 0.0;
}
break;
}
case NODE_MATH_ARCTANGENT: {
*out = atan(in0);
break;
}
case NODE_MATH_POWER: {
/* Only raise negative numbers by full integers */
if (in0 >= 0) {
out[0] = pow(in0, in1);
}
else {
float y_mod_1 = fmod(in1, 1);
if (y_mod_1 > 0.999f || y_mod_1 < 0.001f) {
*out = pow(in0, floor(in1 + 0.5f));
}
else {
*out = 0.0;
}
}
break;
}
case NODE_MATH_LOGARITHM: {
/* Don't want any imaginary numbers... */
if (in0 > 0 && in1 > 0) {
*out = log(in0) / log(in1);
}
else {
*out = 0.0;
}
break;
}
case NODE_MATH_MINIMUM: {
if (in0 < in1) {
*out = in0;
}
else {
*out = in1;
}
break;
}
case NODE_MATH_MAXIMUM: {
if (in0 > in1) {
*out = in0;
}
else {
*out = in1;
}
break;
}
case NODE_MATH_ROUND: {
*out = (in0 < 0) ? int(in0 - 0.5f) : int(in0 + 0.5f);
break;
}
case NODE_MATH_LESS_THAN: {
if (in0 < in1) {
*out = 1.0f;
}
else {
*out = 0.0f;
}
break;
}
case NODE_MATH_GREATER_THAN: {
if (in0 > in1) {
*out = 1.0f;
}
else {
*out = 0.0f;
}
break;
}
case NODE_MATH_MODULO: {
if (in1 == 0.0f) {
*out = 0.0f;
}
else {
*out = fmod(in0, in1);
}
break;
}
case NODE_MATH_FLOORED_MODULO: {
if (in1 == 0.0f) {
*out = 0.0f;
}
else {
*out = in0 - floorf(in0 / in1) * in1;
}
break;
}
case NODE_MATH_ABSOLUTE: {
*out = fabsf(in0);
break;
}
case NODE_MATH_RADIANS: {
*out = DEG2RADF(in0);
break;
}
case NODE_MATH_DEGREES: {
*out = RAD2DEGF(in0);
break;
}
case NODE_MATH_ARCTAN2: {
*out = atan2(in0, in1);
break;
}
case NODE_MATH_SIGN: {
*out = compatible_signf(in0);
break;
}
case NODE_MATH_EXPONENT: {
*out = expf(in0);
break;
}
case NODE_MATH_FLOOR: {
*out = floorf(in0);
break;
}
case NODE_MATH_CEIL: {
*out = ceilf(in0);
break;
}
case NODE_MATH_FRACTION: {
*out = in0 - floorf(in0);
break;
}
case NODE_MATH_SQRT: {
if (in0 > 0.0f) {
*out = sqrtf(in0);
}
else {
*out = 0.0f;
}
break;
}
case NODE_MATH_INV_SQRT: {
if (in0 > 0.0f) {
*out = 1.0f / sqrtf(in0);
}
else {
*out = 0.0f;
}
break;
}
case NODE_MATH_TRUNC: {
if (in0 > 0.0f) {
*out = floorf(in0);
}
else {
*out = ceilf(in0);
}
break;
}
case NODE_MATH_SNAP: {
if (in1 == 0) {
*out = 0.0;
}
else {
*out = floorf(in0 / in1) * in1;
}
break;
}
case NODE_MATH_WRAP: {
float in2 = tex_input_value(in[2], p, thread);
*out = wrapf(in0, in1, in2);
break;
}
case NODE_MATH_PINGPONG: {
*out = pingpongf(in0, in1);
break;
}
case NODE_MATH_COMPARE: {
float in2 = tex_input_value(in[2], p, thread);
*out = (fabsf(in0 - in1) <= std::max(in2, 1e-5f)) ? 1.0f : 0.0f;
break;
}
case NODE_MATH_MULTIPLY_ADD: {
float in2 = tex_input_value(in[2], p, thread);
*out = in0 * in1 + in2;
break;
}
case NODE_MATH_SMOOTH_MIN: {
float in2 = tex_input_value(in[2], p, thread);
*out = smoothminf(in0, in1, in2);
break;
}
case NODE_MATH_SMOOTH_MAX: {
float in2 = tex_input_value(in[2], p, thread);
*out = -smoothminf(-in0, -in1, in2);
break;
}
default: {
BLI_assert(0);
break;
}
}
if (node->custom2 & SHD_MATH_CLAMP) {
CLAMP(*out, 0.0f, 1.0f);
}
}
static void node_update(bNodeTree *ntree, bNode *node)
{
node_math_update(ntree, node);
bNodeSocket *sock1 = static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 0));
bNodeSocket *sock2 = static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 1));
bNodeSocket *sock3 = static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 2));
node_sock_label_clear(sock1);
node_sock_label_clear(sock2);
node_sock_label_clear(sock3);
switch (node->custom1) {
case NODE_MATH_WRAP:
node_sock_label(sock2, "Max");
node_sock_label(sock3, "Min");
break;
case NODE_MATH_MULTIPLY_ADD:
node_sock_label(sock2, "Multiplier");
node_sock_label(sock3, "Addend");
break;
case NODE_MATH_LESS_THAN:
case NODE_MATH_GREATER_THAN:
node_sock_label(sock2, "Threshold");
break;
case NODE_MATH_PINGPONG:
node_sock_label(sock2, "Scale");
break;
case NODE_MATH_SNAP:
node_sock_label(sock2, "Increment");
break;
case NODE_MATH_POWER:
node_sock_label(sock1, "Base");
node_sock_label(sock2, "Exponent");
break;
case NODE_MATH_LOGARITHM:
node_sock_label(sock2, "Base");
break;
case NODE_MATH_DEGREES:
node_sock_label(sock1, "Radians");
break;
case NODE_MATH_RADIANS:
node_sock_label(sock1, "Degrees");
break;
case NODE_MATH_COMPARE:
node_sock_label(sock3, "Epsilon");
break;
case NODE_MATH_SMOOTH_MAX:
case NODE_MATH_SMOOTH_MIN:
node_sock_label(sock3, "Distance");
break;
}
}
static void exec(void *data,
int /*thread*/,
bNode *node,
bNodeExecData *execdata,
bNodeStack **in,
bNodeStack **out)
{
tex_output(node, execdata, in, out[0], &valuefn, static_cast<TexCallData *>(data));
}
void register_node_type_tex_math()
{
static bke::bNodeType ntype;
tex_node_type_base(&ntype, "TextureNodeMath"_ustr, TEX_NODE_MATH);
ntype.ui_name = "Math";
ntype.enum_name_legacy = "MATH";
ntype.nclass = NODE_CLASS_CONVERTER;
bke::node_type_socket_templates(&ntype, inputs, outputs);
ntype.labelfunc = node_math_label;
ntype.exec_fn = exec;
ntype.updatefunc = node_update;
bke::node_register_type(ntype);
}
} // namespace blender

View File

@@ -0,0 +1,74 @@
/* SPDX-FileCopyrightText: 2005 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup texnodes
*/
#include "node_texture_util.hh"
#include "node_util.hh"
#include "BKE_material.hh"
#include "BLI_math_vector.h"
namespace blender {
/* **************** MIX RGB ******************** */
static bke::bNodeSocketTemplate inputs[] = {
{SOCK_FLOAT, N_("Factor"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE},
{SOCK_RGBA, N_("Color1"), 0.5f, 0.5f, 0.5f, 1.0f},
{SOCK_RGBA, N_("Color2"), 0.5f, 0.5f, 0.5f, 1.0f},
{-1, ""},
};
static bke::bNodeSocketTemplate outputs[] = {
{SOCK_RGBA, N_("Color")},
{-1, ""},
};
static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread)
{
float fac = tex_input_value(in[0], p, thread);
float col1[4], col2[4];
tex_input_rgba(col1, in[1], p, thread);
tex_input_rgba(col2, in[2], p, thread);
/* use alpha */
if (node->custom2 & 1) {
fac *= col2[3];
}
CLAMP(fac, 0.0f, 1.0f);
copy_v4_v4(out, col1);
ramp_blend(node->custom1, out, fac, col2);
}
static void exec(void *data,
int /*thread*/,
bNode *node,
bNodeExecData *execdata,
bNodeStack **in,
bNodeStack **out)
{
tex_output(node, execdata, in, out[0], &colorfn, static_cast<TexCallData *>(data));
}
void register_node_type_tex_mix_rgb()
{
static bke::bNodeType ntype;
tex_node_type_base(&ntype, "TextureNodeMixRGB"_ustr, TEX_NODE_MIX_RGB);
ntype.ui_name = "Mix";
ntype.enum_name_legacy = "MIX_RGB";
ntype.nclass = NODE_CLASS_OP_COLOR;
bke::node_type_socket_templates(&ntype, inputs, outputs);
ntype.labelfunc = node_blend_label;
ntype.exec_fn = exec;
bke::node_register_type(ntype);
}
} // namespace blender

View File

@@ -0,0 +1,159 @@
/* SPDX-FileCopyrightText: 2006 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup texnodes
*/
#include <algorithm>
#include "BLI_string.h"
#include "node_texture_util.hh"
#include "node_util.hh"
namespace blender {
/* **************** COMPOSITE ******************** */
static bke::bNodeSocketTemplate inputs[] = {
{SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f},
{-1, ""},
};
/* applies to render pipeline */
static void exec(void *data,
int /*thread*/,
bNode *node,
bNodeExecData * /*execdata*/,
bNodeStack **in,
bNodeStack ** /*out*/)
{
TexCallData *cdata = static_cast<TexCallData *>(data);
TexResult *target = cdata->target;
if (cdata->do_preview) {
TexParams params;
params_from_cdata(&params, cdata);
tex_input_rgba(target->trgba, in[0], &params, cdata->thread);
}
else {
/* 0 means don't care, so just use first */
if (cdata->which_output == node->custom1 || (cdata->which_output == 0 && node->custom1 == 1)) {
TexParams params;
params_from_cdata(&params, cdata);
tex_input_rgba(target->trgba, in[0], &params, cdata->thread);
target->tin = (target->trgba[0] + target->trgba[1] + target->trgba[2]) / 3.0f;
target->talpha = true;
}
}
}
static void unique_name(bNode *node)
{
TexNodeOutput *tno = static_cast<TexNodeOutput *>(node->storage);
char new_name[sizeof(tno->name)];
int new_len = 0;
int suffix;
bNode *i;
const char *name = tno->name;
new_name[0] = '\0';
i = node;
while (i->prev) {
i = i->prev;
}
for (; i; i = i->next) {
if (i == node || i->type_legacy != TEX_NODE_OUTPUT ||
!STREQ(name, ((TexNodeOutput *)(i->storage))->name))
{
continue;
}
if (new_name[0] == '\0') {
int len = strlen(name);
if (len >= 4 && sscanf(name + len - 4, ".%03d", &suffix) == 1) {
new_len = len;
}
else {
suffix = 0;
new_len = len + 4;
new_len = std::min<ulong>(new_len, sizeof(tno->name) - 1);
}
STRNCPY(new_name, name);
name = new_name;
}
int name_ofs = new_len - 4;
BLI_snprintf(new_name + name_ofs, sizeof(new_name) - name_ofs, ".%03d", ++suffix);
}
if (new_name[0] != '\0') {
STRNCPY(tno->name, new_name);
}
}
static void assign_index(bNode *node)
{
bNode *tnode;
int index = 1;
tnode = node;
while (tnode->prev) {
tnode = tnode->prev;
}
check_index:
for (; tnode; tnode = tnode->next) {
if (tnode->type_legacy == TEX_NODE_OUTPUT && tnode != node) {
if (tnode->custom1 == index) {
index++;
goto check_index;
}
}
}
node->custom1 = index;
}
static void init(bNodeTree * /*ntree*/, bNode *node)
{
TexNodeOutput *tno = MEM_new<TexNodeOutput>("TEX_output");
node->storage = tno;
STRNCPY(tno->name, "Default");
unique_name(node);
assign_index(node);
}
static void copy(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node)
{
node_copy_standard_storage(dest_ntree, dest_node, src_node);
unique_name(dest_node);
assign_index(dest_node);
}
void register_node_type_tex_output()
{
static bke::bNodeType ntype;
tex_node_type_base(&ntype, "TextureNodeOutput"_ustr, TEX_NODE_OUTPUT);
ntype.ui_name = "Output";
ntype.enum_name_legacy = "OUTPUT";
ntype.nclass = NODE_CLASS_OUTPUT;
bke::node_type_socket_templates(&ntype, inputs, nullptr);
ntype.default_width = bke::NodeWidth::_160;
ntype.initfunc = init;
bke::node_type_storage(ntype, "TexNodeOutput", node_free_standard_storage, copy);
ntype.exec_fn = exec;
ntype.flag |= NODE_PREVIEW;
ntype.no_muting = true;
bke::node_register_type(ntype);
}
} // namespace blender

View File

@@ -0,0 +1,282 @@
/* SPDX-FileCopyrightText: 2005 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup texnodes
*/
#include "BKE_material.hh"
#include "BKE_texture.h"
#include "BLI_listbase.h"
#include "BLI_math_vector.h"
#include "DNA_material_types.h"
#include "node_texture_util.hh"
#include "node_util.hh"
#include "RE_texture.h"
namespace blender {
/*
* In this file: wrappers to use procedural textures as nodes
*/
static bke::bNodeSocketTemplate outputs_both[] = {{SOCK_RGBA, N_("Color"), 1.0f, 0.0f, 0.0f, 1.0f},
{-1, ""}};
static bke::bNodeSocketTemplate outputs_color_only[] = {{SOCK_RGBA, N_("Color")}, {-1, ""}};
/* Inputs common to all, #defined because nodes will need their own inputs too */
#define I 2 /* count */
#define COMMON_INPUTS \
{SOCK_RGBA, "Color 1", 0.0f, 0.0f, 0.0f, 1.0f}, {SOCK_RGBA, "Color 2", 1.0f, 1.0f, 1.0f, 1.0f}
/* Calls multitex and copies the result to the outputs.
* Called by xxx_exec, which handles inputs. */
static void do_proc(float *result,
TexParams *p,
const float col1[4],
const float col2[4],
Tex *tex,
const short thread)
{
TexResult texres;
int textype;
textype = multitex_nodes(tex, p->co, &texres, thread, 0, p->mtex, nullptr);
if (textype & TEX_RGB) {
copy_v4_v4(result, texres.trgba);
}
else {
copy_v4_v4(result, col1);
ramp_blend(MA_RAMP_BLEND, result, texres.tin, col2);
}
}
using MapFn = void (*)(Tex *tex, bNodeStack **in, TexParams *p, const short thread);
static void texfn(
float *result, TexParams *p, bNode *node, bNodeStack **in, MapFn map_inputs, short thread)
{
Tex tex = dna::shallow_copy(*(static_cast<Tex *>(node->storage)));
float col1[4], col2[4];
tex_input_rgba(col1, in[0], p, thread);
tex_input_rgba(col2, in[1], p, thread);
map_inputs(&tex, in, p, thread);
do_proc(result, p, col1, col2, &tex, thread);
}
static int count_outputs(bNode *node)
{
return node->outputs.count();
}
/* Boilerplate generators */
#define ProcNoInputs(name) \
static void name##_map_inputs( \
Tex * /*tex*/, bNodeStack ** /*in*/, TexParams * /*p*/, short /*thread*/) \
{ \
}
#define ProcDef(name) \
static void name##_colorfn( \
float *result, TexParams *p, bNode *node, bNodeStack **in, short thread) \
{ \
texfn(result, p, node, in, &name##_map_inputs, thread); \
} \
static void name##_exec(void *data, \
int /*thread*/, \
bNode *node, \
bNodeExecData *execdata, \
bNodeStack **in, \
bNodeStack **out) \
{ \
int outs = count_outputs(node); \
if (outs >= 1) { \
tex_output(node, execdata, in, out[0], &name##_colorfn, static_cast<TexCallData *>(data)); \
} \
}
/* --- VORONOI -- */
static bke::bNodeSocketTemplate voronoi_inputs[] = {
COMMON_INPUTS,
{SOCK_FLOAT, N_("W1"), 1.0f, 0.0f, 0.0f, 0.0f, -2.0f, 2.0f, PROP_NONE},
{SOCK_FLOAT, N_("W2"), 0.0f, 0.0f, 0.0f, 0.0f, -2.0f, 2.0f, PROP_NONE},
{SOCK_FLOAT, N_("W3"), 0.0f, 0.0f, 0.0f, 0.0f, -2.0f, 2.0f, PROP_NONE},
{SOCK_FLOAT, N_("W4"), 0.0f, 0.0f, 0.0f, 0.0f, -2.0f, 2.0f, PROP_NONE},
{SOCK_FLOAT, N_("iScale"), 1.0f, 0.0f, 0.0f, 0.0f, 0.01f, 10.0f, PROP_UNSIGNED},
{SOCK_FLOAT, N_("Size"), 0.25f, 0.0f, 0.0f, 0.0f, 0.0001f, 4.0f, PROP_UNSIGNED},
{-1, ""}};
static void voronoi_map_inputs(Tex *tex, bNodeStack **in, TexParams *p, short thread)
{
tex->vn_w1 = tex_input_value(in[I + 0], p, thread);
tex->vn_w2 = tex_input_value(in[I + 1], p, thread);
tex->vn_w3 = tex_input_value(in[I + 2], p, thread);
tex->vn_w4 = tex_input_value(in[I + 3], p, thread);
tex->ns_outscale = tex_input_value(in[I + 4], p, thread);
tex->noisesize = tex_input_value(in[I + 5], p, thread);
}
ProcDef(voronoi);
/* --- BLEND -- */
static bke::bNodeSocketTemplate blend_inputs[] = {COMMON_INPUTS, {-1, ""}};
ProcNoInputs(blend);
ProcDef(blend);
/* -- MAGIC -- */
static bke::bNodeSocketTemplate magic_inputs[] = {
COMMON_INPUTS,
{SOCK_FLOAT, N_("Turbulence"), 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 200.0f, PROP_UNSIGNED},
{-1, ""}};
static void magic_map_inputs(Tex *tex, bNodeStack **in, TexParams *p, short thread)
{
tex->turbul = tex_input_value(in[I + 0], p, thread);
}
ProcDef(magic);
/* --- MARBLE --- */
static bke::bNodeSocketTemplate marble_inputs[] = {
COMMON_INPUTS,
{SOCK_FLOAT, N_("Size"), 0.25f, 0.0f, 0.0f, 0.0f, 0.0001f, 2.0f, PROP_UNSIGNED},
{SOCK_FLOAT, N_("Turbulence"), 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 200.0f, PROP_UNSIGNED},
{-1, ""}};
static void marble_map_inputs(Tex *tex, bNodeStack **in, TexParams *p, short thread)
{
tex->noisesize = tex_input_value(in[I + 0], p, thread);
tex->turbul = tex_input_value(in[I + 1], p, thread);
}
ProcDef(marble);
/* --- CLOUDS --- */
static bke::bNodeSocketTemplate clouds_inputs[] = {
COMMON_INPUTS,
{SOCK_FLOAT, N_("Size"), 0.25f, 0.0f, 0.0f, 0.0f, 0.0001f, 2.0f, PROP_UNSIGNED},
{-1, ""}};
static void clouds_map_inputs(Tex *tex, bNodeStack **in, TexParams *p, short thread)
{
tex->noisesize = tex_input_value(in[I + 0], p, thread);
}
ProcDef(clouds);
/* --- DISTORTED NOISE --- */
static bke::bNodeSocketTemplate distnoise_inputs[] = {
COMMON_INPUTS,
{SOCK_FLOAT, N_("Size"), 0.25f, 0.0f, 0.0f, 0.0f, 0.0001f, 2.0f, PROP_UNSIGNED},
{SOCK_FLOAT, N_("Distortion"), 1.00f, 0.0f, 0.0f, 0.0f, 0.0000f, 10.0f, PROP_UNSIGNED},
{-1, ""}};
static void distnoise_map_inputs(Tex *tex, bNodeStack **in, TexParams *p, short thread)
{
tex->noisesize = tex_input_value(in[I + 0], p, thread);
tex->dist_amount = tex_input_value(in[I + 1], p, thread);
}
ProcDef(distnoise);
/* --- WOOD --- */
static bke::bNodeSocketTemplate wood_inputs[] = {
COMMON_INPUTS,
{SOCK_FLOAT, N_("Size"), 0.25f, 0.0f, 0.0f, 0.0f, 0.0001f, 2.0f, PROP_UNSIGNED},
{SOCK_FLOAT, N_("Turbulence"), 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 200.0f, PROP_UNSIGNED},
{-1, ""}};
static void wood_map_inputs(Tex *tex, bNodeStack **in, TexParams *p, short thread)
{
tex->noisesize = tex_input_value(in[I + 0], p, thread);
tex->turbul = tex_input_value(in[I + 1], p, thread);
}
ProcDef(wood);
/* --- MUSGRAVE --- */
static bke::bNodeSocketTemplate musgrave_inputs[] = {
COMMON_INPUTS,
{SOCK_FLOAT, N_("H"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0001f, 2.0f, PROP_UNSIGNED},
{SOCK_FLOAT, N_("Lacunarity"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 6.0f, PROP_UNSIGNED},
{SOCK_FLOAT, N_("Octaves"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 8.0f, PROP_UNSIGNED},
{SOCK_FLOAT, N_("iScale"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 10.0f, PROP_UNSIGNED},
{SOCK_FLOAT, N_("Size"), 0.25f, 0.0f, 0.0f, 0.0f, 0.0001f, 2.0f, PROP_UNSIGNED},
{-1, ""}};
static void musgrave_map_inputs(Tex *tex, bNodeStack **in, TexParams *p, short thread)
{
tex->mg_H = tex_input_value(in[I + 0], p, thread);
tex->mg_lacunarity = tex_input_value(in[I + 1], p, thread);
tex->mg_octaves = tex_input_value(in[I + 2], p, thread);
tex->ns_outscale = tex_input_value(in[I + 3], p, thread);
tex->noisesize = tex_input_value(in[I + 4], p, thread);
}
ProcDef(musgrave);
/* --- NOISE --- */
static bke::bNodeSocketTemplate noise_inputs[] = {COMMON_INPUTS, {-1, ""}};
ProcNoInputs(noise);
ProcDef(noise);
/* --- STUCCI --- */
static bke::bNodeSocketTemplate stucci_inputs[] = {
COMMON_INPUTS,
{SOCK_FLOAT, N_("Size"), 0.25f, 0.0f, 0.0f, 0.0f, 0.0001f, 2.0f, PROP_UNSIGNED},
{SOCK_FLOAT, N_("Turbulence"), 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 200.0f, PROP_UNSIGNED},
{-1, ""}};
static void stucci_map_inputs(Tex *tex, bNodeStack **in, TexParams *p, short thread)
{
tex->noisesize = tex_input_value(in[I + 0], p, thread);
tex->turbul = tex_input_value(in[I + 1], p, thread);
}
ProcDef(stucci);
/* --- */
static void init(bNodeTree * /*ntree*/, bNode *node)
{
Tex *tex = MEM_new<Tex>("Tex");
node->storage = tex;
BKE_texture_default(tex);
tex->type = eTex_Type(node->type_legacy - TEX_NODE_PROC);
if (tex->type == TEX_WOOD) {
tex->stype = TEX_BANDNOISE;
}
}
/* Node type definitions */
#define TexDef(TEXTYPE, idname, outputs, name, Name, EnumNameLegacy) \
void register_node_type_tex_proc_##name(void) \
{ \
static bke::bNodeType ntype; \
\
tex_node_type_base(&ntype, UString(idname), TEX_NODE_PROC + TEXTYPE); \
ntype.ui_name = Name; \
ntype.enum_name_legacy = EnumNameLegacy; \
ntype.nclass = NODE_CLASS_TEXTURE; \
bke::node_type_socket_templates(&ntype, name##_inputs, outputs); \
ntype.default_width = bke::NodeWidth::_160; \
ntype.initfunc = init; \
bke::node_type_storage(ntype, "Tex", node_free_standard_storage, node_copy_standard_storage); \
ntype.exec_fn = name##_exec; \
ntype.flag |= NODE_PREVIEW; \
\
bke::node_register_type(ntype); \
}
#define C outputs_color_only
#define CV outputs_both
TexDef(TEX_VORONOI, "TextureNodeTexVoronoi", CV, voronoi, "Voronoi", "TEX_VORONOI");
TexDef(TEX_BLEND, "TextureNodeTexBlend", C, blend, "Blend", "TEX_BLEND");
TexDef(TEX_MAGIC, "TextureNodeTexMagic", C, magic, "Magic", "TEX_MAGIC");
TexDef(TEX_MARBLE, "TextureNodeTexMarble", CV, marble, "Marble", "TEX_MARBLE");
TexDef(TEX_CLOUDS, "TextureNodeTexClouds", CV, clouds, "Clouds", "TEX_CLOUDS");
TexDef(TEX_WOOD, "TextureNodeTexWood", CV, wood, "Wood", "TEX_WOOD");
TexDef(TEX_MUSGRAVE, "TextureNodeTexMusgrave", CV, musgrave, "Musgrave", "TEX_MUSGRAVE");
TexDef(TEX_NOISE, "TextureNodeTexNoise", C, noise, "Noise", "TEX_NOISE");
TexDef(TEX_STUCCI, "TextureNodeTexStucci", CV, stucci, "Stucci", "TEX_STUCCI");
TexDef(
TEX_DISTNOISE, "TextureNodeTexDistNoise", CV, distnoise, "Distorted Noise", "TEX_DISTNOISE");
} // namespace blender

View File

@@ -0,0 +1,90 @@
/* SPDX-FileCopyrightText: 2005 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup texnodes
*/
#include <cmath>
#include "BLI_math_vector.h"
#include "node_texture_util.hh"
namespace blender {
static bke::bNodeSocketTemplate inputs[] = {
{SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f},
{SOCK_FLOAT, N_("Turns"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, PROP_NONE},
{SOCK_VECTOR, N_("Axis"), 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 1.0f, PROP_DIRECTION},
{-1, ""},
};
static bke::bNodeSocketTemplate outputs[] = {
{SOCK_RGBA, N_("Color")},
{-1, ""},
};
static void rotate(float new_co[3], float a, const float ax[3], const float co[3])
{
float para[3];
float perp[3];
float cp[3];
float cos_a = cosf(a * float(2 * M_PI));
float sin_a = sinf(a * float(2 * M_PI));
/* `x' = xcosa + n(n.x)(1-cosa) + (x*n)sina`. */
mul_v3_v3fl(perp, co, cos_a);
mul_v3_v3fl(para, ax, dot_v3v3(co, ax) * (1 - cos_a));
cross_v3_v3v3(cp, ax, co);
mul_v3_fl(cp, sin_a);
new_co[0] = para[0] + perp[0] + cp[0];
new_co[1] = para[1] + perp[1] + cp[1];
new_co[2] = para[2] + perp[2] + cp[2];
}
static void colorfn(float *out, TexParams *p, bNode * /*node*/, bNodeStack **in, short thread)
{
float new_co[3], a, ax[3];
a = tex_input_value(in[1], p, thread);
tex_input_vec(ax, in[2], p, thread);
rotate(new_co, a, ax, p->co);
{
TexParams np = *p;
np.co = new_co;
tex_input_rgba(out, in[0], &np, thread);
}
}
static void exec(void *data,
int /*thread*/,
bNode *node,
bNodeExecData *execdata,
bNodeStack **in,
bNodeStack **out)
{
tex_output(node, execdata, in, out[0], &colorfn, static_cast<TexCallData *>(data));
}
void register_node_type_tex_rotate()
{
static bke::bNodeType ntype;
tex_node_type_base(&ntype, "TextureNodeRotate"_ustr, TEX_NODE_ROTATE);
ntype.ui_name = "Rotate";
ntype.enum_name_legacy = "ROTATE";
ntype.nclass = NODE_CLASS_DISTORT;
bke::node_type_socket_templates(&ntype, inputs, outputs);
ntype.exec_fn = exec;
bke::node_register_type(ntype);
}
} // namespace blender

View File

@@ -0,0 +1,65 @@
/* SPDX-FileCopyrightText: 2005 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup texnodes
*/
#include "BLI_math_vector.h"
#include "BKE_node.hh"
#include "node_texture_util.hh"
namespace blender {
static bke::bNodeSocketTemplate inputs[] = {
{SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f},
{SOCK_VECTOR, N_("Scale"), 1.0f, 1.0f, 1.0f, 0.0f, -10.0f, 10.0f, PROP_XYZ},
{-1, ""},
};
static bke::bNodeSocketTemplate outputs[] = {
{SOCK_RGBA, N_("Color")},
{-1, ""},
};
static void colorfn(float *out, TexParams *p, bNode * /*node*/, bNodeStack **in, short thread)
{
float scale[3], new_co[3];
TexParams np = *p;
np.co = new_co;
tex_input_vec(scale, in[1], p, thread);
mul_v3_v3v3(new_co, p->co, scale);
tex_input_rgba(out, in[0], &np, thread);
}
static void exec(void *data,
int /*thread*/,
bNode *node,
bNodeExecData *execdata,
bNodeStack **in,
bNodeStack **out)
{
tex_output(node, execdata, in, out[0], &colorfn, static_cast<TexCallData *>(data));
}
void register_node_type_tex_scale()
{
static bke::bNodeType ntype;
tex_node_type_base(&ntype, "TextureNodeScale"_ustr, TEX_NODE_SCALE);
ntype.ui_name = "Scale";
ntype.enum_name_legacy = "SCALE";
ntype.nclass = NODE_CLASS_DISTORT;
bke::node_type_socket_templates(&ntype, inputs, outputs);
ntype.exec_fn = exec;
bke::node_register_type(ntype);
}
} // namespace blender

View File

@@ -0,0 +1,110 @@
/* SPDX-FileCopyrightText: 2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup texnodes
*/
#include "BLI_math_color.h"
#include "node_texture_util.hh"
#include "node_util.hh"
namespace blender {
static bke::bNodeSocketTemplate inputs[] = {
{SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f},
{-1, ""},
};
static bke::bNodeSocketTemplate outputs[] = {
{SOCK_FLOAT, N_("Red")},
{SOCK_FLOAT, N_("Green")},
{SOCK_FLOAT, N_("Blue")},
{SOCK_FLOAT, N_("Alpha")},
{-1, ""},
};
static void apply_color_space(float *out, NodeCombSepColorMode type)
{
switch (type) {
case NODE_COMBSEP_COLOR_RGB: {
/* Pass */
break;
}
case NODE_COMBSEP_COLOR_HSV: {
rgb_to_hsv_v(out, out);
break;
}
case NODE_COMBSEP_COLOR_HSL: {
rgb_to_hsl_v(out, out);
break;
}
default: {
BLI_assert_unreachable();
break;
}
}
}
static void valuefn_r(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread)
{
tex_input_rgba(out, in[0], p, thread);
apply_color_space(out, NodeCombSepColorMode(node->custom1));
*out = out[0];
}
static void valuefn_g(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread)
{
tex_input_rgba(out, in[0], p, thread);
apply_color_space(out, NodeCombSepColorMode(node->custom1));
*out = out[1];
}
static void valuefn_b(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread)
{
tex_input_rgba(out, in[0], p, thread);
apply_color_space(out, NodeCombSepColorMode(node->custom1));
*out = out[2];
}
static void valuefn_a(float *out, TexParams *p, bNode * /*node*/, bNodeStack **in, short thread)
{
tex_input_rgba(out, in[0], p, thread);
*out = out[3];
}
static void update(bNodeTree * /*ntree*/, bNode *node)
{
node_combsep_color_label(&node->outputs, NodeCombSepColorMode(node->custom1));
}
static void exec(void *data,
int /*thread*/,
bNode *node,
bNodeExecData *execdata,
bNodeStack **in,
bNodeStack **out)
{
TexCallData *tex_call_data = static_cast<TexCallData *>(data);
tex_output(node, execdata, in, out[0], &valuefn_r, tex_call_data);
tex_output(node, execdata, in, out[1], &valuefn_g, tex_call_data);
tex_output(node, execdata, in, out[2], &valuefn_b, tex_call_data);
tex_output(node, execdata, in, out[3], &valuefn_a, tex_call_data);
}
void register_node_type_tex_separate_color()
{
static bke::bNodeType ntype;
tex_node_type_base(&ntype, "TextureNodeSeparateColor"_ustr, TEX_NODE_SEPARATE_COLOR);
ntype.ui_name = "Separate Color";
ntype.enum_name_legacy = "SEPARATE_COLOR";
ntype.nclass = NODE_CLASS_OP_COLOR;
bke::node_type_socket_templates(&ntype, inputs, outputs);
ntype.exec_fn = exec;
ntype.updatefunc = update;
bke::node_register_type(ntype);
}
} // namespace blender

View File

@@ -0,0 +1,91 @@
/* SPDX-FileCopyrightText: 2005 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup texnodes
*/
#include "node_texture_util.hh"
#include "BKE_material.hh"
#include "BKE_node_runtime.hh"
#include "BLI_math_vector.h"
#include "DNA_material_types.h"
#include "RE_texture.h"
namespace blender {
static bke::bNodeSocketTemplate inputs[] = {
{SOCK_RGBA, N_("Color1"), 1.0f, 1.0f, 1.0f, 1.0f},
{SOCK_RGBA, N_("Color2"), 0.0f, 0.0f, 0.0f, 1.0f},
{-1, ""},
};
static bke::bNodeSocketTemplate outputs[] = {
{SOCK_RGBA, N_("Color")},
{-1, ""},
};
static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread)
{
Tex *nodetex = id_cast<Tex *>(node->id);
static float red[] = {1, 0, 0, 1};
static float white[] = {1, 1, 1, 1};
float co[3];
copy_v3_v3(co, p->co);
if (node->custom2 || node->runtime->need_exec == 0) {
/* this node refers to its own texture tree! */
copy_v4_v4(out, (fabsf(co[0] - co[1]) < 0.01f) ? white : red);
}
else if (nodetex) {
TexResult texres;
int textype;
float col1[4], col2[4];
tex_input_rgba(col1, in[0], p, thread);
tex_input_rgba(col2, in[1], p, thread);
textype = multitex_nodes(nodetex, co, &texres, thread, 0, p->mtex, nullptr);
if (textype & TEX_RGB) {
copy_v4_v4(out, texres.trgba);
}
else {
copy_v4_v4(out, col1);
ramp_blend(MA_RAMP_BLEND, out, texres.tin, col2);
}
}
}
static void exec(void *data,
int /*thread*/,
bNode *node,
bNodeExecData *execdata,
bNodeStack **in,
bNodeStack **out)
{
tex_output(node, execdata, in, out[0], &colorfn, static_cast<TexCallData *>(data));
}
void register_node_type_tex_texture()
{
static bke::bNodeType ntype;
tex_node_type_base(&ntype, "TextureNodeTexture"_ustr, TEX_NODE_TEXTURE);
ntype.ui_name = "Texture";
ntype.enum_name_legacy = "TEXTURE";
ntype.nclass = NODE_CLASS_INPUT;
bke::node_type_socket_templates(&ntype, inputs, outputs);
ntype.exec_fn = exec;
ntype.flag |= NODE_PREVIEW;
bke::node_register_type(ntype);
}
} // namespace blender

View File

@@ -0,0 +1,62 @@
/* SPDX-FileCopyrightText: 2005 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup texnodes
*/
#include "node_texture_util.hh"
namespace blender {
static bke::bNodeSocketTemplate inputs[] = {
{SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f},
{SOCK_VECTOR, N_("Offset"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f, PROP_TRANSLATION},
{-1, ""},
};
static bke::bNodeSocketTemplate outputs[] = {
{SOCK_RGBA, N_("Color")},
{-1, ""},
};
static void colorfn(float *out, TexParams *p, bNode * /*node*/, bNodeStack **in, short thread)
{
float offset[3], new_co[3];
TexParams np = *p;
np.co = new_co;
tex_input_vec(offset, in[1], p, thread);
new_co[0] = p->co[0] + offset[0];
new_co[1] = p->co[1] + offset[1];
new_co[2] = p->co[2] + offset[2];
tex_input_rgba(out, in[0], &np, thread);
}
static void exec(void *data,
int /*thread*/,
bNode *node,
bNodeExecData *execdata,
bNodeStack **in,
bNodeStack **out)
{
tex_output(node, execdata, in, out[0], &colorfn, static_cast<TexCallData *>(data));
}
void register_node_type_tex_translate()
{
static bke::bNodeType ntype;
tex_node_type_base(&ntype, "TextureNodeTranslate"_ustr, TEX_NODE_TRANSLATE);
ntype.ui_name = "Translate";
ntype.enum_name_legacy = "TRANSLATE";
ntype.nclass = NODE_CLASS_DISTORT;
bke::node_type_socket_templates(&ntype, inputs, outputs);
ntype.exec_fn = exec;
bke::node_register_type(ntype);
}
} // namespace blender

View File

@@ -0,0 +1,79 @@
/* SPDX-FileCopyrightText: 2005 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup texnodes
*/
#include "node_texture_util.hh"
namespace blender {
static bke::bNodeSocketTemplate inputs[] = {
{SOCK_FLOAT, N_("Val"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE},
{SOCK_FLOAT, N_("Nabla"), 0.025f, 0.0f, 0.0f, 0.0f, 0.001f, 0.1f, PROP_UNSIGNED},
{-1, ""},
};
static bke::bNodeSocketTemplate outputs[] = {
{SOCK_VECTOR, N_("Normal")},
{-1, ""},
};
static void normalfn(float *out, TexParams *p, bNode * /*node*/, bNodeStack **in, short thread)
{
float new_co[3];
const float *co = p->co;
float nabla = tex_input_value(in[1], p, thread);
float val;
float nor[3];
TexParams np = *p;
np.co = new_co;
val = tex_input_value(in[0], p, thread);
new_co[0] = co[0] + nabla;
new_co[1] = co[1];
new_co[2] = co[2];
nor[0] = tex_input_value(in[0], &np, thread);
new_co[0] = co[0];
new_co[1] = co[1] + nabla;
nor[1] = tex_input_value(in[0], &np, thread);
new_co[1] = co[1];
new_co[2] = co[2] + nabla;
nor[2] = tex_input_value(in[0], &np, thread);
out[0] = val - nor[0];
out[1] = val - nor[1];
out[2] = val - nor[2];
}
static void exec(void *data,
int /*thread*/,
bNode *node,
bNodeExecData *execdata,
bNodeStack **in,
bNodeStack **out)
{
tex_output(node, execdata, in, out[0], &normalfn, static_cast<TexCallData *>(data));
}
void register_node_type_tex_valtonor()
{
static bke::bNodeType ntype;
tex_node_type_base(&ntype, "TextureNodeValToNor"_ustr, TEX_NODE_VALTONOR);
ntype.ui_name = "Value to Normal";
ntype.enum_name_legacy = "VALTONOR";
ntype.nclass = NODE_CLASS_CONVERTER;
bke::node_type_socket_templates(&ntype, inputs, outputs);
ntype.exec_fn = exec;
bke::node_register_type(ntype);
}
} // namespace blender

View File

@@ -0,0 +1,110 @@
/* SPDX-FileCopyrightText: 2005 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup texnodes
*/
#include "BKE_colorband.hh"
#include "IMB_colormanagement.hh"
#include "node_texture_util.hh"
#include "node_util.hh"
namespace blender {
/* **************** VALTORGB ******************** */
static bke::bNodeSocketTemplate valtorgb_in[] = {
{SOCK_FLOAT, N_("Fac"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{-1, ""},
};
static bke::bNodeSocketTemplate valtorgb_out[] = {
{SOCK_RGBA, N_("Color")},
{-1, ""},
};
static void valtorgb_colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread)
{
if (node->storage) {
float fac = tex_input_value(in[0], p, thread);
BKE_colorband_evaluate(static_cast<const ColorBand *>(node->storage), fac, out);
}
}
static void valtorgb_exec(void *data,
int /*thread*/,
bNode *node,
bNodeExecData *execdata,
bNodeStack **in,
bNodeStack **out)
{
tex_output(node, execdata, in, out[0], &valtorgb_colorfn, static_cast<TexCallData *>(data));
}
static void valtorgb_init(bNodeTree * /*ntree*/, bNode *node)
{
node->storage = BKE_colorband_add(true);
}
void register_node_type_tex_valtorgb()
{
static bke::bNodeType ntype;
tex_node_type_base(&ntype, "TextureNodeValToRGB"_ustr, TEX_NODE_VALTORGB);
ntype.ui_name = "Color Ramp";
ntype.enum_name_legacy = "VALTORGB";
ntype.nclass = NODE_CLASS_CONVERTER;
bke::node_type_socket_templates(&ntype, valtorgb_in, valtorgb_out);
ntype.default_width = bke::NodeWidth::_240;
ntype.initfunc = valtorgb_init;
bke::node_type_storage(
ntype, "ColorBand", node_free_standard_storage, node_copy_standard_storage);
ntype.exec_fn = valtorgb_exec;
bke::node_register_type(ntype);
}
/* **************** RGBTOBW ******************** */
static bke::bNodeSocketTemplate rgbtobw_in[] = {
{SOCK_RGBA, N_("Color"), 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f},
{-1, ""},
};
static bke::bNodeSocketTemplate rgbtobw_out[] = {
{SOCK_FLOAT, N_("Val"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
{-1, ""},
};
static void rgbtobw_valuefn(
float *out, TexParams *p, bNode * /*node*/, bNodeStack **in, short thread)
{
float cin[4];
tex_input_rgba(cin, in[0], p, thread);
*out = IMB_colormanagement_get_luminance(cin);
}
static void rgbtobw_exec(void *data,
int /*thread*/,
bNode *node,
bNodeExecData *execdata,
bNodeStack **in,
bNodeStack **out)
{
tex_output(node, execdata, in, out[0], &rgbtobw_valuefn, static_cast<TexCallData *>(data));
}
void register_node_type_tex_rgbtobw()
{
static bke::bNodeType ntype;
tex_node_type_base(&ntype, "TextureNodeRGBToBW"_ustr, TEX_NODE_RGBTOBW);
ntype.ui_name = "RGB to BW";
ntype.enum_name_legacy = "RGBTOBW";
ntype.nclass = NODE_CLASS_CONVERTER;
bke::node_type_socket_templates(&ntype, rgbtobw_in, rgbtobw_out);
ntype.exec_fn = rgbtobw_exec;
bke::node_register_type(ntype);
}
} // namespace blender

View File

@@ -0,0 +1,53 @@
/* SPDX-FileCopyrightText: 2005 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup texnodes
*/
#include "node_texture_util.hh"
namespace blender {
static bke::bNodeSocketTemplate inputs[] = {
{SOCK_RGBA, N_("Color"), 1.0f, 0.0f, 0.0f, 1.0f},
{-1, ""},
};
static void exec(void *data,
int /*thread*/,
bNode * /*node*/,
bNodeExecData * /*execdata*/,
bNodeStack **in,
bNodeStack ** /*out*/)
{
TexCallData *cdata = static_cast<TexCallData *>(data);
if (cdata->do_preview) {
TexParams params;
float col[4];
params_from_cdata(&params, cdata);
tex_input_rgba(col, in[0], &params, cdata->thread);
}
}
void register_node_type_tex_viewer()
{
static bke::bNodeType ntype;
tex_node_type_base(&ntype, "TextureNodeViewer"_ustr, TEX_NODE_VIEWER);
ntype.ui_name = "Viewer";
ntype.enum_name_legacy = "VIEWER";
ntype.nclass = NODE_CLASS_OUTPUT;
bke::node_type_socket_templates(&ntype, inputs, nullptr);
ntype.exec_fn = exec;
ntype.no_muting = true;
ntype.flag |= NODE_PREVIEW;
bke::node_register_type(ntype);
}
} // namespace blender