Shading: Extend Musgrave node to other dimensions.
authorOmarSquircleArt <omar.squircleart@gmail.com>
Mon, 9 Sep 2019 19:06:55 +0000 (21:06 +0200)
committerOmarSquircleArt <omar.squircleart@gmail.com>
Mon, 9 Sep 2019 19:06:55 +0000 (21:06 +0200)
This patch extends Musgrave noise to operate in 1D, 2D, 3D, and 4D
space. The Color output was also removed because it was identical
to the Fac output.

Reviewed By: brecht

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

13 files changed:
intern/cycles/blender/blender_shader.cpp
intern/cycles/kernel/shaders/node_musgrave_texture.osl
intern/cycles/kernel/svm/svm.h
intern/cycles/kernel/svm/svm_musgrave.h
intern/cycles/render/nodes.cpp
intern/cycles/render/nodes.h
source/blender/blenkernel/BKE_blender_version.h
source/blender/blenloader/intern/versioning_cycles.c
source/blender/editors/space_node/drawnode.c
source/blender/gpu/shaders/material/gpu_shader_material_tex_musgrave.glsl
source/blender/makesdna/DNA_node_types.h
source/blender/makesrna/intern/rna_nodetree.c
source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c

index 4d7d091076502e2ffd73d93a28ab00a33a098759..7e784527a217fe5b4adb3039c560d2aa9f54eeba 100644 (file)
@@ -785,11 +785,12 @@ static ShaderNode *add_node(Scene *scene,
   }
   else if (b_node.is_a(&RNA_ShaderNodeTexMusgrave)) {
     BL::ShaderNodeTexMusgrave b_musgrave_node(b_node);
-    MusgraveTextureNode *musgrave = new MusgraveTextureNode();
-    musgrave->type = (NodeMusgraveType)b_musgrave_node.musgrave_type();
+    MusgraveTextureNode *musgrave_node = new MusgraveTextureNode();
+    musgrave_node->type = (NodeMusgraveType)b_musgrave_node.musgrave_type();
+    musgrave_node->dimensions = b_musgrave_node.musgrave_dimensions();
     BL::TexMapping b_texture_mapping(b_musgrave_node.texture_mapping());
-    get_tex_mapping(&musgrave->tex_mapping, b_texture_mapping);
-    node = musgrave;
+    get_tex_mapping(&musgrave_node->tex_mapping, b_texture_mapping);
+    node = musgrave_node;
   }
   else if (b_node.is_a(&RNA_ShaderNodeTexCoord)) {
     BL::ShaderNodeTexCoord b_tex_coord_node(b_node);
index 0bf462e21036da364aac35636d3b8de8746314a2..8861f9a671a1bd124ef73274a2d24bb256c0196a 100644 (file)
 
 #include "stdosl.h"
 #include "node_noise.h"
+#include "vector2.h"
+#include "vector4.h"
 
-/* Musgrave fBm
+#define vector3 point
+
+/* 1D 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_1d(float co, float H, float lacunarity, float octaves)
+{
+  float p = co;
+  float value = 0.0;
+  float pwr = 1.0;
+  float pwHL = pow(lacunarity, -H);
+
+  for (int i = 0; i < (int)octaves; i++) {
+    value += safe_snoise(p) * pwr;
+    pwr *= pwHL;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floor(octaves);
+  if (rmd != 0.0) {
+    value += rmd * safe_snoise(p) * pwr;
+  }
+
+  return value;
+}
+
+/* 1D Musgrave Multifractal
+ *
+ * H: highest fractal dimension
+ * lacunarity: gap between successive frequencies
+ * octaves: number of frequencies in the fBm
+ */
+
+float noise_musgrave_multi_fractal_1d(float co, float H, float lacunarity, float octaves)
+{
+  float p = co;
+  float value = 1.0;
+  float pwr = 1.0;
+  float pwHL = pow(lacunarity, -H);
+
+  for (int i = 0; i < (int)octaves; i++) {
+    value *= (pwr * safe_snoise(p) + 1.0);
+    pwr *= pwHL;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floor(octaves);
+  if (rmd != 0.0) {
+    value *= (rmd * pwr * safe_snoise(p) + 1.0); /* correct? */
+  }
+
+  return value;
+}
+
+/* 1D 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_1d(
+    float co, float H, float lacunarity, float octaves, float offset)
+{
+  float p = co;
+  float pwHL = pow(lacunarity, -H);
+  float pwr = pwHL;
+
+  /* first unscaled octave of function; later octaves are scaled */
+  float value = offset + safe_snoise(p);
+  p *= lacunarity;
+
+  for (int i = 1; i < (int)octaves; i++) {
+    float increment = (safe_snoise(p) + offset) * pwr * value;
+    value += increment;
+    pwr *= pwHL;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floor(octaves);
+  if (rmd != 0.0) {
+    float increment = (safe_snoise(p) + offset) * pwr * value;
+    value += rmd * increment;
+  }
+
+  return value;
+}
+
+/* 1D 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_1d(
+    float co, float H, float lacunarity, float octaves, float offset, float gain)
+{
+  float p = co;
+  float pwHL = pow(lacunarity, -H);
+  float pwr = pwHL;
+
+  float value = safe_snoise(p) + offset;
+  float weight = gain * value;
+  p *= lacunarity;
+
+  for (int i = 1; (weight > 0.001) && (i < (int)octaves); i++) {
+    if (weight > 1.0) {
+      weight = 1.0;
+    }
+
+    float signal = (safe_snoise(p) + offset) * pwr;
+    pwr *= pwHL;
+    value += weight * signal;
+    weight *= gain * signal;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floor(octaves);
+  if (rmd != 0.0) {
+    value += rmd * ((safe_snoise(p) + offset) * pwr);
+  }
+
+  return value;
+}
+
+/* 1D 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_1d(
+    float co, float H, float lacunarity, float octaves, float offset, float gain)
+{
+  float p = co;
+  float pwHL = pow(lacunarity, -H);
+  float pwr = pwHL;
+
+  float signal = offset - fabs(safe_snoise(p));
+  signal *= signal;
+  float value = signal;
+  float weight = 1.0;
+
+  for (int i = 1; i < (int)octaves; i++) {
+    p *= lacunarity;
+    weight = clamp(signal * gain, 0.0, 1.0);
+    signal = offset - fabs(safe_snoise(p));
+    signal *= signal;
+    signal *= weight;
+    value += signal * pwr;
+    pwr *= pwHL;
+  }
+
+  return value;
+}
+
+/* 2D 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_2d(vector2 co, float H, float lacunarity, float octaves)
+{
+  vector2 p = co;
+  float value = 0.0;
+  float pwr = 1.0;
+  float pwHL = pow(lacunarity, -H);
+
+  for (int i = 0; i < (int)octaves; i++) {
+    value += safe_snoise(p) * pwr;
+    pwr *= pwHL;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floor(octaves);
+  if (rmd != 0.0) {
+    value += rmd * safe_snoise(p) * pwr;
+  }
+
+  return value;
+}
+
+/* 2D Musgrave Multifractal
+ *
+ * H: highest fractal dimension
+ * lacunarity: gap between successive frequencies
+ * octaves: number of frequencies in the fBm
+ */
+
+float noise_musgrave_multi_fractal_2d(vector2 co, float H, float lacunarity, float octaves)
+{
+  vector2 p = co;
+  float value = 1.0;
+  float pwr = 1.0;
+  float pwHL = pow(lacunarity, -H);
+
+  for (int i = 0; i < (int)octaves; i++) {
+    value *= (pwr * safe_snoise(p) + 1.0);
+    pwr *= pwHL;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floor(octaves);
+  if (rmd != 0.0) {
+    value *= (rmd * pwr * safe_snoise(p) + 1.0); /* correct? */
+  }
+
+  return value;
+}
+
+/* 2D 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_2d(
+    vector2 co, float H, float lacunarity, float octaves, float offset)
+{
+  vector2 p = co;
+  float pwHL = pow(lacunarity, -H);
+  float pwr = pwHL;
+
+  /* first unscaled octave of function; later octaves are scaled */
+  float value = offset + safe_snoise(p);
+  p *= lacunarity;
+
+  for (int i = 1; i < (int)octaves; i++) {
+    float increment = (safe_snoise(p) + offset) * pwr * value;
+    value += increment;
+    pwr *= pwHL;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floor(octaves);
+  if (rmd != 0.0) {
+    float increment = (safe_snoise(p) + offset) * pwr * value;
+    value += rmd * increment;
+  }
+
+  return value;
+}
+
+/* 2D 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_2d(
+    vector2 co, float H, float lacunarity, float octaves, float offset, float gain)
+{
+  vector2 p = co;
+  float pwHL = pow(lacunarity, -H);
+  float pwr = pwHL;
+
+  float value = safe_snoise(p) + offset;
+  float weight = gain * value;
+  p *= lacunarity;
+
+  for (int i = 1; (weight > 0.001) && (i < (int)octaves); i++) {
+    if (weight > 1.0) {
+      weight = 1.0;
+    }
+
+    float signal = (safe_snoise(p) + offset) * pwr;
+    pwr *= pwHL;
+    value += weight * signal;
+    weight *= gain * signal;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floor(octaves);
+  if (rmd != 0.0) {
+    value += rmd * ((safe_snoise(p) + offset) * pwr);
+  }
+
+  return value;
+}
+
+/* 2D 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_2d(
+    vector2 co, float H, float lacunarity, float octaves, float offset, float gain)
+{
+  vector2 p = co;
+  float pwHL = pow(lacunarity, -H);
+  float pwr = pwHL;
+
+  float signal = offset - fabs(safe_snoise(p));
+  signal *= signal;
+  float value = signal;
+  float weight = 1.0;
+
+  for (int i = 1; i < (int)octaves; i++) {
+    p *= lacunarity;
+    weight = clamp(signal * gain, 0.0, 1.0);
+    signal = offset - fabs(safe_snoise(p));
+    signal *= signal;
+    signal *= weight;
+    value += signal * pwr;
+    pwr *= pwHL;
+  }
+
+  return value;
+}
+
+/* 3D Musgrave fBm
  *
  * H: fractal increment parameter
  * lacunarity: gap between successive frequencies
  * from "Texturing and Modelling: A procedural approach"
  */
 
-float noise_musgrave_fBm(point ip, float H, float lacunarity, float octaves)
+float noise_musgrave_fBm_3d(vector3 co, float H, float lacunarity, float octaves)
 {
-  float rmd;
+  vector3 p = co;
   float value = 0.0;
   float pwr = 1.0;
   float pwHL = pow(lacunarity, -H);
-  int i;
-  point p = ip;
 
-  for (i = 0; i < (int)octaves; i++) {
-    value += safe_noise(p) * pwr;
+  for (int i = 0; i < (int)octaves; i++) {
+    value += safe_snoise(p) * pwr;
     pwr *= pwHL;
     p *= lacunarity;
   }
 
-  rmd = octaves - floor(octaves);
-  if (rmd != 0.0)
-    value += rmd * safe_noise(p) * pwr;
+  float rmd = octaves - floor(octaves);
+  if (rmd != 0.0) {
+    value += rmd * safe_snoise(p) * pwr;
+  }
 
   return value;
 }
 
-/* Musgrave Multifractal
+/* 3D Musgrave Multifractal
  *
  * H: highest fractal dimension
  * lacunarity: gap between successive frequencies
  * octaves: number of frequencies in the fBm
  */
 
-float noise_musgrave_multi_fractal(point ip, float H, float lacunarity, float octaves)
+float noise_musgrave_multi_fractal_3d(vector3 co, float H, float lacunarity, float octaves)
 {
-  float rmd;
+  vector3 p = co;
   float value = 1.0;
   float pwr = 1.0;
   float pwHL = pow(lacunarity, -H);
-  int i;
-  point p = ip;
 
-  for (i = 0; i < (int)octaves; i++) {
-    value *= (pwr * safe_noise(p) + 1.0);
+  for (int i = 0; i < (int)octaves; i++) {
+    value *= (pwr * safe_snoise(p) + 1.0);
     pwr *= pwHL;
     p *= lacunarity;
   }
 
-  rmd = octaves - floor(octaves);
-  if (rmd != 0.0)
-    value *= (rmd * pwr * safe_noise(p) + 1.0); /* correct? */
+  float rmd = octaves - floor(octaves);
+  if (rmd != 0.0) {
+    value *= (rmd * pwr * safe_snoise(p) + 1.0); /* correct? */
+  }
 
   return value;
 }
 
-/* Musgrave Heterogeneous Terrain
+/* 3D Musgrave Heterogeneous Terrain
  *
  * H: fractal dimension of the roughest area
  * lacunarity: gap between successive frequencies
@@ -85,36 +417,34 @@ float noise_musgrave_multi_fractal(point ip, float H, float lacunarity, float oc
  * offset: raises the terrain from `sea level'
  */
 
-float noise_musgrave_hetero_terrain(
-    point ip, float H, float lacunarity, float octaves, float offset)
+float noise_musgrave_hetero_terrain_3d(
+    vector3 co, float H, float lacunarity, float octaves, float offset)
 {
-  float value, increment, rmd;
+  vector3 p = co;
   float pwHL = pow(lacunarity, -H);
   float pwr = pwHL;
-  int i;
-  point p = ip;
 
   /* first unscaled octave of function; later octaves are scaled */
-  value = offset + safe_noise(p);
+  float value = offset + safe_snoise(p);
   p *= lacunarity;
 
-  for (i = 1; i < (int)octaves; i++) {
-    increment = (safe_noise(p) + offset) * pwr * value;
+  for (int i = 1; i < (int)octaves; i++) {
+    float increment = (safe_snoise(p) + offset) * pwr * value;
     value += increment;
     pwr *= pwHL;
     p *= lacunarity;
   }
 
-  rmd = octaves - floor(octaves);
+  float rmd = octaves - floor(octaves);
   if (rmd != 0.0) {
-    increment = (safe_noise(p) + offset) * pwr * value;
+    float increment = (safe_snoise(p) + offset) * pwr * value;
     value += rmd * increment;
   }
 
   return value;
 }
 
-/* Hybrid Additive/Multiplicative Multifractal Terrain
+/* 3D Hybrid Additive/Multiplicative Multifractal Terrain
  *
  * H: fractal dimension of the roughest area
  * lacunarity: gap between successive frequencies
@@ -122,38 +452,38 @@ float noise_musgrave_hetero_terrain(
  * offset: raises the terrain from `sea level'
  */
 
-float noise_musgrave_hybrid_multi_fractal(
-    point ip, float H, float lacunarity, float octaves, float offset, float gain)
+float noise_musgrave_hybrid_multi_fractal_3d(
+    vector3 co, float H, float lacunarity, float octaves, float offset, float gain)
 {
-  float result, signal, weight, rmd;
+  vector3 p = co;
   float pwHL = pow(lacunarity, -H);
   float pwr = pwHL;
-  int i;
-  point p = ip;
 
-  result = safe_noise(p) + offset;
-  weight = gain * result;
+  float value = safe_snoise(p) + offset;
+  float weight = gain * value;
   p *= lacunarity;
 
-  for (i = 1; (weight > 0.001) && (i < (int)octaves); i++) {
-    if (weight > 1.0)
+  for (int i = 1; (weight > 0.001) && (i < (int)octaves); i++) {
+    if (weight > 1.0) {
       weight = 1.0;
+    }
 
-    signal = (safe_noise(p) + offset) * pwr;
+    float signal = (safe_snoise(p) + offset) * pwr;
     pwr *= pwHL;
-    result += weight * signal;
+    value += weight * signal;
     weight *= gain * signal;
     p *= lacunarity;
   }
 
-  rmd = octaves - floor(octaves);
-  if (rmd != 0.0)
-    result += rmd * ((safe_noise(p) + offset) * pwr);
+  float rmd = octaves - floor(octaves);
+  if (rmd != 0.0) {
+    value += rmd * ((safe_snoise(p) + offset) * pwr);
+  }
 
-  return result;
+  return value;
 }
 
-/* Ridged Multifractal Terrain
+/* 3D Ridged Multifractal Terrain
  *
  * H: fractal dimension of the roughest area
  * lacunarity: gap between successive frequencies
@@ -161,73 +491,313 @@ float noise_musgrave_hybrid_multi_fractal(
  * offset: raises the terrain from `sea level'
  */
 
-float noise_musgrave_ridged_multi_fractal(
-    point ip, float H, float lacunarity, float octaves, float offset, float gain)
+float noise_musgrave_ridged_multi_fractal_3d(
+    vector3 co, float H, float lacunarity, float octaves, float offset, float gain)
 {
-  float result, signal, weight;
+  vector3 p = co;
   float pwHL = pow(lacunarity, -H);
   float pwr = pwHL;
-  int i;
-  point p = ip;
 
-  signal = offset - fabs(safe_noise(p));
+  float signal = offset - fabs(safe_snoise(p));
   signal *= signal;
-  result = signal;
-  weight = 1.0;
+  float value = signal;
+  float weight = 1.0;
 
-  for (i = 1; i < (int)octaves; i++) {
+  for (int i = 1; i < (int)octaves; i++) {
     p *= lacunarity;
     weight = clamp(signal * gain, 0.0, 1.0);
-    signal = offset - fabs(safe_noise(p));
+    signal = offset - fabs(safe_snoise(p));
     signal *= signal;
     signal *= weight;
-    result += signal * pwr;
+    value += signal * pwr;
+    pwr *= pwHL;
+  }
+
+  return value;
+}
+
+/* 4D 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_4d(vector4 co, float H, float lacunarity, float octaves)
+{
+  vector4 p = co;
+  float value = 0.0;
+  float pwr = 1.0;
+  float pwHL = pow(lacunarity, -H);
+
+  for (int i = 0; i < (int)octaves; i++) {
+    value += safe_snoise(p) * pwr;
+    pwr *= pwHL;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floor(octaves);
+  if (rmd != 0.0) {
+    value += rmd * safe_snoise(p) * pwr;
+  }
+
+  return value;
+}
+
+/* 4D Musgrave Multifractal
+ *
+ * H: highest fractal dimension
+ * lacunarity: gap between successive frequencies
+ * octaves: number of frequencies in the fBm
+ */
+
+float noise_musgrave_multi_fractal_4d(vector4 co, float H, float lacunarity, float octaves)
+{
+  vector4 p = co;
+  float value = 1.0;
+  float pwr = 1.0;
+  float pwHL = pow(lacunarity, -H);
+
+  for (int i = 0; i < (int)octaves; i++) {
+    value *= (pwr * safe_snoise(p) + 1.0);
+    pwr *= pwHL;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floor(octaves);
+  if (rmd != 0.0) {
+    value *= (rmd * pwr * safe_snoise(p) + 1.0); /* correct? */
+  }
+
+  return value;
+}
+
+/* 4D 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_4d(
+    vector4 co, float H, float lacunarity, float octaves, float offset)
+{
+  vector4 p = co;
+  float pwHL = pow(lacunarity, -H);
+  float pwr = pwHL;
+
+  /* first unscaled octave of function; later octaves are scaled */
+  float value = offset + safe_snoise(p);
+  p *= lacunarity;
+
+  for (int i = 1; i < (int)octaves; i++) {
+    float increment = (safe_snoise(p) + offset) * pwr * value;
+    value += increment;
+    pwr *= pwHL;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floor(octaves);
+  if (rmd != 0.0) {
+    float increment = (safe_snoise(p) + offset) * pwr * value;
+    value += rmd * increment;
+  }
+
+  return value;
+}
+
+/* 4D 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_4d(
+    vector4 co, float H, float lacunarity, float octaves, float offset, float gain)
+{
+  vector4 p = co;
+  float pwHL = pow(lacunarity, -H);
+  float pwr = pwHL;
+
+  float value = safe_snoise(p) + offset;
+  float weight = gain * value;
+  p *= lacunarity;
+
+  for (int i = 1; (weight > 0.001) && (i < (int)octaves); i++) {
+    if (weight > 1.0) {
+      weight = 1.0;
+    }
+
+    float signal = (safe_snoise(p) + offset) * pwr;
     pwr *= pwHL;
+    value += weight * signal;
+    weight *= gain * signal;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floor(octaves);
+  if (rmd != 0.0) {
+    value += rmd * ((safe_snoise(p) + offset) * pwr);
   }
 
-  return result;
+  return value;
 }
 
-/* Shader */
+/* 4D 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_4d(
+    vector4 co, float H, float lacunarity, float octaves, float offset, float gain)
+{
+  vector4 p = co;
+  float pwHL = pow(lacunarity, -H);
+  float pwr = pwHL;
+
+  float signal = offset - fabs(safe_snoise(p));
+  signal *= signal;
+  float value = signal;
+  float weight = 1.0;
+
+  for (int i = 1; i < (int)octaves; i++) {
+    p *= lacunarity;
+    weight = clamp(signal * gain, 0.0, 1.0);
+    signal = offset - fabs(safe_snoise(p));
+    signal *= signal;
+    signal *= weight;
+    value += signal * pwr;
+    pwr *= pwHL;
+  }
+
+  return value;
+}
 
 shader node_musgrave_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 = "fBM",
+    string dimensions = "3D",
+    point Vector = P,
+    float W = 0.0,
     float Dimension = 2.0,
-    float Lacunarity = 1.0,
+    float Scale = 5.0,
     float Detail = 2.0,
+    float Lacunarity = 1.0,
     float Offset = 0.0,
     float Gain = 1.0,
-    float Scale = 5.0,
-    point Vector = P,
-    output float Fac = 0.0,
-    output color Color = 0.0)
+    output float Fac = 0.0)
 {
   float dimension = max(Dimension, 1e-5);
   float octaves = clamp(Detail, 0.0, 16.0);
   float lacunarity = max(Lacunarity, 1e-5);
-  float intensity = 1.0;
 
-  point p = Vector;
+  vector3 s = Vector;
 
   if (use_mapping)
-    p = transform(mapping, p);
-
-  p = p * Scale;
-
-  if (type == "multifractal")
-    Fac = intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves);
-  else if (type == "fBM")
-    Fac = intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves);
-  else if (type == "hybrid_multifractal")
-    Fac = intensity *
-          noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, Offset, Gain);
-  else if (type == "ridged_multifractal")
-    Fac = intensity *
-          noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, Offset, Gain);
-  else if (type == "hetero_terrain")
-    Fac = intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, Offset);
-
-  Color = color(Fac, Fac, Fac);
+    s = transform(mapping, s);
+
+  if (dimensions == "1D") {
+    float p = W * Scale;
+    if (type == "multifractal") {
+      Fac = noise_musgrave_multi_fractal_1d(p, dimension, lacunarity, octaves);
+    }
+    else if (type == "fBM") {
+      Fac = noise_musgrave_fBm_1d(p, dimension, lacunarity, octaves);
+    }
+    else if (type == "hybrid_multifractal") {
+      Fac = noise_musgrave_hybrid_multi_fractal_1d(
+          p, dimension, lacunarity, octaves, Offset, Gain);
+    }
+    else if (type == "ridged_multifractal") {
+      Fac = noise_musgrave_ridged_multi_fractal_1d(
+          p, dimension, lacunarity, octaves, Offset, Gain);
+    }
+    else if (type == "hetero_terrain") {
+      Fac = noise_musgrave_hetero_terrain_1d(p, dimension, lacunarity, octaves, Offset);
+    }
+    else {
+      Fac = 0.0;
+    }
+  }
+  else if (dimensions == "2D") {
+    vector2 p = vector2(s[0], s[1]) * Scale;
+    if (type == "multifractal") {
+      Fac = noise_musgrave_multi_fractal_2d(p, dimension, lacunarity, octaves);
+    }
+    else if (type == "fBM") {
+      Fac = noise_musgrave_fBm_2d(p, dimension, lacunarity, octaves);
+    }
+    else if (type == "hybrid_multifractal") {
+      Fac = noise_musgrave_hybrid_multi_fractal_2d(
+          p, dimension, lacunarity, octaves, Offset, Gain);
+    }
+    else if (type == "ridged_multifractal") {
+      Fac = noise_musgrave_ridged_multi_fractal_2d(
+          p, dimension, lacunarity, octaves, Offset, Gain);
+    }
+    else if (type == "hetero_terrain") {
+      Fac = noise_musgrave_hetero_terrain_2d(p, dimension, lacunarity, octaves, Offset);
+    }
+    else {
+      Fac = 0.0;
+    }
+  }
+  else if (dimensions == "3D") {
+    vector3 p = s * Scale;
+    if (type == "multifractal") {
+      Fac = noise_musgrave_multi_fractal_3d(p, dimension, lacunarity, octaves);
+    }
+    else if (type == "fBM") {
+      Fac = noise_musgrave_fBm_3d(p, dimension, lacunarity, octaves);
+    }
+    else if (type == "hybrid_multifractal") {
+      Fac = noise_musgrave_hybrid_multi_fractal_3d(
+          p, dimension, lacunarity, octaves, Offset, Gain);
+    }
+    else if (type == "ridged_multifractal") {
+      Fac = noise_musgrave_ridged_multi_fractal_3d(
+          p, dimension, lacunarity, octaves, Offset, Gain);
+    }
+    else if (type == "hetero_terrain") {
+      Fac = noise_musgrave_hetero_terrain_3d(p, dimension, lacunarity, octaves, Offset);
+    }
+    else {
+      Fac = 0.0;
+    }
+  }
+  else if (dimensions == "4D") {
+    vector4 p = vector4(s[0], s[1], s[2], W) * Scale;
+    if (type == "multifractal") {
+      Fac = noise_musgrave_multi_fractal_4d(p, dimension, lacunarity, octaves);
+    }
+    else if (type == "fBM") {
+      Fac = noise_musgrave_fBm_4d(p, dimension, lacunarity, octaves);
+    }
+    else if (type == "hybrid_multifractal") {
+      Fac = noise_musgrave_hybrid_multi_fractal_4d(
+          p, dimension, lacunarity, octaves, Offset, Gain);
+    }
+    else if (type == "ridged_multifractal") {
+      Fac = noise_musgrave_ridged_multi_fractal_4d(
+          p, dimension, lacunarity, octaves, Offset, Gain);
+    }
+    else if (type == "hetero_terrain") {
+      Fac = noise_musgrave_hetero_terrain_4d(p, dimension, lacunarity, octaves, Offset);
+    }
+    else {
+      Fac = 0.0;
+    }
+  }
+  else {
+    Fac = 0.0;
+  }
 }
index ce651a1b5ff7f742ce728ebcd11003eec21635d5..a192930937fc4c6c0331fc241c64949804d5951e 100644 (file)
@@ -432,7 +432,7 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg,
         svm_node_tex_voronoi(kg, sd, stack, node, &offset);
         break;
       case NODE_TEX_MUSGRAVE:
-        svm_node_tex_musgrave(kg, sd, stack, node, &offset);
+        svm_node_tex_musgrave(kg, sd, stack, node.y, node.z, node.w, &offset);
         break;
       case NODE_TEX_WAVE:
         svm_node_tex_wave(kg, sd, stack, node, &offset);
index db87f04581f0c897f23989722d99ff90090055c2..571f62fe27ffe8e60f16266bef3135362f18a7fc 100644 (file)
@@ -16,7 +16,7 @@
 
 CCL_NAMESPACE_BEGIN
 
-/* Musgrave fBm
+/* 1D Musgrave fBm
  *
  * H: fractal increment parameter
  * lacunarity: gap between successive frequencies
@@ -25,62 +25,404 @@ CCL_NAMESPACE_BEGIN
  * from "Texturing and Modelling: A procedural approach"
  */
 
-ccl_device_noinline_cpu float noise_musgrave_fBm(float3 p,
-                                                 float H,
-                                                 float lacunarity,
-                                                 float octaves)
+ccl_device_noinline_cpu float noise_musgrave_fBm_1d(float co,
+                                                    float H,
+                                                    float lacunarity,
+                                                    float octaves)
 {
-  float rmd;
+  float p = co;
   float value = 0.0f;
   float pwr = 1.0f;
   float pwHL = powf(lacunarity, -H);
-  int i;
 
-  for (i = 0; i < float_to_int(octaves); i++) {
+  for (int i = 0; i < float_to_int(octaves); i++) {
+    value += snoise_1d(p) * pwr;
+    pwr *= pwHL;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floorf(octaves);
+  if (rmd != 0.0f) {
+    value += rmd * snoise_1d(p) * pwr;
+  }
+
+  return value;
+}
+
+/* 1D Musgrave Multifractal
+ *
+ * H: highest fractal dimension
+ * lacunarity: gap between successive frequencies
+ * octaves: number of frequencies in the fBm
+ */
+
+ccl_device_noinline_cpu float noise_musgrave_multi_fractal_1d(float co,
+                                                              float H,
+                                                              float lacunarity,
+                                                              float octaves)
+{
+  float p = co;
+  float value = 1.0f;
+  float pwr = 1.0f;
+  float pwHL = powf(lacunarity, -H);
+
+  for (int i = 0; i < float_to_int(octaves); i++) {
+    value *= (pwr * snoise_1d(p) + 1.0f);
+    pwr *= pwHL;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floorf(octaves);
+  if (rmd != 0.0f) {
+    value *= (rmd * pwr * snoise_1d(p) + 1.0f); /* correct? */
+  }
+
+  return value;
+}
+
+/* 1D 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'
+ */
+
+ccl_device_noinline_cpu float noise_musgrave_hetero_terrain_1d(
+    float co, float H, float lacunarity, float octaves, float offset)
+{
+  float p = co;
+  float pwHL = powf(lacunarity, -H);
+  float pwr = pwHL;
+
+  /* first unscaled octave of function; later octaves are scaled */
+  float value = offset + snoise_1d(p);
+  p *= lacunarity;
+
+  for (int i = 1; i < float_to_int(octaves); i++) {
+    float increment = (snoise_1d(p) + offset) * pwr * value;
+    value += increment;
+    pwr *= pwHL;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floorf(octaves);
+  if (rmd != 0.0f) {
+    float increment = (snoise_1d(p) + offset) * pwr * value;
+    value += rmd * increment;
+  }
+
+  return value;
+}
+
+/* 1D 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'
+ */
+
+ccl_device_noinline_cpu float noise_musgrave_hybrid_multi_fractal_1d(
+    float co, float H, float lacunarity, float octaves, float offset, float gain)
+{
+  float p = co;
+  float pwHL = powf(lacunarity, -H);
+  float pwr = pwHL;
+
+  float value = snoise_1d(p) + offset;
+  float weight = gain * value;
+  p *= lacunarity;
+
+  for (int i = 1; (weight > 0.001f) && (i < float_to_int(octaves)); i++) {
+    if (weight > 1.0f) {
+      weight = 1.0f;
+    }
+
+    float signal = (snoise_1d(p) + offset) * pwr;
+    pwr *= pwHL;
+    value += weight * signal;
+    weight *= gain * signal;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floorf(octaves);
+  if (rmd != 0.0f) {
+    value += rmd * ((snoise_1d(p) + offset) * pwr);
+  }
+
+  return value;
+}
+
+/* 1D 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'
+ */
+
+ccl_device_noinline_cpu float noise_musgrave_ridged_multi_fractal_1d(
+    float co, float H, float lacunarity, float octaves, float offset, float gain)
+{
+  float p = co;
+  float pwHL = powf(lacunarity, -H);
+  float pwr = pwHL;
+
+  float signal = offset - fabsf(snoise_1d(p));
+  signal *= signal;
+  float value = signal;
+  float weight = 1.0f;
+
+  for (int i = 1; i < float_to_int(octaves); i++) {
+    p *= lacunarity;
+    weight = saturate(signal * gain);
+    signal = offset - fabsf(snoise_1d(p));
+    signal *= signal;
+    signal *= weight;
+    value += signal * pwr;
+    pwr *= pwHL;
+  }
+
+  return value;
+}
+
+/* 2D 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"
+ */
+
+ccl_device_noinline_cpu float noise_musgrave_fBm_2d(float2 co,
+                                                    float H,
+                                                    float lacunarity,
+                                                    float octaves)
+{
+  float2 p = co;
+  float value = 0.0f;
+  float pwr = 1.0f;
+  float pwHL = powf(lacunarity, -H);
+
+  for (int i = 0; i < float_to_int(octaves); i++) {
+    value += snoise_2d(p) * pwr;
+    pwr *= pwHL;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floorf(octaves);
+  if (rmd != 0.0f) {
+    value += rmd * snoise_2d(p) * pwr;
+  }
+
+  return value;
+}
+
+/* 2D Musgrave Multifractal
+ *
+ * H: highest fractal dimension
+ * lacunarity: gap between successive frequencies
+ * octaves: number of frequencies in the fBm
+ */
+
+ccl_device_noinline_cpu float noise_musgrave_multi_fractal_2d(float2 co,
+                                                              float H,
+                                                              float lacunarity,
+                                                              float octaves)
+{
+  float2 p = co;
+  float value = 1.0f;
+  float pwr = 1.0f;
+  float pwHL = powf(lacunarity, -H);
+
+  for (int i = 0; i < float_to_int(octaves); i++) {
+    value *= (pwr * snoise_2d(p) + 1.0f);
+    pwr *= pwHL;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floorf(octaves);
+  if (rmd != 0.0f) {
+    value *= (rmd * pwr * snoise_2d(p) + 1.0f); /* correct? */
+  }
+
+  return value;
+}
+
+/* 2D 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'
+ */
+
+ccl_device_noinline_cpu float noise_musgrave_hetero_terrain_2d(
+    float2 co, float H, float lacunarity, float octaves, float offset)
+{
+  float2 p = co;
+  float pwHL = powf(lacunarity, -H);
+  float pwr = pwHL;
+
+  /* first unscaled octave of function; later octaves are scaled */
+  float value = offset + snoise_2d(p);
+  p *= lacunarity;
+
+  for (int i = 1; i < float_to_int(octaves); i++) {
+    float increment = (snoise_2d(p) + offset) * pwr * value;
+    value += increment;
+    pwr *= pwHL;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floorf(octaves);
+  if (rmd != 0.0f) {
+    float increment = (snoise_2d(p) + offset) * pwr * value;
+    value += rmd * increment;
+  }
+
+  return value;
+}
+
+/* 2D 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'
+ */
+
+ccl_device_noinline_cpu float noise_musgrave_hybrid_multi_fractal_2d(
+    float2 co, float H, float lacunarity, float octaves, float offset, float gain)
+{
+  float2 p = co;
+  float pwHL = powf(lacunarity, -H);
+  float pwr = pwHL;
+
+  float value = snoise_2d(p) + offset;
+  float weight = gain * value;
+  p *= lacunarity;
+
+  for (int i = 1; (weight > 0.001f) && (i < float_to_int(octaves)); i++) {
+    if (weight > 1.0f) {
+      weight = 1.0f;
+    }
+
+    float signal = (snoise_2d(p) + offset) * pwr;
+    pwr *= pwHL;
+    value += weight * signal;
+    weight *= gain * signal;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floorf(octaves);
+  if (rmd != 0.0f) {
+    value += rmd * ((snoise_2d(p) + offset) * pwr);
+  }
+
+  return value;
+}
+
+/* 2D 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'
+ */
+
+ccl_device_noinline_cpu float noise_musgrave_ridged_multi_fractal_2d(
+    float2 co, float H, float lacunarity, float octaves, float offset, float gain)
+{
+  float2 p = co;
+  float pwHL = powf(lacunarity, -H);
+  float pwr = pwHL;
+
+  float signal = offset - fabsf(snoise_2d(p));
+  signal *= signal;
+  float value = signal;
+  float weight = 1.0f;
+
+  for (int i = 1; i < float_to_int(octaves); i++) {
+    p *= lacunarity;
+    weight = saturate(signal * gain);
+    signal = offset - fabsf(snoise_2d(p));
+    signal *= signal;
+    signal *= weight;
+    value += signal * pwr;
+    pwr *= pwHL;
+  }
+
+  return value;
+}
+
+/* 3D 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"
+ */
+
+ccl_device_noinline_cpu float noise_musgrave_fBm_3d(float3 co,
+                                                    float H,
+                                                    float lacunarity,
+                                                    float octaves)
+{
+  float3 p = co;
+  float value = 0.0f;
+  float pwr = 1.0f;
+  float pwHL = powf(lacunarity, -H);
+
+  for (int i = 0; i < float_to_int(octaves); i++) {
     value += snoise_3d(p) * pwr;
     pwr *= pwHL;
     p *= lacunarity;
   }
 
-  rmd = octaves - floorf(octaves);
-  if (rmd != 0.0f)
+  float rmd = octaves - floorf(octaves);
+  if (rmd != 0.0f) {
     value += rmd * snoise_3d(p) * pwr;
+  }
 
   return value;
 }
 
-/* Musgrave Multifractal
+/* 3D Musgrave Multifractal
  *
  * H: highest fractal dimension
  * lacunarity: gap between successive frequencies
  * octaves: number of frequencies in the fBm
  */
 
-ccl_device_noinline_cpu float noise_musgrave_multi_fractal(float3 p,
-                                                           float H,
-                                                           float lacunarity,
-                                                           float octaves)
+ccl_device_noinline_cpu float noise_musgrave_multi_fractal_3d(float3 co,
+                                                              float H,
+                                                              float lacunarity,
+                                                              float octaves)
 {
-  float rmd;
+  float3 p = co;
   float value = 1.0f;
   float pwr = 1.0f;
   float pwHL = powf(lacunarity, -H);
-  int i;
 
-  for (i = 0; i < float_to_int(octaves); i++) {
+  for (int i = 0; i < float_to_int(octaves); i++) {
     value *= (pwr * snoise_3d(p) + 1.0f);
     pwr *= pwHL;
     p *= lacunarity;
   }
 
-  rmd = octaves - floorf(octaves);
-  if (rmd != 0.0f)
+  float rmd = octaves - floorf(octaves);
+  if (rmd != 0.0f) {
     value *= (rmd * pwr * snoise_3d(p) + 1.0f); /* correct? */
+  }
 
   return value;
 }
 
-/* Musgrave Heterogeneous Terrain
+/* 3D Musgrave Heterogeneous Terrain
  *
  * H: fractal dimension of the roughest area
  * lacunarity: gap between successive frequencies
@@ -88,35 +430,34 @@ ccl_device_noinline_cpu float noise_musgrave_multi_fractal(float3 p,
  * offset: raises the terrain from `sea level'
  */
 
-ccl_device_noinline_cpu float noise_musgrave_hetero_terrain(
-    float3 p, float H, float lacunarity, float octaves, float offset)
+ccl_device_noinline_cpu float noise_musgrave_hetero_terrain_3d(
+    float3 co, float H, float lacunarity, float octaves, float offset)
 {
-  float value, increment, rmd;
+  float3 p = co;
   float pwHL = powf(lacunarity, -H);
   float pwr = pwHL;
-  int i;
 
   /* first unscaled octave of function; later octaves are scaled */
-  value = offset + snoise_3d(p);
+  float value = offset + snoise_3d(p);
   p *= lacunarity;
 
-  for (i = 1; i < float_to_int(octaves); i++) {
-    increment = (snoise_3d(p) + offset) * pwr * value;
+  for (int i = 1; i < float_to_int(octaves); i++) {
+    float increment = (snoise_3d(p) + offset) * pwr * value;
     value += increment;
     pwr *= pwHL;
     p *= lacunarity;
   }
 
-  rmd = octaves - floorf(octaves);
+  float rmd = octaves - floorf(octaves);
   if (rmd != 0.0f) {
-    increment = (snoise_3d(p) + offset) * pwr * value;
+    float increment = (snoise_3d(p) + offset) * pwr * value;
     value += rmd * increment;
   }
 
   return value;
 }
 
-/* Hybrid Additive/Multiplicative Multifractal Terrain
+/* 3D Hybrid Additive/Multiplicative Multifractal Terrain
  *
  * H: fractal dimension of the roughest area
  * lacunarity: gap between successive frequencies
@@ -124,37 +465,38 @@ ccl_device_noinline_cpu float noise_musgrave_hetero_terrain(
  * offset: raises the terrain from `sea level'
  */
 
-ccl_device_noinline_cpu float noise_musgrave_hybrid_multi_fractal(
-    float3 p, float H, float lacunarity, float octaves, float offset, float gain)
+ccl_device_noinline_cpu float noise_musgrave_hybrid_multi_fractal_3d(
+    float3 co, float H, float lacunarity, float octaves, float offset, float gain)
 {
-  float result, signal, weight, rmd;
+  float3 p = co;
   float pwHL = powf(lacunarity, -H);
   float pwr = pwHL;
-  int i;
 
-  result = snoise_3d(p) + offset;
-  weight = gain * result;
+  float value = snoise_3d(p) + offset;
+  float weight = gain * value;
   p *= lacunarity;
 
-  for (i = 1; (weight > 0.001f) && (i < float_to_int(octaves)); i++) {
-    if (weight > 1.0f)
+  for (int i = 1; (weight > 0.001f) && (i < float_to_int(octaves)); i++) {
+    if (weight > 1.0f) {
       weight = 1.0f;
+    }
 
-    signal = (snoise_3d(p) + offset) * pwr;
+    float signal = (snoise_3d(p) + offset) * pwr;
     pwr *= pwHL;
-    result += weight * signal;
+    value += weight * signal;
     weight *= gain * signal;
     p *= lacunarity;
   }
 
-  rmd = octaves - floorf(octaves);
-  if (rmd != 0.0f)
-    result += rmd * ((snoise_3d(p) + offset) * pwr);
+  float rmd = octaves - floorf(octaves);
+  if (rmd != 0.0f) {
+    value += rmd * ((snoise_3d(p) + offset) * pwr);
+  }
 
-  return result;
+  return value;
 }
 
-/* Ridged Multifractal Terrain
+/* 3D Ridged Multifractal Terrain
  *
  * H: fractal dimension of the roughest area
  * lacunarity: gap between successive frequencies
@@ -162,93 +504,346 @@ ccl_device_noinline_cpu float noise_musgrave_hybrid_multi_fractal(
  * offset: raises the terrain from `sea level'
  */
 
-ccl_device_noinline_cpu float noise_musgrave_ridged_multi_fractal(
-    float3 p, float H, float lacunarity, float octaves, float offset, float gain)
+ccl_device_noinline_cpu float noise_musgrave_ridged_multi_fractal_3d(
+    float3 co, float H, float lacunarity, float octaves, float offset, float gain)
 {
-  float result, signal, weight;
+  float3 p = co;
   float pwHL = powf(lacunarity, -H);
   float pwr = pwHL;
-  int i;
 
-  signal = offset - fabsf(snoise_3d(p));
+  float signal = offset - fabsf(snoise_3d(p));
   signal *= signal;
-  result = signal;
-  weight = 1.0f;
+  float value = signal;
+  float weight = 1.0f;
 
-  for (i = 1; i < float_to_int(octaves); i++) {
+  for (int i = 1; i < float_to_int(octaves); i++) {
     p *= lacunarity;
     weight = saturate(signal * gain);
     signal = offset - fabsf(snoise_3d(p));
     signal *= signal;
     signal *= weight;
-    result += signal * pwr;
+    value += signal * pwr;
     pwr *= pwHL;
   }
 
-  return result;
+  return value;
 }
 
-/* Shader */
+/* 4D 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"
+ */
 
-ccl_device float svm_musgrave(NodeMusgraveType type,
-                              float dimension,
-                              float lacunarity,
-                              float octaves,
-                              float offset,
-                              float intensity,
-                              float gain,
-                              float3 p)
+ccl_device_noinline_cpu float noise_musgrave_fBm_4d(float4 co,
+                                                    float H,
+                                                    float lacunarity,
+                                                    float octaves)
 {
-  if (type == NODE_MUSGRAVE_MULTIFRACTAL)
-    return intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves);
-  else if (type == NODE_MUSGRAVE_FBM)
-    return intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves);
-  else if (type == NODE_MUSGRAVE_HYBRID_MULTIFRACTAL)
-    return intensity *
-           noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
-  else if (type == NODE_MUSGRAVE_RIDGED_MULTIFRACTAL)
-    return intensity *
-           noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
-  else if (type == NODE_MUSGRAVE_HETERO_TERRAIN)
-    return intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, offset);
+  float4 p = co;
+  float value = 0.0f;
+  float pwr = 1.0f;
+  float pwHL = powf(lacunarity, -H);
+
+  for (int i = 0; i < float_to_int(octaves); i++) {
+    value += snoise_4d(p) * pwr;
+    pwr *= pwHL;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floorf(octaves);
+  if (rmd != 0.0f) {
+    value += rmd * snoise_4d(p) * pwr;
+  }
 
-  return 0.0f;
+  return value;
 }
 
-ccl_device void svm_node_tex_musgrave(
-    KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
+/* 4D Musgrave Multifractal
+ *
+ * H: highest fractal dimension
+ * lacunarity: gap between successive frequencies
+ * octaves: number of frequencies in the fBm
+ */
+
+ccl_device_noinline_cpu float noise_musgrave_multi_fractal_4d(float4 co,
+                                                              float H,
+                                                              float lacunarity,
+                                                              float octaves)
 {
-  uint4 node2 = read_node(kg, offset);
-  uint4 node3 = read_node(kg, offset);
+  float4 p = co;
+  float value = 1.0f;
+  float pwr = 1.0f;
+  float pwHL = powf(lacunarity, -H);
 
-  uint type, co_offset, color_offset, fac_offset;
-  uint dimension_offset, lacunarity_offset, detail_offset, offset_offset;
-  uint gain_offset, scale_offset;
+  for (int i = 0; i < float_to_int(octaves); i++) {
+    value *= (pwr * snoise_4d(p) + 1.0f);
+    pwr *= pwHL;
+    p *= lacunarity;
+  }
 
-  svm_unpack_node_uchar4(node.y, &type, &co_offset, &color_offset, &fac_offset);
-  svm_unpack_node_uchar4(
-      node.z, &dimension_offset, &lacunarity_offset, &detail_offset, &offset_offset);
-  svm_unpack_node_uchar2(node.w, &gain_offset, &scale_offset);
+  float rmd = octaves - floorf(octaves);
+  if (rmd != 0.0f) {
+    value *= (rmd * pwr * snoise_4d(p) + 1.0f); /* correct? */
+  }
 
-  float3 co = stack_load_float3(stack, co_offset);
-  float dimension = stack_load_float_default(stack, dimension_offset, node2.x);
-  float lacunarity = stack_load_float_default(stack, lacunarity_offset, node2.y);
-  float detail = stack_load_float_default(stack, detail_offset, node2.z);
-  float foffset = stack_load_float_default(stack, offset_offset, node2.w);
-  float gain = stack_load_float_default(stack, gain_offset, node3.x);
-  float scale = stack_load_float_default(stack, scale_offset, node3.y);
+  return value;
+}
+
+/* 4D 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'
+ */
+
+ccl_device_noinline_cpu float noise_musgrave_hetero_terrain_4d(
+    float4 co, float H, float lacunarity, float octaves, float offset)
+{
+  float4 p = co;
+  float pwHL = powf(lacunarity, -H);
+  float pwr = pwHL;
+
+  /* first unscaled octave of function; later octaves are scaled */
+  float value = offset + snoise_4d(p);
+  p *= lacunarity;
+
+  for (int i = 1; i < float_to_int(octaves); i++) {
+    float increment = (snoise_4d(p) + offset) * pwr * value;
+    value += increment;
+    pwr *= pwHL;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floorf(octaves);
+  if (rmd != 0.0f) {
+    float increment = (snoise_4d(p) + offset) * pwr * value;
+    value += rmd * increment;
+  }
+
+  return value;
+}
+
+/* 4D 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'
+ */
+
+ccl_device_noinline_cpu float noise_musgrave_hybrid_multi_fractal_4d(
+    float4 co, float H, float lacunarity, float octaves, float offset, float gain)
+{
+  float4 p = co;
+  float pwHL = powf(lacunarity, -H);
+  float pwr = pwHL;
+
+  float value = snoise_4d(p) + offset;
+  float weight = gain * value;
+  p *= lacunarity;
+
+  for (int i = 1; (weight > 0.001f) && (i < float_to_int(octaves)); i++) {
+    if (weight > 1.0f) {
+      weight = 1.0f;
+    }
+
+    float signal = (snoise_4d(p) + offset) * pwr;
+    pwr *= pwHL;
+    value += weight * signal;
+    weight *= gain * signal;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floorf(octaves);
+  if (rmd != 0.0f) {
+    value += rmd * ((snoise_4d(p) + offset) * pwr);
+  }
+
+  return value;
+}
+
+/* 4D 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'
+ */
+
+ccl_device_noinline_cpu float noise_musgrave_ridged_multi_fractal_4d(
+    float4 co, float H, float lacunarity, float octaves, float offset, float gain)
+{
+  float4 p = co;
+  float pwHL = powf(lacunarity, -H);
+  float pwr = pwHL;
+
+  float signal = offset - fabsf(snoise_4d(p));
+  signal *= signal;
+  float value = signal;
+  float weight = 1.0f;
+
+  for (int i = 1; i < float_to_int(octaves); i++) {
+    p *= lacunarity;
+    weight = saturate(signal * gain);
+    signal = offset - fabsf(snoise_4d(p));
+    signal *= signal;
+    signal *= weight;
+    value += signal * pwr;
+    pwr *= pwHL;
+  }
+
+  return value;
+}
+
+ccl_device void svm_node_tex_musgrave(KernelGlobals *kg,
+                                      ShaderData *sd,
+                                      float *stack,
+                                      uint offsets1,
+                                      uint offsets2,
+                                      uint offsets3,
+                                      int *offset)
+{
+  uint type, dimensions, co_stack_offset, w_stack_offset;
+  uint scale_stack_offset, detail_stack_offset, dimension_stack_offset, lacunarity_stack_offset;
+  uint offset_stack_offset, gain_stack_offset, fac_stack_offset;
+
+  svm_unpack_node_uchar4(offsets1, &type, &dimensions, &co_stack_offset, &w_stack_offset);
+  svm_unpack_node_uchar4(offsets2,
+                         &scale_stack_offset,
+                         &detail_stack_offset,
+                         &dimension_stack_offset,
+                         &lacunarity_stack_offset);
+  svm_unpack_node_uchar3(offsets3, &offset_stack_offset, &gain_stack_offset, &fac_stack_offset);
+
+  uint4 defaults1 = read_node(kg, offset);
+  uint4 defaults2 = read_node(kg, offset);
+
+  float3 co = stack_load_float3(stack, co_stack_offset);
+  float w = stack_load_float_default(stack, w_stack_offset, defaults1.x);
+  float scale = stack_load_float_default(stack, scale_stack_offset, defaults1.y);
+  float detail = stack_load_float_default(stack, detail_stack_offset, defaults1.z);
+  float dimension = stack_load_float_default(stack, dimension_stack_offset, defaults1.w);
+  float lacunarity = stack_load_float_default(stack, lacunarity_stack_offset, defaults2.x);
+  float foffset = stack_load_float_default(stack, offset_stack_offset, defaults2.y);
+  float gain = stack_load_float_default(stack, gain_stack_offset, defaults2.z);
 
   dimension = fmaxf(dimension, 1e-5f);
   detail = clamp(detail, 0.0f, 16.0f);
   lacunarity = fmaxf(lacunarity, 1e-5f);
 
-  float f = svm_musgrave(
-      (NodeMusgraveType)type, dimension, lacunarity, detail, foffset, 1.0f, gain, co * scale);
+  float fac;
+
+  switch (dimensions) {
+    case 1: {
+      float p = w * scale;
+      switch ((NodeMusgraveType)type) {
+        case NODE_MUSGRAVE_MULTIFRACTAL:
+          fac = noise_musgrave_multi_fractal_1d(p, dimension, lacunarity, detail);
+          break;
+        case NODE_MUSGRAVE_FBM:
+          fac = noise_musgrave_fBm_1d(p, dimension, lacunarity, detail);
+          break;
+        case NODE_MUSGRAVE_HYBRID_MULTIFRACTAL:
+          fac = noise_musgrave_hybrid_multi_fractal_1d(
+              p, dimension, lacunarity, detail, foffset, gain);
+          break;
+        case NODE_MUSGRAVE_RIDGED_MULTIFRACTAL:
+          fac = noise_musgrave_ridged_multi_fractal_1d(
+              p, dimension, lacunarity, detail, foffset, gain);
+          break;
+        case NODE_MUSGRAVE_HETERO_TERRAIN:
+          fac = noise_musgrave_hetero_terrain_1d(p, dimension, lacunarity, detail, foffset);
+          break;
+        default:
+          fac = 0.0f;
+      }
+      break;
+    }
+    case 2: {
+      float2 p = make_float2(co.x, co.y) * scale;
+      switch ((NodeMusgraveType)type) {
+        case NODE_MUSGRAVE_MULTIFRACTAL:
+          fac = noise_musgrave_multi_fractal_2d(p, dimension, lacunarity, detail);
+          break;
+        case NODE_MUSGRAVE_FBM:
+          fac = noise_musgrave_fBm_2d(p, dimension, lacunarity, detail);
+          break;
+        case NODE_MUSGRAVE_HYBRID_MULTIFRACTAL:
+          fac = noise_musgrave_hybrid_multi_fractal_2d(
+              p, dimension, lacunarity, detail, foffset, gain);
+          break;
+        case NODE_MUSGRAVE_RIDGED_MULTIFRACTAL:
+          fac = noise_musgrave_ridged_multi_fractal_2d(
+              p, dimension, lacunarity, detail, foffset, gain);
+          break;
+        case NODE_MUSGRAVE_HETERO_TERRAIN:
+          fac = noise_musgrave_hetero_terrain_2d(p, dimension, lacunarity, detail, foffset);
+          break;
+        default:
+          fac = 0.0f;
+      }
+      break;
+    }
+    case 3: {
+      float3 p = co * scale;
+      switch ((NodeMusgraveType)type) {
+        case NODE_MUSGRAVE_MULTIFRACTAL:
+          fac = noise_musgrave_multi_fractal_3d(p, dimension, lacunarity, detail);
+          break;
+        case NODE_MUSGRAVE_FBM:
+          fac = noise_musgrave_fBm_3d(p, dimension, lacunarity, detail);
+          break;
+        case NODE_MUSGRAVE_HYBRID_MULTIFRACTAL:
+          fac = noise_musgrave_hybrid_multi_fractal_3d(
+              p, dimension, lacunarity, detail, foffset, gain);
+          break;
+        case NODE_MUSGRAVE_RIDGED_MULTIFRACTAL:
+          fac = noise_musgrave_ridged_multi_fractal_3d(
+              p, dimension, lacunarity, detail, foffset, gain);
+          break;
+        case NODE_MUSGRAVE_HETERO_TERRAIN:
+          fac = noise_musgrave_hetero_terrain_3d(p, dimension, lacunarity, detail, foffset);
+          break;
+        default:
+          fac = 0.0f;
+      }
+      break;
+    }
+    case 4: {
+      float4 p = make_float4(co.x, co.y, co.z, w) * scale;
+      switch ((NodeMusgraveType)type) {
+        case NODE_MUSGRAVE_MULTIFRACTAL:
+          fac = noise_musgrave_multi_fractal_4d(p, dimension, lacunarity, detail);
+          break;
+        case NODE_MUSGRAVE_FBM:
+          fac = noise_musgrave_fBm_4d(p, dimension, lacunarity, detail);
+          break;
+        case NODE_MUSGRAVE_HYBRID_MULTIFRACTAL:
+          fac = noise_musgrave_hybrid_multi_fractal_4d(
+              p, dimension, lacunarity, detail, foffset, gain);
+          break;
+        case NODE_MUSGRAVE_RIDGED_MULTIFRACTAL:
+          fac = noise_musgrave_ridged_multi_fractal_4d(
+              p, dimension, lacunarity, detail, foffset, gain);
+          break;
+        case NODE_MUSGRAVE_HETERO_TERRAIN:
+          fac = noise_musgrave_hetero_terrain_4d(p, dimension, lacunarity, detail, foffset);
+          break;
+        default:
+          fac = 0.0f;
+      }
+      break;
+    }
+    default:
+      fac = 0.0f;
+  }
 
-  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));
+  stack_store_float(stack, fac_stack_offset, fac);
 }
 
 CCL_NAMESPACE_END
index 31dc986a4d1bc9e5acab3a8f88562abab2b535f7..01661a6d1e0c7622f87f729e768b1a0da20c1092 100644 (file)
@@ -1183,6 +1183,13 @@ NODE_DEFINE(MusgraveTextureNode)
 
   TEXTURE_MAPPING_DEFINE(MusgraveTextureNode);
 
+  static NodeEnum dimensions_enum;
+  dimensions_enum.insert("1D", 1);
+  dimensions_enum.insert("2D", 2);
+  dimensions_enum.insert("3D", 3);
+  dimensions_enum.insert("4D", 4);
+  SOCKET_ENUM(dimensions, "Dimensions", dimensions_enum, 3);
+
   static NodeEnum type_enum;
   type_enum.insert("multifractal", NODE_MUSGRAVE_MULTIFRACTAL);
   type_enum.insert("fBM", NODE_MUSGRAVE_FBM);
@@ -1191,16 +1198,16 @@ NODE_DEFINE(MusgraveTextureNode)
   type_enum.insert("hetero_terrain", NODE_MUSGRAVE_HETERO_TERRAIN);
   SOCKET_ENUM(type, "Type", type_enum, NODE_MUSGRAVE_FBM);
 
+  SOCKET_IN_POINT(
+      vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
+  SOCKET_IN_FLOAT(w, "W", 0.0f);
   SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
   SOCKET_IN_FLOAT(detail, "Detail", 2.0f);
   SOCKET_IN_FLOAT(dimension, "Dimension", 2.0f);
   SOCKET_IN_FLOAT(lacunarity, "Lacunarity", 1.0f);
   SOCKET_IN_FLOAT(offset, "Offset", 0.0f);
   SOCKET_IN_FLOAT(gain, "Gain", 1.0f);
-  SOCKET_IN_POINT(
-      vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
 
-  SOCKET_OUT_COLOR(color, "Color");
   SOCKET_OUT_FLOAT(fac, "Fac");
 
   return type;
@@ -1213,35 +1220,38 @@ MusgraveTextureNode::MusgraveTextureNode() : TextureNode(node_type)
 void MusgraveTextureNode::compile(SVMCompiler &compiler)
 {
   ShaderInput *vector_in = input("Vector");
+  ShaderInput *w_in = input("W");
   ShaderInput *scale_in = input("Scale");
+  ShaderInput *detail_in = input("Detail");
   ShaderInput *dimension_in = input("Dimension");
   ShaderInput *lacunarity_in = input("Lacunarity");
-  ShaderInput *detail_in = input("Detail");
   ShaderInput *offset_in = input("Offset");
   ShaderInput *gain_in = input("Gain");
   ShaderOutput *fac_out = output("Fac");
-  ShaderOutput *color_out = output("Color");
 
-  int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
+  int vector_stack_offset = tex_mapping.compile_begin(compiler, vector_in);
+  int w_stack_offset = compiler.stack_assign_if_linked(w_in);
+  int scale_stack_offset = compiler.stack_assign_if_linked(scale_in);
+  int detail_stack_offset = compiler.stack_assign_if_linked(detail_in);
+  int dimension_stack_offset = compiler.stack_assign_if_linked(dimension_in);
+  int lacunarity_stack_offset = compiler.stack_assign_if_linked(lacunarity_in);
+  int offset_stack_offset = compiler.stack_assign_if_linked(offset_in);
+  int gain_stack_offset = compiler.stack_assign_if_linked(gain_in);
+  int fac_stack_offset = compiler.stack_assign(fac_out);
 
-  compiler.add_node(NODE_TEX_MUSGRAVE,
-                    compiler.encode_uchar4(type,
-                                           vector_offset,
-                                           compiler.stack_assign_if_linked(color_out),
-                                           compiler.stack_assign_if_linked(fac_out)),
-                    compiler.encode_uchar4(compiler.stack_assign_if_linked(dimension_in),
-                                           compiler.stack_assign_if_linked(lacunarity_in),
-                                           compiler.stack_assign_if_linked(detail_in),
-                                           compiler.stack_assign_if_linked(offset_in)),
-                    compiler.encode_uchar4(compiler.stack_assign_if_linked(gain_in),
-                                           compiler.stack_assign_if_linked(scale_in)));
-  compiler.add_node(__float_as_int(dimension),
-                    __float_as_int(lacunarity),
-                    __float_as_int(detail),
-                    __float_as_int(offset));
-  compiler.add_node(__float_as_int(gain), __float_as_int(scale));
+  compiler.add_node(
+      NODE_TEX_MUSGRAVE,
+      compiler.encode_uchar4(type, dimensions, vector_stack_offset, w_stack_offset),
+      compiler.encode_uchar4(scale_stack_offset,
+                             detail_stack_offset,
+                             dimension_stack_offset,
+                             lacunarity_stack_offset),
+      compiler.encode_uchar4(offset_stack_offset, gain_stack_offset, fac_stack_offset));
+  compiler.add_node(
+      __float_as_int(w), __float_as_int(scale), __float_as_int(detail), __float_as_int(dimension));
+  compiler.add_node(__float_as_int(lacunarity), __float_as_int(offset), __float_as_int(gain));
 
-  tex_mapping.compile_end(compiler, vector_in, vector_offset);
+  tex_mapping.compile_end(compiler, vector_in, vector_stack_offset);
 }
 
 void MusgraveTextureNode::compile(OSLCompiler &compiler)
@@ -1249,6 +1259,7 @@ void MusgraveTextureNode::compile(OSLCompiler &compiler)
   tex_mapping.compile(compiler);
 
   compiler.parameter(this, "type");
+  compiler.parameter(this, "dimensions");
   compiler.add(this, "node_musgrave_texture");
 }
 
index 769687f1f190d2f4ad7c5c89c63d9249ab9121f2..5d7e074f62b19ee1b24088fd80268157cbd3c086 100644 (file)
@@ -236,8 +236,9 @@ class MusgraveTextureNode : public TextureNode {
     return NODE_GROUP_LEVEL_2;
   }
 
+  int dimensions;
   NodeMusgraveType type;
-  float scale, detail, dimension, lacunarity, offset, gain;
+  float w, scale, detail, dimension, lacunarity, offset, gain;
   float3 vector;
 };
 
index 24a48b2913b9de84b1ed49be098aa1c4df72d049..b9ea85e7a00c778d380ae2875b6f8e85a1ed180e 100644 (file)
@@ -27,7 +27,7 @@
  * \note Use #STRINGIFY() rather than defining with quotes.
  */
 #define BLENDER_VERSION 281
-#define BLENDER_SUBVERSION 9
+#define BLENDER_SUBVERSION 10
 /** Several breakages with 280, e.g. collections vs layers. */
 #define BLENDER_MINVERSION 280
 #define BLENDER_MINSUBVERSION 0
index d4d940daba53916b95bb1c5f76e9a184547b6fc6..98f8820e4adf1bdc00d8e74868a8842df749b894 100644 (file)
@@ -911,6 +911,34 @@ static void update_mapping_node_inputs_and_properties(bNodeTree *ntree)
   }
 }
 
+/* The Musgrave node now has a dimension property. This property should
+ * be initialized to 3 by default.
+ */
+static void update_musgrave_node_dimensions(bNodeTree *ntree)
+{
+  for (bNode *node = ntree->nodes.first; node; node = node->next) {
+    if (node->type == SH_NODE_TEX_MUSGRAVE) {
+      NodeTexMusgrave *tex = (NodeTexMusgrave *)node->storage;
+      tex->dimensions = 3;
+    }
+  }
+}
+
+/* The Color output of the Musgrave node has been removed. Previously, this
+ * output was just equal to the Fac output. To correct this, we move links
+ * from the Color output to the Fac output if they exist.
+ */
+static void update_musgrave_node_color_output(bNodeTree *ntree)
+{
+  LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
+    if (link->fromnode && link->fromnode->type == SH_NODE_TEX_MUSGRAVE) {
+      if (link->fromsock->type == SOCK_RGBA) {
+        link->fromsock = link->fromsock->next;
+      }
+    }
+  }
+}
+
 void blo_do_versions_cycles(FileData *UNUSED(fd), Library *UNUSED(lib), Main *bmain)
 {
   /* Particle shape shared with Eevee. */
@@ -952,6 +980,15 @@ void blo_do_versions_cycles(FileData *UNUSED(fd), Library *UNUSED(lib), Main *bm
     }
     FOREACH_NODETREE_END;
   }
+
+  if (!MAIN_VERSION_ATLEAST(bmain, 281, 10)) {
+    FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+      if (ntree->type == NTREE_SHADER) {
+        update_musgrave_node_color_output(ntree);
+      }
+    }
+    FOREACH_NODETREE_END;
+  }
 }
 
 void do_versions_after_linking_cycles(Main *bmain)
@@ -1101,4 +1138,13 @@ void do_versions_after_linking_cycles(Main *bmain)
     }
     FOREACH_NODETREE_END;
   }
+
+  if (!MAIN_VERSION_ATLEAST(bmain, 281, 10)) {
+    FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+      if (ntree->type == NTREE_SHADER) {
+        update_musgrave_node_dimensions(ntree);
+      }
+    }
+    FOREACH_NODETREE_END;
+  }
 }
index 23d452412ea7bef216452d7f69acbe4f880ea1ec..c707a1eed926124f29e0c4786b585fbe479720a5 100644 (file)
@@ -908,6 +908,7 @@ static void node_shader_buts_tex_wave(uiLayout *layout, bContext *UNUSED(C), Poi
 
 static void node_shader_buts_tex_musgrave(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
 {
+  uiItemR(layout, ptr, "musgrave_dimensions", 0, "", ICON_NONE);
   uiItemR(layout, ptr, "musgrave_type", 0, "", ICON_NONE);
 }
 
index 52332c45c3d0cedd6fe70294ed861de82d995ed1..7ecca286acde412ffd575ac61be6793a81c069e7 100644 (file)
@@ -1,4 +1,4 @@
-/* Musgrave fBm
+/* 1D Musgrave fBm
  *
  * H: fractal increment parameter
  * lacunarity: gap between successive frequencies
@@ -7,9 +7,465 @@
  * from "Texturing and Modelling: A procedural approach"
  */
 
-float noise_musgrave_fBm(vec3 p, float H, float lacunarity, float octaves)
+void node_tex_musgrave_fBm_1d(vec3 co,
+                              float w,
+                              float scale,
+                              float detail,
+                              float dimension,
+                              float lac,
+                              float offset,
+                              float gain,
+                              out float fac)
 {
-  float rmd;
+  float p = w * scale;
+  float H = max(dimension, 1e-5);
+  float octaves = clamp(detail, 0.0, 16.0);
+  float lacunarity = max(lac, 1e-5);
+
+  float value = 0.0;
+  float pwr = 1.0;
+  float pwHL = pow(lacunarity, -H);
+
+  for (int i = 0; i < int(octaves); i++) {
+    value += snoise(p) * pwr;
+    pwr *= pwHL;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floor(octaves);
+  if (rmd != 0.0) {
+    value += rmd * snoise(p) * pwr;
+  }
+
+  fac = value;
+}
+
+/* 1D Musgrave Multifractal
+ *
+ * H: highest fractal dimension
+ * lacunarity: gap between successive frequencies
+ * octaves: number of frequencies in the fBm
+ */
+
+void node_tex_musgrave_multi_fractal_1d(vec3 co,
+                                        float w,
+                                        float scale,
+                                        float detail,
+                                        float dimension,
+                                        float lac,
+                                        float offset,
+                                        float gain,
+                                        out float fac)
+{
+  float p = w * scale;
+  float H = max(dimension, 1e-5);
+  float octaves = clamp(detail, 0.0, 16.0);
+  float lacunarity = max(lac, 1e-5);
+
+  float value = 1.0;
+  float pwr = 1.0;
+  float pwHL = pow(lacunarity, -H);
+
+  for (int i = 0; i < int(octaves); i++) {
+    value *= (pwr * snoise(p) + 1.0);
+    pwr *= pwHL;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floor(octaves);
+  if (rmd != 0.0) {
+    value *= (rmd * pwr * snoise(p) + 1.0); /* correct? */
+  }
+
+  fac = value;
+}
+
+/* 1D 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'
+ */
+
+void node_tex_musgrave_hetero_terrain_1d(vec3 co,
+                                         float w,
+                                         float scale,
+                                         float detail,
+                                         float dimension,
+                                         float lac,
+                                         float offset,
+                                         float gain,
+                                         out float fac)
+{
+  float p = w * scale;
+  float H = max(dimension, 1e-5);
+  float octaves = clamp(detail, 0.0, 16.0);
+  float lacunarity = max(lac, 1e-5);
+
+  float pwHL = pow(lacunarity, -H);
+  float pwr = pwHL;
+
+  /* first unscaled octave of function; later octaves are scaled */
+  float value = offset + snoise(p);
+  p *= lacunarity;
+
+  for (int i = 1; i < int(octaves); i++) {
+    float increment = (snoise(p) + offset) * pwr * value;
+    value += increment;
+    pwr *= pwHL;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floor(octaves);
+  if (rmd != 0.0) {
+    float increment = (snoise(p) + offset) * pwr * value;
+    value += rmd * increment;
+  }
+
+  fac = value;
+}
+
+/* 1D 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'
+ */
+
+void node_tex_musgrave_hybrid_multi_fractal_1d(vec3 co,
+                                               float w,
+                                               float scale,
+                                               float detail,
+                                               float dimension,
+                                               float lac,
+                                               float offset,
+                                               float gain,
+                                               out float fac)
+{
+  float p = w * scale;
+  float H = max(dimension, 1e-5);
+  float octaves = clamp(detail, 0.0, 16.0);
+  float lacunarity = max(lac, 1e-5);
+
+  float pwHL = pow(lacunarity, -H);
+  float pwr = pwHL;
+
+  float value = snoise(p) + offset;
+  float weight = gain * value;
+  p *= lacunarity;
+
+  for (int i = 1; (weight > 0.001f) && (i < int(octaves)); i++) {
+    if (weight > 1.0) {
+      weight = 1.0;
+    }
+
+    float signal = (snoise(p) + offset) * pwr;
+    pwr *= pwHL;
+    value += weight * signal;
+    weight *= gain * signal;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floor(octaves);
+  if (rmd != 0.0) {
+    value += rmd * ((snoise(p) + offset) * pwr);
+  }
+
+  fac = value;
+}
+
+/* 1D 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'
+ */
+
+void node_tex_musgrave_ridged_multi_fractal_1d(vec3 co,
+                                               float w,
+                                               float scale,
+                                               float detail,
+                                               float dimension,
+                                               float lac,
+                                               float offset,
+                                               float gain,
+                                               out float fac)
+{
+  float p = w * scale;
+  float H = max(dimension, 1e-5);
+  float octaves = clamp(detail, 0.0, 16.0);
+  float lacunarity = max(lac, 1e-5);
+
+  float pwHL = pow(lacunarity, -H);
+  float pwr = pwHL;
+
+  float signal = offset - abs(snoise(p));
+  signal *= signal;
+  float value = signal;
+  float weight = 1.0;
+
+  for (int 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;
+    value += signal * pwr;
+    pwr *= pwHL;
+  }
+
+  fac = value;
+}
+
+/* 2D 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"
+ */
+
+void node_tex_musgrave_fBm_2d(vec3 co,
+                              float w,
+                              float scale,
+                              float detail,
+                              float dimension,
+                              float lac,
+                              float offset,
+                              float gain,
+                              out float fac)
+{
+  vec2 p = co.xy * scale;
+  float H = max(dimension, 1e-5);
+  float octaves = clamp(detail, 0.0, 16.0);
+  float lacunarity = max(lac, 1e-5);
+
+  float value = 0.0;
+  float pwr = 1.0;
+  float pwHL = pow(lacunarity, -H);
+
+  for (int i = 0; i < int(octaves); i++) {
+    value += snoise(p) * pwr;
+    pwr *= pwHL;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floor(octaves);
+  if (rmd != 0.0) {
+    value += rmd * snoise(p) * pwr;
+  }
+
+  fac = value;
+}
+
+/* 2D Musgrave Multifractal
+ *
+ * H: highest fractal dimension
+ * lacunarity: gap between successive frequencies
+ * octaves: number of frequencies in the fBm
+ */
+
+void node_tex_musgrave_multi_fractal_2d(vec3 co,
+                                        float w,
+                                        float scale,
+                                        float detail,
+                                        float dimension,
+                                        float lac,
+                                        float offset,
+                                        float gain,
+                                        out float fac)
+{
+  vec2 p = co.xy * scale;
+  float H = max(dimension, 1e-5);
+  float octaves = clamp(detail, 0.0, 16.0);
+  float lacunarity = max(lac, 1e-5);
+
+  float value = 1.0;
+  float pwr = 1.0;
+  float pwHL = pow(lacunarity, -H);
+
+  for (int i = 0; i < int(octaves); i++) {
+    value *= (pwr * snoise(p) + 1.0);
+    pwr *= pwHL;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floor(octaves);
+  if (rmd != 0.0) {
+    value *= (rmd * pwr * snoise(p) + 1.0); /* correct? */
+  }
+
+  fac = value;
+}
+
+/* 2D 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'
+ */
+
+void node_tex_musgrave_hetero_terrain_2d(vec3 co,
+                                         float w,
+                                         float scale,
+                                         float detail,
+                                         float dimension,
+                                         float lac,
+                                         float offset,
+                                         float gain,
+                                         out float fac)
+{
+  vec2 p = co.xy * scale;
+  float H = max(dimension, 1e-5);
+  float octaves = clamp(detail, 0.0, 16.0);
+  float lacunarity = max(lac, 1e-5);
+
+  float pwHL = pow(lacunarity, -H);
+  float pwr = pwHL;
+
+  /* first unscaled octave of function; later octaves are scaled */
+  float value = offset + snoise(p);
+  p *= lacunarity;
+
+  for (int i = 1; i < int(octaves); i++) {
+    float increment = (snoise(p) + offset) * pwr * value;
+    value += increment;
+    pwr *= pwHL;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floor(octaves);
+  if (rmd != 0.0) {
+    float increment = (snoise(p) + offset) * pwr * value;
+    value += rmd * increment;
+  }
+
+  fac = value;
+}
+
+/* 2D 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'
+ */
+
+void node_tex_musgrave_hybrid_multi_fractal_2d(vec3 co,
+                                               float w,
+                                               float scale,
+                                               float detail,
+                                               float dimension,
+                                               float lac,
+                                               float offset,
+                                               float gain,
+                                               out float fac)
+{
+  vec2 p = co.xy * scale;
+  float H = max(dimension, 1e-5);
+  float octaves = clamp(detail, 0.0, 16.0);
+  float lacunarity = max(lac, 1e-5);
+
+  float pwHL = pow(lacunarity, -H);
+  float pwr = pwHL;
+
+  float value = snoise(p) + offset;
+  float weight = gain * value;
+  p *= lacunarity;
+
+  for (int i = 1; (weight > 0.001f) && (i < int(octaves)); i++) {
+    if (weight > 1.0) {
+      weight = 1.0;
+    }
+
+    float signal = (snoise(p) + offset) * pwr;
+    pwr *= pwHL;
+    value += weight * signal;
+    weight *= gain * signal;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floor(octaves);
+  if (rmd != 0.0) {
+    value += rmd * ((snoise(p) + offset) * pwr);
+  }
+
+  fac = value;
+}
+
+/* 2D 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'
+ */
+
+void node_tex_musgrave_ridged_multi_fractal_2d(vec3 co,
+                                               float w,
+                                               float scale,
+                                               float detail,
+                                               float dimension,
+                                               float lac,
+                                               float offset,
+                                               float gain,
+                                               out float fac)
+{
+  vec2 p = co.xy * scale;
+  float H = max(dimension, 1e-5);
+  float octaves = clamp(detail, 0.0, 16.0);
+  float lacunarity = max(lac, 1e-5);
+
+  float pwHL = pow(lacunarity, -H);
+  float pwr = pwHL;
+
+  float signal = offset - abs(snoise(p));
+  signal *= signal;
+  float value = signal;
+  float weight = 1.0;
+
+  for (int 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;
+    value += signal * pwr;
+    pwr *= pwHL;
+  }
+
+  fac = value;
+}
+
+/* 3D 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"
+ */
+
+void node_tex_musgrave_fBm_3d(vec3 co,
+                              float w,
+                              float scale,
+                              float detail,
+                              float dimension,
+                              float lac,
+                              float offset,
+                              float gain,
+                              out float fac)
+{
+  vec3 p = co * scale;
+  float H = max(dimension, 1e-5);
+  float octaves = clamp(detail, 0.0, 16.0);
+  float lacunarity = max(lac, 1e-5);
+
   float value = 0.0;
   float pwr = 1.0;
   float pwHL = pow(lacunarity, -H);
@@ -20,24 +476,36 @@ float noise_musgrave_fBm(vec3 p, float H, float lacunarity, float octaves)
     p *= lacunarity;
   }
 
-  rmd = octaves - floor(octaves);
+  float rmd = octaves - floor(octaves);
   if (rmd != 0.0) {
     value += rmd * snoise(p) * pwr;
   }
 
-  return value;
+  fac = value;
 }
 
-/* Musgrave Multifractal
+/* 3D 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)
+void node_tex_musgrave_multi_fractal_3d(vec3 co,
+                                        float w,
+                                        float scale,
+                                        float detail,
+                                        float dimension,
+                                        float lac,
+                                        float offset,
+                                        float gain,
+                                        out float fac)
 {
-  float rmd;
+  vec3 p = co * scale;
+  float H = max(dimension, 1e-5);
+  float octaves = clamp(detail, 0.0, 16.0);
+  float lacunarity = max(lac, 1e-5);
+
   float value = 1.0;
   float pwr = 1.0;
   float pwHL = pow(lacunarity, -H);
@@ -48,15 +516,15 @@ float noise_musgrave_multi_fractal(vec3 p, float H, float lacunarity, float octa
     p *= lacunarity;
   }
 
-  rmd = octaves - floor(octaves);
+  float rmd = octaves - floor(octaves);
   if (rmd != 0.0) {
     value *= (rmd * pwr * snoise(p) + 1.0); /* correct? */
   }
 
-  return value;
+  fac = value;
 }
 
-/* Musgrave Heterogeneous Terrain
+/* 3D Musgrave Heterogeneous Terrain
  *
  * H: fractal dimension of the roughest area
  * lacunarity: gap between successive frequencies
@@ -64,33 +532,45 @@ float noise_musgrave_multi_fractal(vec3 p, float H, float lacunarity, float octa
  * offset: raises the terrain from `sea level'
  */
 
-float noise_musgrave_hetero_terrain(vec3 p, float H, float lacunarity, float octaves, float offset)
+void node_tex_musgrave_hetero_terrain_3d(vec3 co,
+                                         float w,
+                                         float scale,
+                                         float detail,
+                                         float dimension,
+                                         float lac,
+                                         float offset,
+                                         float gain,
+                                         out float fac)
 {
-  float value, increment, rmd;
+  vec3 p = co * scale;
+  float H = max(dimension, 1e-5);
+  float octaves = clamp(detail, 0.0, 16.0);
+  float lacunarity = max(lac, 1e-5);
+
   float pwHL = pow(lacunarity, -H);
   float pwr = pwHL;
 
   /* first unscaled octave of function; later octaves are scaled */
-  value = offset + snoise(p);
+  float value = offset + snoise(p);
   p *= lacunarity;
 
   for (int i = 1; i < int(octaves); i++) {
-    increment = (snoise(p) + offset) * pwr * value;
+    float increment = (snoise(p) + offset) * pwr * value;
     value += increment;
     pwr *= pwHL;
     p *= lacunarity;
   }
 
-  rmd = octaves - floor(octaves);
+  float rmd = octaves - floor(octaves);
   if (rmd != 0.0) {
-    increment = (snoise(p) + offset) * pwr * value;
+    float increment = (snoise(p) + offset) * pwr * value;
     value += rmd * increment;
   }
 
-  return value;
+  fac = value;
 }
 
-/* Hybrid Additive/Multiplicative Multifractal Terrain
+/* 3D Hybrid Additive/Multiplicative Multifractal Terrain
  *
  * H: fractal dimension of the roughest area
  * lacunarity: gap between successive frequencies
@@ -98,15 +578,26 @@ float noise_musgrave_hetero_terrain(vec3 p, float H, float lacunarity, float oct
  * 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)
+void node_tex_musgrave_hybrid_multi_fractal_3d(vec3 co,
+                                               float w,
+                                               float scale,
+                                               float detail,
+                                               float dimension,
+                                               float lac,
+                                               float offset,
+                                               float gain,
+                                               out float fac)
 {
-  float result, signal, weight, rmd;
+  vec3 p = co * scale;
+  float H = max(dimension, 1e-5);
+  float octaves = clamp(detail, 0.0, 16.0);
+  float lacunarity = max(lac, 1e-5);
+
   float pwHL = pow(lacunarity, -H);
   float pwr = pwHL;
 
-  result = snoise(p) + offset;
-  weight = gain * result;
+  float value = snoise(p) + offset;
+  float weight = gain * value;
   p *= lacunarity;
 
   for (int i = 1; (weight > 0.001f) && (i < int(octaves)); i++) {
@@ -114,22 +605,22 @@ float noise_musgrave_hybrid_multi_fractal(
       weight = 1.0;
     }
 
-    signal = (snoise(p) + offset) * pwr;
+    float signal = (snoise(p) + offset) * pwr;
     pwr *= pwHL;
-    result += weight * signal;
+    value += weight * signal;
     weight *= gain * signal;
     p *= lacunarity;
   }
 
-  rmd = octaves - floor(octaves);
+  float rmd = octaves - floor(octaves);
   if (rmd != 0.0) {
-    result += rmd * ((snoise(p) + offset) * pwr);
+    value += rmd * ((snoise(p) + offset) * pwr);
   }
 
-  return result;
+  fac = value;
 }
 
-/* Ridged Multifractal Terrain
+/* 3D Ridged Multifractal Terrain
  *
  * H: fractal dimension of the roughest area
  * lacunarity: gap between successive frequencies
@@ -137,17 +628,28 @@ float noise_musgrave_hybrid_multi_fractal(
  * 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)
+void node_tex_musgrave_ridged_multi_fractal_3d(vec3 co,
+                                               float w,
+                                               float scale,
+                                               float detail,
+                                               float dimension,
+                                               float lac,
+                                               float offset,
+                                               float gain,
+                                               out float fac)
 {
-  float result, signal, weight;
+  vec3 p = co * scale;
+  float H = max(dimension, 1e-5);
+  float octaves = clamp(detail, 0.0, 16.0);
+  float lacunarity = max(lac, 1e-5);
+
   float pwHL = pow(lacunarity, -H);
   float pwr = pwHL;
 
-  signal = offset - abs(snoise(p));
+  float signal = offset - abs(snoise(p));
   signal *= signal;
-  result = signal;
-  weight = 1.0;
+  float value = signal;
+  float weight = 1.0;
 
   for (int i = 1; i < int(octaves); i++) {
     p *= lacunarity;
@@ -155,54 +657,231 @@ float noise_musgrave_ridged_multi_fractal(
     signal = offset - abs(snoise(p));
     signal *= signal;
     signal *= weight;
-    result += signal * pwr;
+    value += signal * pwr;
     pwr *= pwHL;
   }
 
-  return result;
+  fac = value;
 }
 
-float svm_musgrave(int type,
-                   float dimension,
-                   float lacunarity,
-                   float octaves,
-                   float offset,
-                   float intensity,
-                   float gain,
-                   vec3 p)
+/* 4D 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"
+ */
+
+void node_tex_musgrave_fBm_4d(vec3 co,
+                              float w,
+                              float scale,
+                              float detail,
+                              float dimension,
+                              float lac,
+                              float offset,
+                              float gain,
+                              out float fac)
 {
-  if (type == 0 /* NODE_MUSGRAVE_MULTIFRACTAL */) {
-    return intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves);
+  vec4 p = vec4(co, w) * scale;
+  float H = max(dimension, 1e-5);
+  float octaves = clamp(detail, 0.0, 16.0);
+  float lacunarity = max(lac, 1e-5);
+
+  float value = 0.0;
+  float pwr = 1.0;
+  float pwHL = pow(lacunarity, -H);
+
+  for (int i = 0; i < int(octaves); i++) {
+    value += snoise(p) * pwr;
+    pwr *= pwHL;
+    p *= lacunarity;
   }
-  else if (type == 1 /* NODE_MUSGRAVE_FBM */) {
-    return intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves);
+
+  float rmd = octaves - floor(octaves);
+  if (rmd != 0.0) {
+    value += rmd * snoise(p) * pwr;
   }
-  else if (type == 2 /* NODE_MUSGRAVE_HYBRID_MULTIFRACTAL */) {
-    return intensity *
-           noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
+
+  fac = value;
+}
+
+/* 4D Musgrave Multifractal
+ *
+ * H: highest fractal dimension
+ * lacunarity: gap between successive frequencies
+ * octaves: number of frequencies in the fBm
+ */
+
+void node_tex_musgrave_multi_fractal_4d(vec3 co,
+                                        float w,
+                                        float scale,
+                                        float detail,
+                                        float dimension,
+                                        float lac,
+                                        float offset,
+                                        float gain,
+                                        out float fac)
+{
+  vec4 p = vec4(co, w) * scale;
+  float H = max(dimension, 1e-5);
+  float octaves = clamp(detail, 0.0, 16.0);
+  float lacunarity = max(lac, 1e-5);
+
+  float value = 1.0;
+  float pwr = 1.0;
+  float pwHL = pow(lacunarity, -H);
+
+  for (int i = 0; i < int(octaves); i++) {
+    value *= (pwr * snoise(p) + 1.0);
+    pwr *= pwHL;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floor(octaves);
+  if (rmd != 0.0) {
+    value *= (rmd * pwr * snoise(p) + 1.0); /* correct? */
+  }
+
+  fac = value;
+}
+
+/* 4D 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'
+ */
+
+void node_tex_musgrave_hetero_terrain_4d(vec3 co,
+                                         float w,
+                                         float scale,
+                                         float detail,
+                                         float dimension,
+                                         float lac,
+                                         float offset,
+                                         float gain,
+                                         out float fac)
+{
+  vec4 p = vec4(co, w) * scale;
+  float H = max(dimension, 1e-5);
+  float octaves = clamp(detail, 0.0, 16.0);
+  float lacunarity = max(lac, 1e-5);
+
+  float pwHL = pow(lacunarity, -H);
+  float pwr = pwHL;
+
+  /* first unscaled octave of function; later octaves are scaled */
+  float value = offset + snoise(p);
+  p *= lacunarity;
+
+  for (int i = 1; i < int(octaves); i++) {
+    float increment = (snoise(p) + offset) * pwr * value;
+    value += increment;
+    pwr *= pwHL;
+    p *= lacunarity;
+  }
+
+  float rmd = octaves - floor(octaves);
+  if (rmd != 0.0) {
+    float increment = (snoise(p) + offset) * pwr * value;
+    value += rmd * increment;
   }
-  else if (type == 3 /* NODE_MUSGRAVE_RIDGED_MULTIFRACTAL */) {
-    return intensity *
-           noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
+
+  fac = value;
+}
+
+/* 4D 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'
+ */
+
+void node_tex_musgrave_hybrid_multi_fractal_4d(vec3 co,
+                                               float w,
+                                               float scale,
+                                               float detail,
+                                               float dimension,
+                                               float lac,
+                                               float offset,
+                                               float gain,
+                                               out float fac)
+{
+  vec4 p = vec4(co, w) * scale;
+  float H = max(dimension, 1e-5);
+  float octaves = clamp(detail, 0.0, 16.0);
+  float lacunarity = max(lac, 1e-5);
+
+  float pwHL = pow(lacunarity, -H);
+  float pwr = pwHL;
+
+  float value = snoise(p) + offset;
+  float weight = gain * value;
+  p *= lacunarity;
+
+  for (int i = 1; (weight > 0.001f) && (i < int(octaves)); i++) {
+    if (weight > 1.0) {
+      weight = 1.0;
+    }
+
+    float signal = (snoise(p) + offset) * pwr;
+    pwr *= pwHL;
+    value += weight * signal;
+    weight *= gain * signal;
+    p *= lacunarity;
   }
-  else if (type == 4 /* NODE_MUSGRAVE_HETERO_TERRAIN */) {
-    return intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, offset);
+
+  float rmd = octaves - floor(octaves);
+  if (rmd != 0.0) {
+    value += rmd * ((snoise(p) + offset) * pwr);
   }
-  return 0.0;
+
+  fac = value;
 }
 
-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)
+/* 4D 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'
+ */
+
+void node_tex_musgrave_ridged_multi_fractal_4d(vec3 co,
+                                               float w,
+                                               float scale,
+                                               float detail,
+                                               float dimension,
+                                               float lac,
+                                               float offset,
+                                               float gain,
+                                               out float fac)
 {
-  fac = svm_musgrave(int(type), dimension, lacunarity, detail, offset, 1.0, gain, co *scale);
+  vec4 p = vec4(co, w) * scale;
+  float H = max(dimension, 1e-5);
+  float octaves = clamp(detail, 0.0, 16.0);
+  float lacunarity = max(lac, 1e-5);
+
+  float pwHL = pow(lacunarity, -H);
+  float pwr = pwHL;
+
+  float signal = offset - abs(snoise(p));
+  signal *= signal;
+  float value = signal;
+  float weight = 1.0;
+
+  for (int 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;
+    value += signal * pwr;
+    pwr *= pwHL;
+  }
 
-  color = vec4(fac, fac, fac, 1.0);
+  fac = value;
 }
index 6d2b278472fbf08e087f38fb1a349434d419f293..b4e12484bdcda8d015fa1e83e413944c50848abd 100644 (file)
@@ -885,7 +885,7 @@ typedef struct NodeTexVoronoi {
 typedef struct NodeTexMusgrave {
   NodeTexBase base;
   int musgrave_type;
-  char _pad[4];
+  int dimensions;
 } NodeTexMusgrave;
 
 typedef struct NodeTexWave {
index 0598f4807ecd33003994f8549ee96681e244a31b..a648134186891881f61ec221edc94ccd010480e4 100644 (file)
@@ -4389,11 +4389,17 @@ static void def_sh_tex_musgrave(StructRNA *srna)
   RNA_def_struct_sdna_from(srna, "NodeTexMusgrave", "storage");
   def_sh_tex(srna);
 
+  prop = RNA_def_property(srna, "musgrave_dimensions", PROP_ENUM, PROP_NONE);
+  RNA_def_property_enum_sdna(prop, NULL, "dimensions");
+  RNA_def_property_enum_items(prop, rna_enum_node_tex_dimensions_items);
+  RNA_def_property_ui_text(prop, "Dimensions", "");
+  RNA_def_property_update(prop, 0, "rna_ShaderNode_socket_update");
+
   prop = RNA_def_property(srna, "musgrave_type", PROP_ENUM, PROP_NONE);
   RNA_def_property_enum_sdna(prop, NULL, "musgrave_type");
   RNA_def_property_enum_items(prop, prop_musgrave_type);
   RNA_def_property_ui_text(prop, "Type", "");
-  RNA_def_property_update(prop, 0, "rna_Node_update");
+  RNA_def_property_update(prop, 0, "rna_ShaderNode_socket_update");
 }
 
 static void def_sh_tex_voronoi(StructRNA *srna)
index 1a959b8faa80b43ca2e12c3602111a17893ff613..daf4053f1826ebd9ccf3247ede9affff4850cf08 100644 (file)
@@ -23,6 +23,7 @@
 
 static bNodeSocketTemplate sh_node_tex_musgrave_in[] = {
     {SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
+    {SOCK_FLOAT, 1, N_("W"), 0.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
     {SOCK_FLOAT, 1, N_("Scale"), 5.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
     {SOCK_FLOAT, 1, N_("Detail"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 16.0f},
     {SOCK_FLOAT, 1, N_("Dimension"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
@@ -33,17 +34,6 @@ static bNodeSocketTemplate sh_node_tex_musgrave_in[] = {
 };
 
 static bNodeSocketTemplate sh_node_tex_musgrave_out[] = {
-    {SOCK_RGBA,
-     0,
-     N_("Color"),
-     0.0f,
-     0.0f,
-     0.0f,
-     0.0f,
-     0.0f,
-     1.0f,
-     PROP_NONE,
-     SOCK_NO_INTERNAL_LINK},
     {SOCK_FLOAT,
      0,
      N_("Fac"),
@@ -64,6 +54,7 @@ static void node_shader_init_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *node)
   BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
   BKE_texture_colormapping_default(&tex->base.color_mapping);
   tex->musgrave_type = SHD_MUSGRAVE_FBM;
+  tex->dimensions = 3;
 
   node->storage = tex;
 }
@@ -78,12 +69,77 @@ static int node_shader_gpu_tex_musgrave(GPUMaterial *mat,
   node_shader_gpu_tex_mapping(mat, node, in, out);
 
   NodeTexMusgrave *tex = (NodeTexMusgrave *)node->storage;
-  float type = tex->musgrave_type;
+  int dimensions = tex->dimensions;
+  int type = tex->musgrave_type;
+
+  static const char *names[][5] = {
+      [SHD_MUSGRAVE_MULTIFRACTAL] =
+          {
+              "",
+              "node_tex_musgrave_multi_fractal_1d",
+              "node_tex_musgrave_multi_fractal_2d",
+              "node_tex_musgrave_multi_fractal_3d",
+              "node_tex_musgrave_multi_fractal_4d",
+          },
+      [SHD_MUSGRAVE_FBM] =
+          {
+              "",
+              "node_tex_musgrave_fBm_1d",
+              "node_tex_musgrave_fBm_2d",
+              "node_tex_musgrave_fBm_3d",
+              "node_tex_musgrave_fBm_4d",
+          },
+      [SHD_MUSGRAVE_HYBRID_MULTIFRACTAL] =
+          {
+              "",
+              "node_tex_musgrave_hybrid_multi_fractal_1d",
+              "node_tex_musgrave_hybrid_multi_fractal_2d",
+              "node_tex_musgrave_hybrid_multi_fractal_3d",
+              "node_tex_musgrave_hybrid_multi_fractal_4d",
+          },
+      [SHD_MUSGRAVE_RIDGED_MULTIFRACTAL] =
+          {
+              "",
+              "node_tex_musgrave_ridged_multi_fractal_1d",
+              "node_tex_musgrave_ridged_multi_fractal_2d",
+              "node_tex_musgrave_ridged_multi_fractal_3d",
+              "node_tex_musgrave_ridged_multi_fractal_4d",
+          },
+      [SHD_MUSGRAVE_HETERO_TERRAIN] =
+          {
+              "",
+              "node_tex_musgrave_hetero_terrain_1d",
+              "node_tex_musgrave_hetero_terrain_2d",
+              "node_tex_musgrave_hetero_terrain_3d",
+              "node_tex_musgrave_hetero_terrain_4d",
+          },
+  };
+
+  BLI_assert(type >= 0 && type < 5);
+  BLI_assert(dimensions > 0 && dimensions < 5);
+
+  return GPU_stack_link(mat, node, names[type][dimensions], in, out);
+}
+
+static void node_shader_update_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *node)
+{
+  NodeTexMusgrave *tex = (NodeTexMusgrave *)node->storage;
+
+  bNodeSocket *inVectorSock = nodeFindSocket(node, SOCK_IN, "Vector");
+  bNodeSocket *inWSock = nodeFindSocket(node, SOCK_IN, "W");
+  bNodeSocket *inOffsetSock = nodeFindSocket(node, SOCK_IN, "Offset");
+  bNodeSocket *inGainSock = nodeFindSocket(node, SOCK_IN, "Gain");
 
-  return GPU_stack_link(mat, node, "node_tex_musgrave", in, out, GPU_constant(&type));
+  nodeSetSocketAvailability(inVectorSock, tex->dimensions != 1);
+  nodeSetSocketAvailability(inWSock, tex->dimensions == 1 || tex->dimensions == 4);
+  nodeSetSocketAvailability(inOffsetSock,
+                            tex->musgrave_type != SHD_MUSGRAVE_MULTIFRACTAL &&
+                                tex->musgrave_type != SHD_MUSGRAVE_FBM);
+  nodeSetSocketAvailability(inGainSock,
+                            tex->musgrave_type == SHD_MUSGRAVE_HYBRID_MULTIFRACTAL &&
+                                tex->musgrave_type != SHD_MUSGRAVE_RIDGED_MULTIFRACTAL);
 }
 
-/* node type definition */
 void register_node_type_sh_tex_musgrave(void)
 {
   static bNodeType ntype;
@@ -95,6 +151,7 @@ void register_node_type_sh_tex_musgrave(void)
   node_type_storage(
       &ntype, "NodeTexMusgrave", node_free_standard_storage, node_copy_standard_storage);
   node_type_gpu(&ntype, node_shader_gpu_tex_musgrave);
+  node_type_update(&ntype, node_shader_update_tex_musgrave);
 
   nodeRegisterType(&ntype);
 }