Shading: Add White Noise node.

The White Noise node hashes the input and returns a random number in the
range [0, 1]. The input can be a 1D, 2D, 3D, or a 4D vector.

Reviewers: brecht, JacquesLucke

Differential Revision: https://developer.blender.org/D5550
This commit is contained in:
OmarSquircleArt
2019-08-21 20:04:09 +02:00
parent 7f4a2fc437
commit 133dfdd704
29 changed files with 693 additions and 106 deletions

View File

@@ -978,6 +978,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree,
#define SH_NODE_BSDF_HAIR_PRINCIPLED 701
#define SH_NODE_MAP_RANGE 702
#define SH_NODE_CLAMP 703
#define SH_NODE_TEX_WHITE_NOISE 704
/* custom defines options for Material node */
#define SH_NODE_MAT_DIFF 1

View File

@@ -3933,6 +3933,7 @@ static void registerShaderNodes(void)
register_node_type_sh_tex_brick();
register_node_type_sh_tex_pointdensity();
register_node_type_sh_tex_ies();
register_node_type_sh_tex_white_noise();
}
static void registerTextureNodes(void)

View File

@@ -1186,6 +1186,11 @@ static void node_shader_buts_ambient_occlusion(uiLayout *layout,
uiItemR(layout, ptr, "only_local", 0, NULL, ICON_NONE);
}
static void node_shader_buts_white_noise(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "dimensions", 0, "", ICON_NONE);
}
/* only once called */
static void node_shader_set_butfunc(bNodeType *ntype)
{
@@ -1330,6 +1335,9 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_AMBIENT_OCCLUSION:
ntype->draw_buttons = node_shader_buts_ambient_occlusion;
break;
case SH_NODE_TEX_WHITE_NOISE:
ntype->draw_buttons = node_shader_buts_white_noise;
break;
}
}

View File

@@ -1166,9 +1166,34 @@ float integer_noise(int n)
return 0.5 * (float(nn) / 1073741824.0);
}
uint hash(uint kx, uint ky, uint kz)
{
/* ***** Jenkins Lookup3 Hash Functions ***** */
/* Source: http://burtleburtle.net/bob/c/lookup3.c */
#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
#define mix(a, b, c) \
{ \
a -= c; \
a ^= rot(c, 4); \
c += b; \
b -= a; \
b ^= rot(a, 6); \
a += c; \
c -= b; \
c ^= rot(b, 8); \
b += a; \
a -= c; \
a ^= rot(c, 16); \
c += b; \
b -= a; \
b ^= rot(a, 19); \
a += c; \
c -= b; \
c ^= rot(b, 4); \
b += a; \
}
#define final(a, b, c) \
{ \
c ^= b; \
@@ -1186,9 +1211,34 @@ uint hash(uint kx, uint ky, uint kz)
c ^= b; \
c -= rot(b, 24); \
}
// now hash the data!
uint a, b, c, len = 3u;
a = b = c = 0xdeadbeefu + (len << 2u) + 13u;
uint hash_uint(uint kx)
{
uint a, b, c;
a = b = c = 0xdeadbeefu + (1u << 2u) + 13u;
a += kx;
final(a, b, c);
return c;
}
uint hash_uint2(uint kx, uint ky)
{
uint a, b, c;
a = b = c = 0xdeadbeefu + (2u << 2u) + 13u;
b += ky;
a += kx;
final(a, b, c);
return c;
}
uint hash_uint3(uint kx, uint ky, uint kz)
{
uint a, b, c;
a = b = c = 0xdeadbeefu + (3u << 2u) + 13u;
c += kz;
b += ky;
@@ -1196,15 +1246,157 @@ uint hash(uint kx, uint ky, uint kz)
final(a, b, c);
return c;
#undef rot
#undef final
}
uint hash(int kx, int ky, int kz)
uint hash_uint4(uint kx, uint ky, uint kz, uint kw)
{
return hash(uint(kx), uint(ky), uint(kz));
uint a, b, c;
a = b = c = 0xdeadbeefu + (4u << 2u) + 13u;
a += kx;
b += ky;
c += kz;
mix(a, b, c);
a += kw;
final(a, b, c);
return c;
}
#undef rot
#undef final
#undef mix
uint hash_int(int kx)
{
return hash_uint(uint(kx));
}
uint hash_int2(int kx, int ky)
{
return hash_uint2(uint(kx), uint(ky));
}
uint hash_int3(int kx, int ky, int kz)
{
return hash_uint3(uint(kx), uint(ky), uint(kz));
}
uint hash_int4(int kx, int ky, int kz, int kw)
{
return hash_uint4(uint(kx), uint(ky), uint(kz), uint(kw));
}
/* Hashing uint or uint[234] into a float in the range [0, 1]. */
float hash_uint_to_float(uint kx)
{
return float(hash_uint(kx)) / float(0xFFFFFFFFu);
}
float hash_uint2_to_float(uint kx, uint ky)
{
return float(hash_uint2(kx, ky)) / float(0xFFFFFFFFu);
}
float hash_uint3_to_float(uint kx, uint ky, uint kz)
{
return float(hash_uint3(kx, ky, kz)) / float(0xFFFFFFFFu);
}
float hash_uint4_to_float(uint kx, uint ky, uint kz, uint kw)
{
return float(hash_uint4(kx, ky, kz, kw)) / float(0xFFFFFFFFu);
}
/* Hashing float or vec[234] into a float in the range [0, 1]. */
float hash_float_to_float(float k)
{
return hash_uint_to_float(floatBitsToUint(k));
}
float hash_vec2_to_float(vec2 k)
{
return hash_uint2_to_float(floatBitsToUint(k.x), floatBitsToUint(k.y));
}
float hash_vec3_to_float(vec3 k)
{
return hash_uint3_to_float(floatBitsToUint(k.x), floatBitsToUint(k.y), floatBitsToUint(k.z));
}
float hash_vec4_to_float(vec4 k)
{
return hash_uint4_to_float(
floatBitsToUint(k.x), floatBitsToUint(k.y), floatBitsToUint(k.z), floatBitsToUint(k.w));
}
/* Hashing vec[234] into vec[234] of components in the range [0, 1]. */
vec2 hash_vec2_to_vec2(vec2 k)
{
return vec2(hash_vec2_to_float(k), hash_vec3_to_float(vec3(k, 1.0)));
}
vec3 hash_vec3_to_vec3(vec3 k)
{
return vec3(
hash_vec3_to_float(k), hash_vec4_to_float(vec4(k, 1.0)), hash_vec4_to_float(vec4(k, 2.0)));
}
vec4 hash_vec4_to_vec4(vec4 k)
{
return vec4(hash_vec4_to_float(k.xyzw),
hash_vec4_to_float(k.wxyz),
hash_vec4_to_float(k.zwxy),
hash_vec4_to_float(k.yzwx));
}
/* Hashing float or vec[234] into vec3 of components in range [0, 1]. */
vec3 hash_float_to_vec3(float k)
{
return vec3(
hash_float_to_float(k), hash_vec2_to_float(vec2(k, 1.0)), hash_vec2_to_float(vec2(k, 2.0)));
}
vec3 hash_vec2_to_vec3(vec2 k)
{
return vec3(
hash_vec2_to_float(k), hash_vec3_to_float(vec3(k, 1.0)), hash_vec3_to_float(vec3(k, 2.0)));
}
vec3 hash_vec4_to_vec3(vec4 k)
{
return vec3(hash_vec4_to_float(k.xyzw), hash_vec4_to_float(k.zxwy), hash_vec4_to_float(k.wzyx));
}
/* White Noise */
void node_white_noise_1d(vec3 vector, float w, out float value)
{
value = hash_float_to_float(w);
}
void node_white_noise_2d(vec3 vector, float w, out float value)
{
value = hash_vec2_to_float(vector.xy);
}
void node_white_noise_3d(vec3 vector, float w, out float value)
{
value = hash_vec3_to_float(vector);
}
void node_white_noise_4d(vec3 vector, float w, out float value)
{
value = hash_vec4_to_float(vec4(vector, w));
}
/* Cell Noise */
float bits_to_01(uint bits)
{
return (float(bits) / 4294967295.0);
@@ -1216,7 +1408,7 @@ float cellnoise(vec3 p)
int iy = quick_floor(p.y);
int iz = quick_floor(p.z);
return bits_to_01(hash(uint(ix), uint(iy), uint(iz)));
return hash_uint3_to_float(uint(ix), uint(iy), uint(iz));
}
vec3 cellnoise_color(vec3 p)
@@ -2901,22 +3093,24 @@ float noise_perlin(float x, float y, float z)
float noise_u[2], noise_v[2];
noise_u[0] = noise_nerp(
u, noise_grad(hash(X, Y, Z), fx, fy, fz), noise_grad(hash(X + 1, Y, Z), fx - 1.0, fy, fz));
noise_u[0] = noise_nerp(u,
noise_grad(hash_int3(X, Y, Z), fx, fy, fz),
noise_grad(hash_int3(X + 1, Y, Z), fx - 1.0, fy, fz));
noise_u[1] = noise_nerp(u,
noise_grad(hash(X, Y + 1, Z), fx, fy - 1.0, fz),
noise_grad(hash(X + 1, Y + 1, Z), fx - 1.0, fy - 1.0, fz));
noise_grad(hash_int3(X, Y + 1, Z), fx, fy - 1.0, fz),
noise_grad(hash_int3(X + 1, Y + 1, Z), fx - 1.0, fy - 1.0, fz));
noise_v[0] = noise_nerp(v, noise_u[0], noise_u[1]);
noise_u[0] = noise_nerp(u,
noise_grad(hash(X, Y, Z + 1), fx, fy, fz - 1.0),
noise_grad(hash(X + 1, Y, Z + 1), fx - 1.0, fy, fz - 1.0));
noise_grad(hash_int3(X, Y, Z + 1), fx, fy, fz - 1.0),
noise_grad(hash_int3(X + 1, Y, Z + 1), fx - 1.0, fy, fz - 1.0));
noise_u[1] = noise_nerp(u,
noise_grad(hash(X, Y + 1, Z + 1), fx, fy - 1.0, fz - 1.0),
noise_grad(hash(X + 1, Y + 1, Z + 1), fx - 1.0, fy - 1.0, fz - 1.0));
noise_u[1] = noise_nerp(
u,
noise_grad(hash_int3(X, Y + 1, Z + 1), fx, fy - 1.0, fz - 1.0),
noise_grad(hash_int3(X + 1, Y + 1, Z + 1), fx - 1.0, fy - 1.0, fz - 1.0));
noise_v[1] = noise_nerp(v, noise_u[0], noise_u[1]);

View File

@@ -170,6 +170,14 @@ const EnumPropertyItem rna_enum_node_vec_math_items[] = {
{0, NULL, 0, NULL, NULL},
};
const EnumPropertyItem rna_enum_node_tex_dimensions_items[] = {
{1, "1D", 0, "1D", "Use the scalar value W as input"},
{2, "2D", 0, "2D", "Use the 2D vector (x, y) as input. The z component is ignored"},
{3, "3D", 0, "3D", "Use the 3D vector Vector as input"},
{4, "4D", 0, "4D", "Use the 4D vector (x, y, z, w) as input"},
{0, NULL, 0, NULL, NULL},
};
const EnumPropertyItem rna_enum_node_filter_items[] = {
{0, "SOFTEN", 0, "Soften", ""},
{1, "SHARPEN", 0, "Sharpen", ""},
@@ -4497,6 +4505,18 @@ static void def_sh_tex_wave(StructRNA *srna)
RNA_def_property_update(prop, 0, "rna_Node_update");
}
static void def_sh_tex_white_noise(StructRNA *srna)
{
PropertyRNA *prop;
prop = RNA_def_property(srna, "dimensions", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "custom1");
RNA_def_property_enum_items(prop, rna_enum_node_tex_dimensions_items);
RNA_def_property_ui_text(
prop, "Dimensions", "The number of dimensions to evaluate the noise in");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update");
}
static void def_sh_tex_coord(StructRNA *srna)
{
PropertyRNA *prop;

View File

@@ -200,6 +200,7 @@ set(SRC
shader/nodes/node_shader_tex_sky.c
shader/nodes/node_shader_tex_voronoi.c
shader/nodes/node_shader_tex_wave.c
shader/nodes/node_shader_tex_white_noise.c
shader/nodes/node_shader_uvAlongStroke.c
shader/nodes/node_shader_uvmap.c
shader/nodes/node_shader_valToRgb.c

View File

@@ -131,6 +131,7 @@ void register_node_type_sh_tex_noise(void);
void register_node_type_sh_tex_checker(void);
void register_node_type_sh_bump(void);
void register_node_type_sh_tex_ies(void);
void register_node_type_sh_tex_white_noise(void);
void register_node_type_sh_custom_group(bNodeType *ntype);

View File

@@ -127,6 +127,7 @@ DefNode(ShaderNode, SH_NODE_BEVEL, def_sh_bevel, "BEV
DefNode(ShaderNode, SH_NODE_DISPLACEMENT, def_sh_displacement, "DISPLACEMENT", Displacement, "Displacement", "" )
DefNode(ShaderNode, SH_NODE_VECTOR_DISPLACEMENT,def_sh_vector_displacement,"VECTOR_DISPLACEMENT",VectorDisplacement,"Vector Displacement","" )
DefNode(ShaderNode, SH_NODE_TEX_IES, def_sh_tex_ies, "TEX_IES", TexIES, "IES Texture", "" )
DefNode(ShaderNode, SH_NODE_TEX_WHITE_NOISE, def_sh_tex_white_noise, "TEX_WHITE_NOISE", TexWhiteNoise, "White Noise", "" )
DefNode(CompositorNode, CMP_NODE_VIEWER, def_cmp_viewer, "VIEWER", Viewer, "Viewer", "" )
DefNode(CompositorNode, CMP_NODE_RGB, 0, "RGB", RGB, "RGB", "" )

View File

@@ -0,0 +1,76 @@
/*
* 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.
*/
#include "../node_shader_util.h"
/* **************** WHITE NOISE **************** */
static bNodeSocketTemplate sh_node_tex_white_noise_in[] = {
{SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f, PROP_NONE},
{SOCK_FLOAT, 1, N_("W"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f, PROP_NONE},
{-1, 0, ""}};
static bNodeSocketTemplate sh_node_tex_white_noise_out[] = {
{SOCK_FLOAT, 0, N_("Value")},
{-1, 0, ""},
};
static void node_shader_init_tex_white_noise(bNodeTree *UNUSED(ntree), bNode *node)
{
node->custom1 = 3;
}
static int gpu_shader_tex_white_noise(GPUMaterial *mat,
bNode *node,
bNodeExecData *UNUSED(execdata),
GPUNodeStack *in,
GPUNodeStack *out)
{
static const char *names[] = {
"",
"node_white_noise_1d",
"node_white_noise_2d",
"node_white_noise_3d",
"node_white_noise_4d",
};
return GPU_stack_link(mat, node, names[node->custom1], in, out);
}
static void node_shader_update_tex_white_noise(bNodeTree *UNUSED(ntree), bNode *node)
{
bNodeSocket *sockVector = nodeFindSocket(node, SOCK_IN, "Vector");
bNodeSocket *sockW = nodeFindSocket(node, SOCK_IN, "W");
nodeSetSocketAvailability(sockVector, node->custom1 != 1);
nodeSetSocketAvailability(sockW, node->custom1 == 1 || node->custom1 == 4);
}
void register_node_type_sh_tex_white_noise(void)
{
static bNodeType ntype;
sh_node_type_base(&ntype, SH_NODE_TEX_WHITE_NOISE, "White Noise Texture", NODE_CLASS_TEXTURE, 0);
node_type_socket_templates(&ntype, sh_node_tex_white_noise_in, sh_node_tex_white_noise_out);
node_type_init(&ntype, node_shader_init_tex_white_noise);
node_type_gpu(&ntype, gpu_shader_tex_white_noise);
node_type_update(&ntype, node_shader_update_tex_white_noise);
nodeRegisterType(&ntype);
}