This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/nodes/texture/nodes/node_texture_proc.c

312 lines
11 KiB
C

/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2005 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup texnodes
*/
#include "node_texture_util.h"
#include "NOD_texture.h"
#include "RE_shader_ext.h"
/*
* In this file: wrappers to use procedural textures as nodes
*/
static bNodeSocketTemplate outputs_both[] = {
{SOCK_RGBA, 0, N_("Color"), 1.0f, 0.0f, 0.0f, 1.0f},
{SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, PROP_DIRECTION},
{-1, 0, ""}};
static bNodeSocketTemplate outputs_color_only[] = {{SOCK_RGBA, 0, N_("Color")}, {-1, 0, ""}};
/* Inputs common to all, #defined because nodes will need their own inputs too */
#define I 2 /* count */
#define COMMON_INPUTS \
{SOCK_RGBA, 1, "Color 1", 0.0f, 0.0f, 0.0f, 1.0f}, \
{ \
SOCK_RGBA, 1, "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],
char is_normal,
Tex *tex,
const short thread)
{
TexResult texres;
int textype;
if (is_normal) {
texres.nor = result;
}
else {
texres.nor = NULL;
}
textype = multitex_nodes(
tex, p->co, p->dxt, p->dyt, p->osatex, &texres, thread, 0, p->mtex, NULL);
if (is_normal) {
return;
}
if (textype & TEX_RGB) {
copy_v4_v4(result, &texres.tr);
}
else {
copy_v4_v4(result, col1);
ramp_blend(MA_RAMP_BLEND, result, texres.tin, col2);
}
}
typedef void (*MapFn)(Tex *tex, bNodeStack **in, TexParams *p, const short thread);
static void texfn(float *result,
TexParams *p,
bNode *node,
bNodeStack **in,
char is_normal,
MapFn map_inputs,
short thread)
{
Tex tex = *((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, is_normal, &tex, thread);
}
static int count_outputs(bNode *node)
{
bNodeSocket *sock;
int num = 0;
for (sock = node->outputs.first; sock; sock = sock->next) {
num++;
}
return num;
}
/* Boilerplate generators */
#define ProcNoInputs(name) \
static void name##_map_inputs( \
Tex *UNUSED(tex), bNodeStack **UNUSED(in), TexParams *UNUSED(p), short UNUSED(thread)) \
{ \
}
#define ProcDef(name) \
static void name##_colorfn( \
float *result, TexParams *p, bNode *node, bNodeStack **in, short thread) \
{ \
texfn(result, p, node, in, 0, &name##_map_inputs, thread); \
} \
static void name##_normalfn( \
float *result, TexParams *p, bNode *node, bNodeStack **in, short thread) \
{ \
texfn(result, p, node, in, 1, &name##_map_inputs, thread); \
} \
static void name##_exec(void *data, \
int UNUSED(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, data); \
if (outs >= 2) \
tex_output(node, execdata, in, out[1], &name##_normalfn, data); \
}
/* --- VORONOI -- */
static bNodeSocketTemplate voronoi_inputs[] = {
COMMON_INPUTS,
{SOCK_FLOAT, 1, N_("W1"), 1.0f, 0.0f, 0.0f, 0.0f, -2.0f, 2.0f, PROP_NONE},
{SOCK_FLOAT, 1, N_("W2"), 0.0f, 0.0f, 0.0f, 0.0f, -2.0f, 2.0f, PROP_NONE},
{SOCK_FLOAT, 1, N_("W3"), 0.0f, 0.0f, 0.0f, 0.0f, -2.0f, 2.0f, PROP_NONE},
{SOCK_FLOAT, 1, N_("W4"), 0.0f, 0.0f, 0.0f, 0.0f, -2.0f, 2.0f, PROP_NONE},
{SOCK_FLOAT, 1, N_("iScale"), 1.0f, 0.0f, 0.0f, 0.0f, 0.01f, 10.0f, PROP_UNSIGNED},
{SOCK_FLOAT, 1, N_("Size"), 0.25f, 0.0f, 0.0f, 0.0f, 0.0001f, 4.0f, PROP_UNSIGNED},
{-1, 0, ""}};
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 bNodeSocketTemplate blend_inputs[] = {COMMON_INPUTS, {-1, 0, ""}};
ProcNoInputs(blend) ProcDef(blend)
/* -- MAGIC -- */
static bNodeSocketTemplate magic_inputs[] = {
COMMON_INPUTS,
{SOCK_FLOAT, 1, N_("Turbulence"), 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 200.0f, PROP_UNSIGNED},
{-1, 0, ""}};
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 bNodeSocketTemplate marble_inputs[] = {
COMMON_INPUTS,
{SOCK_FLOAT, 1, N_("Size"), 0.25f, 0.0f, 0.0f, 0.0f, 0.0001f, 2.0f, PROP_UNSIGNED},
{SOCK_FLOAT, 1, N_("Turbulence"), 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 200.0f, PROP_UNSIGNED},
{-1, 0, ""}};
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 bNodeSocketTemplate clouds_inputs[] = {
COMMON_INPUTS,
{SOCK_FLOAT, 1, N_("Size"), 0.25f, 0.0f, 0.0f, 0.0f, 0.0001f, 2.0f, PROP_UNSIGNED},
{-1, 0, ""}};
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 bNodeSocketTemplate distnoise_inputs[] = {
COMMON_INPUTS,
{SOCK_FLOAT, 1, N_("Size"), 0.25f, 0.0f, 0.0f, 0.0f, 0.0001f, 2.0f, PROP_UNSIGNED},
{SOCK_FLOAT, 1, N_("Distortion"), 1.00f, 0.0f, 0.0f, 0.0f, 0.0000f, 10.0f, PROP_UNSIGNED},
{-1, 0, ""}};
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 bNodeSocketTemplate wood_inputs[] = {
COMMON_INPUTS,
{SOCK_FLOAT, 1, N_("Size"), 0.25f, 0.0f, 0.0f, 0.0f, 0.0001f, 2.0f, PROP_UNSIGNED},
{SOCK_FLOAT, 1, N_("Turbulence"), 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 200.0f, PROP_UNSIGNED},
{-1, 0, ""}};
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 bNodeSocketTemplate musgrave_inputs[] = {
COMMON_INPUTS,
{SOCK_FLOAT, 1, N_("H"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0001f, 2.0f, PROP_UNSIGNED},
{SOCK_FLOAT, 1, N_("Lacunarity"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 6.0f, PROP_UNSIGNED},
{SOCK_FLOAT, 1, N_("Octaves"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 8.0f, PROP_UNSIGNED},
{SOCK_FLOAT, 1, N_("iScale"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 10.0f, PROP_UNSIGNED},
{SOCK_FLOAT, 1, N_("Size"), 0.25f, 0.0f, 0.0f, 0.0f, 0.0001f, 2.0f, PROP_UNSIGNED},
{-1, 0, ""}};
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 bNodeSocketTemplate noise_inputs[] = {COMMON_INPUTS, {-1, 0, ""}};
ProcNoInputs(noise) ProcDef(noise)
/* --- STUCCI --- */
static bNodeSocketTemplate stucci_inputs[] = {
COMMON_INPUTS,
{SOCK_FLOAT, 1, N_("Size"), 0.25f, 0.0f, 0.0f, 0.0f, 0.0001f, 2.0f, PROP_UNSIGNED},
{SOCK_FLOAT, 1, N_("Turbulence"), 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 200.0f, PROP_UNSIGNED},
{-1, 0, ""}};
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 *UNUSED(ntree), bNode *node)
{
Tex *tex = MEM_callocN(sizeof(Tex), "Tex");
node->storage = tex;
BKE_texture_default(tex);
tex->type = node->type - TEX_NODE_PROC;
if (tex->type == TEX_WOOD) {
tex->stype = TEX_BANDNOISE;
}
}
/* Node type definitions */
#define TexDef(TEXTYPE, outputs, name, Name) \
void register_node_type_tex_proc_##name(void) \
{ \
static bNodeType ntype; \
\
tex_node_type_base(&ntype, TEX_NODE_PROC + TEXTYPE, Name, NODE_CLASS_TEXTURE, NODE_PREVIEW); \
node_type_socket_templates(&ntype, name##_inputs, outputs); \
node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); \
node_type_init(&ntype, init); \
node_type_storage(&ntype, "Tex", node_free_standard_storage, node_copy_standard_storage); \
node_type_exec(&ntype, NULL, NULL, name##_exec); \
\
nodeRegisterType(&ntype); \
}
#define C outputs_color_only
#define CV outputs_both
TexDef(TEX_VORONOI, CV, voronoi, "Voronoi") TexDef(TEX_BLEND, C, blend, "Blend")
TexDef(TEX_MAGIC, C, magic, "Magic") TexDef(TEX_MARBLE, CV, marble, "Marble")
TexDef(TEX_CLOUDS, CV, clouds, "Clouds") TexDef(TEX_WOOD, CV, wood, "Wood")
TexDef(TEX_MUSGRAVE, CV, musgrave, "Musgrave") TexDef(TEX_NOISE, C, noise, "Noise")
TexDef(TEX_STUCCI, CV, stucci, "Stucci")
TexDef(TEX_DISTNOISE, CV, distnoise, "Distorted Noise")