Cycles: Add Saw option to the wave texture
authorLukas Stockner <lukas.stockner@freenet.de>
Tue, 29 Dec 2015 13:42:49 +0000 (14:42 +0100)
committerLukas Stockner <lukas.stockner@freenet.de>
Fri, 1 Jan 2016 22:25:37 +0000 (23:25 +0100)
This commit adds "Bands Saw" and "Rings Saw" to the options for the Wave texture node in Cycles, behaving similar to the Saw option in BI textures.
Requested by @cekuhnen on BA.

Reviewers: dingto, sergey

Subscribers: cekuhnen

Differential Revision: https://developer.blender.org/D1699

intern/cycles/blender/blender_shader.cpp
intern/cycles/kernel/shaders/node_wave_texture.osl
intern/cycles/kernel/svm/svm_types.h
intern/cycles/kernel/svm/svm_wave.h
intern/cycles/render/nodes.cpp
intern/cycles/render/nodes.h
source/blender/editors/space_node/drawnode.c
source/blender/makesdna/DNA_node_types.h
source/blender/makesrna/intern/rna_nodetree.c

index 2b4d0e4af9cede43acbd11e148e445ad2e8e106f..abf1fc25f7b6969480383bc345827fd38306be8e 100644 (file)
@@ -718,6 +718,7 @@ static ShaderNode *add_node(Scene *scene,
                BL::ShaderNodeTexWave b_wave_node(b_node);
                WaveTextureNode *wave = new WaveTextureNode();
                wave->type = WaveTextureNode::type_enum[(int)b_wave_node.wave_type()];
+               wave->profile = WaveTextureNode::profile_enum[(int)b_wave_node.wave_profile()];
                get_tex_mapping(&wave->tex_mapping, b_wave_node.texture_mapping());
                node = wave;
        }
index 569f284cbacf40c1810fd1a876f0542b86952760..beb2a9de1125950926349ab8a7a918e72479c188 100644 (file)
@@ -19,7 +19,7 @@
 
 /* Wave */
 
-float wave(point p, string type, float detail, float distortion, float dscale)
+float wave(point p, string type, string profile, float detail, float distortion, float dscale)
 {
        float n = 0.0;
 
@@ -33,13 +33,23 @@ float wave(point p, string type, float detail, float distortion, float dscale)
        if (distortion != 0.0) {
                n = n + (distortion * noise_turbulence(p * dscale, detail, 0));
        }
-       return 0.5 + 0.5 * sin(n);
+
+       if (profile == "Sine") {
+               return 0.5 + 0.5 * sin(n);
+       }
+       else {
+               /* Saw profile */
+               n /= M_2PI;
+               n -= (int) n;
+               return (n < 0.0)? n + 1.0: n;
+       }
 }
 
 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 Profile = "Sine",
        float Scale = 5.0,
        float Distortion = 0.0,
        float Detail = 2.0,
@@ -53,7 +63,7 @@ shader node_wave_texture(
        if (use_mapping)
                p = transform(mapping, p);
 
-       Fac = wave(p * Scale, Type, Detail, Distortion, DetailScale);
+       Fac = wave(p * Scale, Type, Profile, Detail, Distortion, DetailScale);
        Color = Fac;
 }
 
index bf7e067616f018bf50b2a6b5b1df2c57446da812..7df139103b76e87479209650aeb1fa8281bf290b 100644 (file)
@@ -293,6 +293,11 @@ typedef enum NodeWaveType {
        NODE_WAVE_RINGS
 } NodeWaveType;
 
+typedef enum NodeWaveProfiles {
+       NODE_WAVE_PROFILE_SIN,
+       NODE_WAVE_PROFILE_SAW,
+} NodeWaveProfile;
+
 typedef enum NodeSkyType {
        NODE_SKY_OLD,
        NODE_SKY_NEW
index 6eaddaf301ce48a738da84660ff5c699ee6950ae..6ce69458a034d6f7b0e71c5fc2336b8565ced131 100644 (file)
@@ -18,7 +18,7 @@ CCL_NAMESPACE_BEGIN
 
 /* Wave */
 
-ccl_device_noinline float svm_wave(NodeWaveType type, float3 p, float detail, float distortion, float dscale)
+ccl_device_noinline float svm_wave(NodeWaveType type, NodeWaveProfile profile, float3 p, float detail, float distortion, float dscale)
 {
        float n;
 
@@ -26,11 +26,18 @@ ccl_device_noinline float svm_wave(NodeWaveType type, float3 p, float detail, fl
                n = (p.x + p.y + p.z) * 10.0f;
        else /* NODE_WAVE_RINGS */
                n = len(p) * 20.0f;
-       
+
        if(distortion != 0.0f)
                n += distortion * noise_turbulence(p*dscale, detail, 0);
 
-       return 0.5f + 0.5f * sinf(n);
+       if(profile == NODE_WAVE_PROFILE_SIN) {
+               return 0.5f + 0.5f * sinf(n);
+       }
+       else { /* NODE_WAVE_PROFILE_SAW */
+               n /= M_2PI_F;
+               n -= (int) n;
+               return (n < 0.0f)? n + 1.0f: n;
+       }
 }
 
 ccl_device void svm_node_tex_wave(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
@@ -49,7 +56,7 @@ ccl_device void svm_node_tex_wave(KernelGlobals *kg, ShaderData *sd, float *stac
        float distortion = stack_load_float_default(stack, distortion_offset, node2.z);
        float dscale = stack_load_float_default(stack, dscale_offset, node2.w);
 
-       float f = svm_wave((NodeWaveType)type, co*scale, detail, distortion, dscale);
+       float f = svm_wave((NodeWaveType)type, (NodeWaveProfile)node.w, co*scale, detail, distortion, dscale);
 
        if(stack_valid(fac_offset)) stack_store_float(stack, fac_offset, f);
        if(stack_valid(color_offset)) stack_store_float3(stack, color_offset, make_float3(f, f, f));
index 92ade79781a2a7024df28f7088b7fe6b256e07ce..e35c4a9dd4628072cb9d46d8772a3cbc81cf50b7 100644 (file)
@@ -1073,12 +1073,24 @@ static ShaderEnum wave_type_init()
        return enm;
 }
 
+static ShaderEnum wave_profile_init()
+{
+       ShaderEnum enm;
+
+       enm.insert("Sine", NODE_WAVE_PROFILE_SIN);
+       enm.insert("Saw", NODE_WAVE_PROFILE_SAW);
+
+       return enm;
+}
+
 ShaderEnum WaveTextureNode::type_enum = wave_type_init();
+ShaderEnum WaveTextureNode::profile_enum = wave_profile_init();
 
 WaveTextureNode::WaveTextureNode()
 : TextureNode("wave_texture")
 {
        type = ustring("Bands");
+       profile = ustring("Sine");
 
        add_input("Scale", SHADER_SOCKET_FLOAT, 1.0f);
        add_input("Distortion", SHADER_SOCKET_FLOAT, 0.0f);
@@ -1120,7 +1132,8 @@ void WaveTextureNode::compile(SVMCompiler& compiler)
 
        compiler.add_node(NODE_TEX_WAVE,
                compiler.encode_uchar4(type_enum[type], color_out->stack_offset, fac_out->stack_offset, dscale_in->stack_offset),
-               compiler.encode_uchar4(vector_offset, scale_in->stack_offset, detail_in->stack_offset, distortion_in->stack_offset));
+               compiler.encode_uchar4(vector_offset, scale_in->stack_offset, detail_in->stack_offset, distortion_in->stack_offset),
+               profile_enum[profile]);
 
        compiler.add_node(
                __float_as_int(scale_in->value.x),
@@ -1137,6 +1150,7 @@ void WaveTextureNode::compile(OSLCompiler& compiler)
        tex_mapping.compile(compiler);
 
        compiler.parameter("Type", type);
+       compiler.parameter("Profile", profile);
 
        compiler.add(this, "node_wave_texture");
 }
index 67943775b9226c4279ed7143f54bc7b811d1f56a..cede4205a6aefe6cf64238e81ab6e666ac971e30 100644 (file)
@@ -267,12 +267,15 @@ public:
        virtual int get_group() { return NODE_GROUP_LEVEL_2; }
 
        ustring type;
+       ustring profile;
        static ShaderEnum type_enum;
+       static ShaderEnum profile_enum;
 
        virtual bool equals(const ShaderNode *other) {
                const WaveTextureNode *wave_node = (const WaveTextureNode*)other;
                return TextureNode::equals(other) &&
-                      type == wave_node->type;
+                      type == wave_node->type &&
+                      profile == wave_node->profile;
        }
 };
 
index 603db9564cfe1b6ded66f39d9febac96dfffc73b..50e31ffca64e6f83731819a7974c079a26330127 100644 (file)
@@ -939,6 +939,7 @@ static void node_shader_buts_tex_brick(uiLayout *layout, bContext *UNUSED(C), Po
 static void node_shader_buts_tex_wave(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
 {
        uiItemR(layout, ptr, "wave_type", 0, "", ICON_NONE);
+       uiItemR(layout, ptr, "wave_profile", 0, "", ICON_NONE);
 }
 
 static void node_shader_buts_tex_musgrave(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
index 86713d7dcc870e7ec700b72f8eb42a7687f92217..7aec437b62b720ed92c91fda99b4d40b0935a9b4 100644 (file)
@@ -778,7 +778,7 @@ typedef struct NodeTexMusgrave {
 typedef struct NodeTexWave {
        NodeTexBase base;
        int wave_type;
-       int pad;
+       int wave_profile;
 } NodeTexWave;
 
 typedef struct NodeTexMagic {
@@ -972,6 +972,9 @@ typedef struct NodeSunBeams {
 #define SHD_WAVE_BANDS         0
 #define SHD_WAVE_RINGS         1
 
+#define SHD_WAVE_PROFILE_SIN   0
+#define SHD_WAVE_PROFILE_SAW   1
+
 /* sky texture */
 #define SHD_SKY_OLD            0
 #define SHD_SKY_NEW            1
index c10fe52bb29617941b77d1cbb8903ba42a5ea873..984ecbe96ac06ee16bdc36e3d734dd6791bd7389 100644 (file)
@@ -3858,6 +3858,12 @@ static void def_sh_tex_wave(StructRNA *srna)
                {0, NULL, 0, NULL, NULL}
        };
 
+       static EnumPropertyItem prop_wave_profile_items[] = {
+               {SHD_WAVE_PROFILE_SIN, "SIN", 0, "Sine", "Use a standard sine profile"},
+               {SHD_WAVE_PROFILE_SAW, "SAW", 0, "Saw", "Use a sawtooth profile"},
+               {0, NULL, 0, NULL, NULL}
+       };
+
        PropertyRNA *prop;
        
        RNA_def_struct_sdna_from(srna, "NodeTexWave", "storage");
@@ -3868,6 +3874,12 @@ static void def_sh_tex_wave(StructRNA *srna)
        RNA_def_property_enum_items(prop, prop_wave_type_items);
        RNA_def_property_ui_text(prop, "Wave Type", "");
        RNA_def_property_update(prop, 0, "rna_Node_update");
+
+       prop = RNA_def_property(srna, "wave_profile", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "wave_profile");
+       RNA_def_property_enum_items(prop, prop_wave_profile_items);
+       RNA_def_property_ui_text(prop, "Wave Profile", "");
+       RNA_def_property_update(prop, 0, "rna_Node_update");
 }
 
 static void def_sh_tex_coord(StructRNA *srna)