Support Musgrave texture for Cycles GLSL viewport
authorSergey Sharybin <sergey.vfx@gmail.com>
Sun, 22 May 2016 17:09:42 +0000 (19:09 +0200)
committerSergey Sharybin <sergey.vfx@gmail.com>
Sun, 22 May 2016 17:10:15 +0000 (19:10 +0200)
Only for non-OSX viewport!

source/blender/gpu/shaders/gpu_shader_material.glsl
source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c

index e97dddfd00f60de4b21ac34dab1a075a785779f2..dcb888b1a9bbb5de6162789974ae8e15a42f811a 100644 (file)
@@ -2875,12 +2875,6 @@ void node_tex_magic(vec3 co, float scale, float distortion, float depth, out vec
        fac = (color.x + color.y + color.z) / 3.0;
 }
 
-void node_tex_musgrave(vec3 co, float scale, float detail, float dimension, float lacunarity, float offset, float gain, out vec4 color, out float fac)
-{
-       color = vec4(1.0);
-       fac = 1.0;
-}
-
 #ifdef BIT_OPERATIONS
 float noise_fade(float t)
 {
@@ -2934,6 +2928,11 @@ float noise(vec3 p)
        return 0.5 * noise_perlin(p.x, p.y, p.z) + 0.5;
 }
 
+float snoise(vec3 p)
+{
+       return noise_perlin(p.x, p.y, p.z);
+}
+
 float noise_turbulence(vec3 p, float octaves, int hard)
 {
        float fscale = 1.0;
@@ -2993,6 +2992,222 @@ void node_tex_noise(vec3 co, float scale, float detail, float distortion, out ve
 #endif  // BIT_OPERATIONS
 }
 
+
+#ifdef BIT_OPERATIONS
+
+/* Musgrave fBm
+ *
+ * H: fractal increment parameter
+ * lacunarity: gap between successive frequencies
+ * octaves: number of frequencies in the fBm
+ *
+ * from "Texturing and Modelling: A procedural approach"
+ */
+
+float noise_musgrave_fBm(vec3 p, float H, float lacunarity, float octaves)
+{
+       float rmd;
+       float value = 0.0;
+       float pwr = 1.0;
+       float pwHL = pow(lacunarity, -H);
+       int i;
+
+       for(i = 0; i < int(octaves); i++) {
+               value += snoise(p) * pwr;
+               pwr *= pwHL;
+               p *= lacunarity;
+       }
+
+       rmd = octaves - floor(octaves);
+       if(rmd != 0.0)
+               value += rmd * snoise(p) * pwr;
+
+       return value;
+}
+
+/* Musgrave Multifractal
+ *
+ * H: highest fractal dimension
+ * lacunarity: gap between successive frequencies
+ * octaves: number of frequencies in the fBm
+ */
+
+float noise_musgrave_multi_fractal(vec3 p, float H, float lacunarity, float octaves)
+{
+       float rmd;
+       float value = 1.0;
+       float pwr = 1.0;
+       float pwHL = pow(lacunarity, -H);
+       int i;
+
+       for(i = 0; i < int(octaves); i++) {
+               value *= (pwr * snoise(p) + 1.0);
+               pwr *= pwHL;
+               p *= lacunarity;
+       }
+
+       rmd = octaves - floor(octaves);
+       if(rmd != 0.0)
+               value *= (rmd * pwr * snoise(p) + 1.0); /* correct? */
+
+       return value;
+}
+
+/* Musgrave Heterogeneous Terrain
+ *
+ * H: fractal dimension of the roughest area
+ * lacunarity: gap between successive frequencies
+ * octaves: number of frequencies in the fBm
+ * offset: raises the terrain from `sea level'
+ */
+
+float noise_musgrave_hetero_terrain(vec3 p, float H, float lacunarity, float octaves, float offset)
+{
+       float value, increment, rmd;
+       float pwHL = pow(lacunarity, -H);
+       float pwr = pwHL;
+       int i;
+
+       /* first unscaled octave of function; later octaves are scaled */
+       value = offset + snoise(p);
+       p *= lacunarity;
+
+       for(i = 1; i < int(octaves); i++) {
+               increment = (snoise(p) + offset) * pwr * value;
+               value += increment;
+               pwr *= pwHL;
+               p *= lacunarity;
+       }
+
+       rmd = octaves - floor(octaves);
+       if(rmd != 0.0) {
+               increment = (snoise(p) + offset) * pwr * value;
+               value += rmd * increment;
+       }
+
+       return value;
+}
+
+/* Hybrid Additive/Multiplicative Multifractal Terrain
+ *
+ * H: fractal dimension of the roughest area
+ * lacunarity: gap between successive frequencies
+ * octaves: number of frequencies in the fBm
+ * offset: raises the terrain from `sea level'
+ */
+
+float noise_musgrave_hybrid_multi_fractal(vec3 p, float H, float lacunarity, float octaves, float offset, float gain)
+{
+       float result, signal, weight, rmd;
+       float pwHL = pow(lacunarity, -H);
+       float pwr = pwHL;
+       int i;
+
+       result = snoise(p) + offset;
+       weight = gain * result;
+       p *= lacunarity;
+
+       for(i = 1; (weight > 0.001f) && (i < int(octaves)); i++) {
+               if(weight > 1.0)
+                       weight = 1.0;
+
+               signal = (snoise(p) + offset) * pwr;
+               pwr *= pwHL;
+               result += weight * signal;
+               weight *= gain * signal;
+               p *= lacunarity;
+       }
+
+       rmd = octaves - floor(octaves);
+       if(rmd != 0.0)
+               result += rmd * ((snoise(p) + offset) * pwr);
+
+       return result;
+}
+
+/* Ridged Multifractal Terrain
+ *
+ * H: fractal dimension of the roughest area
+ * lacunarity: gap between successive frequencies
+ * octaves: number of frequencies in the fBm
+ * offset: raises the terrain from `sea level'
+ */
+
+float noise_musgrave_ridged_multi_fractal(vec3 p, float H, float lacunarity, float octaves, float offset, float gain)
+{
+       float result, signal, weight;
+       float pwHL = pow(lacunarity, -H);
+       float pwr = pwHL;
+       int i;
+
+       signal = offset - abs(snoise(p));
+       signal *= signal;
+       result = signal;
+       weight = 1.0;
+
+       for(i = 1; i < int(octaves); i++) {
+               p *= lacunarity;
+               weight = clamp(signal * gain, 0.0, 1.0);
+               signal = offset - abs(snoise(p));
+               signal *= signal;
+               signal *= weight;
+               result += signal * pwr;
+               pwr *= pwHL;
+       }
+
+       return result;
+}
+
+float svm_musgrave(int type,
+                   float dimension,
+                   float lacunarity,
+                   float octaves,
+                   float offset,
+                   float intensity,
+                   float gain,
+                   vec3 p)
+{
+       if (type == 0 /*NODE_MUSGRAVE_MULTIFRACTAL*/)
+               return intensity*noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves);
+       else if (type == 1 /*NODE_MUSGRAVE_FBM*/)
+               return intensity*noise_musgrave_fBm(p, dimension, lacunarity, octaves);
+       else if (type == 2 /*NODE_MUSGRAVE_HYBRID_MULTIFRACTAL*/)
+               return intensity*noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
+       else if (type == 3 /*NODE_MUSGRAVE_RIDGED_MULTIFRACTAL*/)
+               return intensity*noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
+       else if (type == 4 /*NODE_MUSGRAVE_HETERO_TERRAIN*/)
+               return intensity*noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, offset);
+       return 0.0;
+}
+#endif  // #ifdef BIT_OPERATIONS
+
+void node_tex_musgrave(vec3 co,
+                       float scale,
+                       float detail,
+                       float dimension,
+                       float lacunarity,
+                       float offset,
+                       float gain,
+                       float type,
+                       out vec4 color,
+                       out float fac)
+{
+#ifdef BIT_OPERATIONS
+       fac = svm_musgrave(int(type),
+                          dimension,
+                          lacunarity,
+                          detail,
+                          offset,
+                          1.0,
+                          gain,
+                          co*scale);
+#else
+       fac = 1.0;
+#endif
+
+       color = vec4(fac, fac, fac, 1.0);
+}
+
 void node_tex_sky(vec3 co, out vec4 color)
 {
        color = vec4(1.0);
index 825ba7eb3c129c6530cc93bf21cca938904c904c..51d6699fadd9754094645cd143059f05fd8738a8 100644 (file)
@@ -58,12 +58,17 @@ static void node_shader_init_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *node)
 
 static int node_shader_gpu_tex_musgrave(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
 {
-       if (!in[0].link)
+       if (!in[0].link) {
                in[0].link = GPU_attribute(CD_ORCO, "");
+               GPU_link(mat, "generated_from_orco", in[0].link, &in[0].link);
+       }
 
        node_shader_gpu_tex_mapping(mat, node, in, out);
 
-       return GPU_stack_link(mat, "node_tex_musgrave", in, out);
+       NodeTexMusgrave *tex = (NodeTexMusgrave *)node->storage;
+       float type = tex->musgrave_type;
+
+       return GPU_stack_link(mat, "node_tex_musgrave", in, out, GPU_uniform(&type));
 }
 
 /* node type definition */