diff options
author | Bartosz Moniewski <monio> | 2020-02-17 14:31:38 +0300 |
---|---|---|
committer | Brecht Van Lommel <brecht@blender.org> | 2020-02-17 15:24:07 +0300 |
commit | 67d12bb5192d04a596e216f63cff2875fdd8cfbf (patch) | |
tree | c4d866f343ec9b87f713ebd004a8f343ab6f5307 /intern/cycles | |
parent | ae9bbb4d0360aea694b46ee698d24dbc1476ebf3 (diff) |
Shading: add direction modes and phase offset to wave texture node
* Direction mode X, Y and Z to align with axes rather than diagonal or
spherical as previously. X is the new default, existing files will
use diagonal or spherical for compatibility.
* Phase offset to offset the wave along its direction, for purposes like
animation and distortion.
https://developer.blender.org/D6382
Diffstat (limited to 'intern/cycles')
-rw-r--r-- | intern/cycles/blender/blender_shader.cpp | 2 | ||||
-rw-r--r-- | intern/cycles/kernel/shaders/node_wave_texture.osl | 67 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm_types.h | 17 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm_wave.h | 91 | ||||
-rw-r--r-- | intern/cycles/render/nodes.cpp | 44 | ||||
-rw-r--r-- | intern/cycles/render/nodes.h | 4 |
6 files changed, 183 insertions, 42 deletions
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 635405e42c7..12009d6160c 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -770,6 +770,8 @@ static ShaderNode *add_node(Scene *scene, BL::ShaderNodeTexWave b_wave_node(b_node); WaveTextureNode *wave = new WaveTextureNode(); wave->type = (NodeWaveType)b_wave_node.wave_type(); + wave->bands_direction = (NodeWaveBandsDirection)b_wave_node.bands_direction(); + wave->rings_direction = (NodeWaveRingsDirection)b_wave_node.rings_direction(); wave->profile = (NodeWaveProfile)b_wave_node.wave_profile(); BL::TexMapping b_texture_mapping(b_wave_node.texture_mapping()); get_tex_mapping(&wave->tex_mapping, b_texture_mapping); diff --git a/intern/cycles/kernel/shaders/node_wave_texture.osl b/intern/cycles/kernel/shaders/node_wave_texture.osl index 5b27c570e42..5f97976e582 100644 --- a/intern/cycles/kernel/shaders/node_wave_texture.osl +++ b/intern/cycles/kernel/shaders/node_wave_texture.osl @@ -19,40 +19,81 @@ /* Wave */ -float wave(point p, string type, string profile, float detail, float distortion, float dscale) +float wave(point p, + string type, + string bands_direction, + string rings_direction, + string profile, + float detail, + float distortion, + float dscale, + float phase) { + /* Prevent precision issues on unit coordinates. */ + p = (p + 0.000001) * 0.999999; + float n = 0.0; if (type == "bands") { - n = (p[0] + p[1] + p[2]) * 10.0; + if (bands_direction == "x") { + n = p[0] * 20.0; + } + else if (bands_direction == "y") { + n = p[1] * 20.0; + } + else if (bands_direction == "z") { + n = p[2] * 20.0; + } + else { /* diagonal */ + n = (p[0] + p[1] + p[2]) * 10.0; + } } else if (type == "rings") { - n = length(p) * 20.0; + point rp = p; + if (rings_direction == "x") { + rp *= point(0.0, 1.0, 1.0); + } + else if (rings_direction == "y") { + rp *= point(1.0, 0.0, 1.0); + } + else if (rings_direction == "z") { + rp *= point(1.0, 1.0, 0.0); + } + /* else: "spherical" */ + + n = length(rp) * 20.0; } + n += phase; + if (distortion != 0.0) { n = n + (distortion * (fractal_noise(p * dscale, detail) * 2.0 - 1.0)); } if (profile == "sine") { - return 0.5 + 0.5 * sin(n); + return 0.5 + 0.5 * sin(n - M_PI_2); + } + else if (profile == "saw") { + n /= M_2PI; + return n - floor(n); } - else { - /* Saw profile */ + else { /* profile tri */ n /= M_2PI; - n -= (int)n; - return (n < 0.0) ? n + 1.0 : n; + return abs(n - floor(n + 0.5)) * 2.0; } } shader node_wave_texture(int use_mapping = 0, matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), string type = "bands", + string bands_direction = "x", + string rings_direction = "x", string profile = "sine", float Scale = 5.0, float Distortion = 0.0, float Detail = 2.0, float DetailScale = 1.0, + float PhaseOffset = 0.0, point Vector = P, output float Fac = 0.0, output color Color = 0.0) @@ -62,6 +103,14 @@ shader node_wave_texture(int use_mapping = 0, if (use_mapping) p = transform(mapping, p); - Fac = wave(p * Scale, type, profile, Detail, Distortion, DetailScale); + Fac = wave(p * Scale, + type, + bands_direction, + rings_direction, + profile, + Detail, + Distortion, + DetailScale, + PhaseOffset); Color = Fac; } diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 828b43eb8e4..45c299e0acb 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -384,9 +384,24 @@ typedef enum NodeMusgraveType { typedef enum NodeWaveType { NODE_WAVE_BANDS, NODE_WAVE_RINGS } NodeWaveType; -typedef enum NodeWaveProfiles { +typedef enum NodeWaveBandsDirection { + NODE_WAVE_BANDS_DIRECTION_X, + NODE_WAVE_BANDS_DIRECTION_Y, + NODE_WAVE_BANDS_DIRECTION_Z, + NODE_WAVE_BANDS_DIRECTION_DIAGONAL +} NodeWaveBandsDirection; + +typedef enum NodeWaveRingsDirection { + NODE_WAVE_RINGS_DIRECTION_X, + NODE_WAVE_RINGS_DIRECTION_Y, + NODE_WAVE_RINGS_DIRECTION_Z, + NODE_WAVE_RINGS_DIRECTION_SPHERICAL +} NodeWaveRingsDirection; + +typedef enum NodeWaveProfile { NODE_WAVE_PROFILE_SIN, NODE_WAVE_PROFILE_SAW, + NODE_WAVE_PROFILE_TRI, } NodeWaveProfile; typedef enum NodeSkyType { NODE_SKY_OLD, NODE_SKY_NEW } NodeSkyType; diff --git a/intern/cycles/kernel/svm/svm_wave.h b/intern/cycles/kernel/svm/svm_wave.h index 50c868c0f82..64102535f7d 100644 --- a/intern/cycles/kernel/svm/svm_wave.h +++ b/intern/cycles/kernel/svm/svm_wave.h @@ -19,52 +19,101 @@ CCL_NAMESPACE_BEGIN /* Wave */ ccl_device_noinline_cpu float svm_wave(NodeWaveType type, + NodeWaveBandsDirection bands_dir, + NodeWaveRingsDirection rings_dir, NodeWaveProfile profile, float3 p, float detail, float distortion, - float dscale) + float dscale, + float phase) { + /* Prevent precision issues on unit coordinates. */ + p = (p + 0.000001f) * 0.999999f; + float n; - if (type == NODE_WAVE_BANDS) - n = (p.x + p.y + p.z) * 10.0f; - else /* NODE_WAVE_RINGS */ - n = len(p) * 20.0f; + if (type == NODE_WAVE_BANDS) { + if (bands_dir == NODE_WAVE_BANDS_DIRECTION_X) { + n = p.x * 20.0f; + } + else if (bands_dir == NODE_WAVE_BANDS_DIRECTION_Y) { + n = p.y * 20.0f; + } + else if (bands_dir == NODE_WAVE_BANDS_DIRECTION_Z) { + n = p.z * 20.0f; + } + else { /* NODE_WAVE_BANDS_DIRECTION_DIAGONAL */ + n = (p.x + p.y + p.z) * 10.0f; + } + } + else { /* NODE_WAVE_RINGS */ + float3 rp = p; + if (rings_dir == NODE_WAVE_RINGS_DIRECTION_X) { + rp *= make_float3(0.0f, 1.0f, 1.0f); + } + else if (rings_dir == NODE_WAVE_RINGS_DIRECTION_Y) { + rp *= make_float3(1.0f, 0.0f, 1.0f); + } + else if (rings_dir == NODE_WAVE_RINGS_DIRECTION_Z) { + rp *= make_float3(1.0f, 1.0f, 0.0f); + } + /* else: NODE_WAVE_RINGS_DIRECTION_SPHERICAL */ + + n = len(rp) * 20.0f; + } + + n += phase; if (distortion != 0.0f) n += distortion * (fractal_noise_3d(p * dscale, detail) * 2.0f - 1.0f); if (profile == NODE_WAVE_PROFILE_SIN) { - return 0.5f + 0.5f * sinf(n); + return 0.5f + 0.5f * sinf(n - M_PI_2_F); + } + else if (profile == NODE_WAVE_PROFILE_SAW) { + n /= M_2PI_F; + return n - floorf(n); } - else { /* NODE_WAVE_PROFILE_SAW */ + else { /* NODE_WAVE_PROFILE_TRI */ n /= M_2PI_F; - n -= (int)n; - return (n < 0.0f) ? n + 1.0f : n; + return fabsf(n - floorf(n + 0.5f)) * 2.0f; } } ccl_device void svm_node_tex_wave( KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset) { - uint4 node2 = read_node(kg, offset); + uint4 defaults1 = read_node(kg, offset); + uint4 defaults2 = read_node(kg, offset); - uint type; - uint co_offset, scale_offset, detail_offset, dscale_offset, distortion_offset, color_offset, - fac_offset; + /* RNA properties */ + uint type_offset, bands_dir_offset, rings_dir_offset, profile_offset; + /* Inputs, Outputs */ + uint co_offset, scale_offset, distortion_offset, detail_offset, dscale_offset, phase_offset; + uint color_offset, fac_offset; - svm_unpack_node_uchar4(node.y, &type, &color_offset, &fac_offset, &dscale_offset); - svm_unpack_node_uchar4(node.z, &co_offset, &scale_offset, &detail_offset, &distortion_offset); + svm_unpack_node_uchar4( + node.y, &type_offset, &bands_dir_offset, &rings_dir_offset, &profile_offset); + svm_unpack_node_uchar4(node.z, &co_offset, &scale_offset, &distortion_offset, &detail_offset); + svm_unpack_node_uchar4(node.w, &dscale_offset, &phase_offset, &color_offset, &fac_offset); float3 co = stack_load_float3(stack, co_offset); - float scale = stack_load_float_default(stack, scale_offset, node2.x); - float detail = stack_load_float_default(stack, detail_offset, node2.y); - float distortion = stack_load_float_default(stack, distortion_offset, node2.z); - float dscale = stack_load_float_default(stack, dscale_offset, node2.w); + float scale = stack_load_float_default(stack, scale_offset, defaults1.x); + float detail = stack_load_float_default(stack, detail_offset, defaults1.y); + float distortion = stack_load_float_default(stack, distortion_offset, defaults1.z); + float dscale = stack_load_float_default(stack, dscale_offset, defaults1.w); + float phase = stack_load_float_default(stack, phase_offset, defaults2.x); - float f = svm_wave( - (NodeWaveType)type, (NodeWaveProfile)node.w, co * scale, detail, distortion, dscale); + float f = svm_wave((NodeWaveType)type_offset, + (NodeWaveBandsDirection)bands_dir_offset, + (NodeWaveRingsDirection)rings_dir_offset, + (NodeWaveProfile)profile_offset, + co * scale, + detail, + distortion, + dscale, + phase); if (stack_valid(fac_offset)) stack_store_float(stack, fac_offset, f); diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 3f5c2aacc98..83b973011a1 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -1422,15 +1422,33 @@ NODE_DEFINE(WaveTextureNode) type_enum.insert("rings", NODE_WAVE_RINGS); SOCKET_ENUM(type, "Type", type_enum, NODE_WAVE_BANDS); + static NodeEnum bands_direction_enum; + bands_direction_enum.insert("x", NODE_WAVE_BANDS_DIRECTION_X); + bands_direction_enum.insert("y", NODE_WAVE_BANDS_DIRECTION_Y); + bands_direction_enum.insert("z", NODE_WAVE_BANDS_DIRECTION_Z); + bands_direction_enum.insert("diagonal", NODE_WAVE_BANDS_DIRECTION_DIAGONAL); + SOCKET_ENUM( + bands_direction, "Bands Direction", bands_direction_enum, NODE_WAVE_BANDS_DIRECTION_X); + + static NodeEnum rings_direction_enum; + rings_direction_enum.insert("x", NODE_WAVE_RINGS_DIRECTION_X); + rings_direction_enum.insert("y", NODE_WAVE_RINGS_DIRECTION_Y); + rings_direction_enum.insert("z", NODE_WAVE_RINGS_DIRECTION_Z); + rings_direction_enum.insert("spherical", NODE_WAVE_RINGS_DIRECTION_SPHERICAL); + SOCKET_ENUM( + rings_direction, "Rings Direction", rings_direction_enum, NODE_WAVE_BANDS_DIRECTION_X); + static NodeEnum profile_enum; profile_enum.insert("sine", NODE_WAVE_PROFILE_SIN); profile_enum.insert("saw", NODE_WAVE_PROFILE_SAW); + profile_enum.insert("tri", NODE_WAVE_PROFILE_TRI); SOCKET_ENUM(profile, "Profile", profile_enum, NODE_WAVE_PROFILE_SIN); SOCKET_IN_FLOAT(scale, "Scale", 1.0f); SOCKET_IN_FLOAT(distortion, "Distortion", 0.0f); SOCKET_IN_FLOAT(detail, "Detail", 2.0f); SOCKET_IN_FLOAT(detail_scale, "Detail Scale", 0.0f); + SOCKET_IN_FLOAT(phase, "Phase Offset", 0.0f); SOCKET_IN_POINT( vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED); @@ -1446,32 +1464,36 @@ WaveTextureNode::WaveTextureNode() : TextureNode(node_type) void WaveTextureNode::compile(SVMCompiler &compiler) { + ShaderInput *vector_in = input("Vector"); ShaderInput *scale_in = input("Scale"); ShaderInput *distortion_in = input("Distortion"); - ShaderInput *dscale_in = input("Detail Scale"); ShaderInput *detail_in = input("Detail"); - ShaderInput *vector_in = input("Vector"); - ShaderOutput *fac_out = output("Fac"); + ShaderInput *dscale_in = input("Detail Scale"); + ShaderInput *phase_in = input("Phase Offset"); ShaderOutput *color_out = output("Color"); + ShaderOutput *fac_out = output("Fac"); int vector_offset = tex_mapping.compile_begin(compiler, vector_in); compiler.add_node(NODE_TEX_WAVE, - compiler.encode_uchar4(type, - compiler.stack_assign_if_linked(color_out), - compiler.stack_assign_if_linked(fac_out), - compiler.stack_assign_if_linked(dscale_in)), + compiler.encode_uchar4(type, bands_direction, rings_direction, profile), compiler.encode_uchar4(vector_offset, compiler.stack_assign_if_linked(scale_in), - compiler.stack_assign_if_linked(detail_in), - compiler.stack_assign_if_linked(distortion_in)), - profile); + compiler.stack_assign_if_linked(distortion_in), + compiler.stack_assign_if_linked(detail_in)), + compiler.encode_uchar4(compiler.stack_assign_if_linked(dscale_in), + compiler.stack_assign_if_linked(phase_in), + compiler.stack_assign_if_linked(color_out), + compiler.stack_assign_if_linked(fac_out))); compiler.add_node(__float_as_int(scale), __float_as_int(detail), __float_as_int(distortion), __float_as_int(detail_scale)); + compiler.add_node( + __float_as_int(phase), SVM_STACK_INVALID, SVM_STACK_INVALID, SVM_STACK_INVALID); + tex_mapping.compile_end(compiler, vector_in, vector_offset); } @@ -1480,6 +1502,8 @@ void WaveTextureNode::compile(OSLCompiler &compiler) tex_mapping.compile(compiler); compiler.parameter(this, "type"); + compiler.parameter(this, "bands_direction"); + compiler.parameter(this, "rings_direction"); compiler.parameter(this, "profile"); compiler.add(this, "node_wave_texture"); diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 56f709c8a79..8346ac77ae6 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -288,9 +288,11 @@ class WaveTextureNode : public TextureNode { } NodeWaveType type; + NodeWaveBandsDirection bands_direction; + NodeWaveRingsDirection rings_direction; NodeWaveProfile profile; - float scale, distortion, detail, detail_scale; + float scale, distortion, detail, detail_scale, phase; float3 vector; }; |