Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--intern/cycles/blender/blender_shader.cpp9
-rw-r--r--intern/cycles/kernel/shaders/node_musgrave_texture.osl742
-rw-r--r--intern/cycles/kernel/svm/svm.h2
-rw-r--r--intern/cycles/kernel/svm/svm_musgrave.h799
-rw-r--r--intern/cycles/render/nodes.cpp57
-rw-r--r--intern/cycles/render/nodes.h3
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenloader/intern/versioning_cycles.c46
-rw-r--r--source/blender/editors/space_node/drawnode.c1
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_tex_musgrave.glsl821
-rw-r--r--source/blender/makesdna/DNA_node_types.h2
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c85
13 files changed, 2272 insertions, 305 deletions
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 4d7d0910765..7e784527a21 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -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);
diff --git a/intern/cycles/kernel/shaders/node_musgrave_texture.osl b/intern/cycles/kernel/shaders/node_musgrave_texture.osl
index 0bf462e2103..8861f9a671a 100644
--- a/intern/cycles/kernel/shaders/node_musgrave_texture.osl
+++ b/intern/cycles/kernel/shaders/node_musgrave_texture.osl
@@ -16,8 +16,342 @@
#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
@@ -26,58 +360,56 @@
* 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;
+ }
}
diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h
index ce651a1b5ff..a192930937f 100644
--- a/intern/cycles/kernel/svm/svm.h
+++ b/intern/cycles/kernel/svm/svm.h
@@ -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);
diff --git a/intern/cycles/kernel/svm/svm_musgrave.h b/intern/cycles/kernel/svm/svm_musgrave.h
index db87f04581f..571f62fe27f 100644
--- a/intern/cycles/kernel/svm/svm_musgrave.h
+++ b/intern/cycles/kernel/svm/svm_musgrave.h
@@ -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
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 31dc986a4d1..01661a6d1e0 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -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");
}
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 769687f1f19..5d7e074f62b 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -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;
};
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index 24a48b2913b..b9ea85e7a00 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -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
diff --git a/source/blender/blenloader/intern/versioning_cycles.c b/source/blender/blenloader/intern/versioning_cycles.c
index d4d940daba5..98f8820e4ad 100644
--- a/source/blender/blenloader/intern/versioning_cycles.c
+++ b/source/blender/blenloader/intern/versioning_cycles.c
@@ -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;
+ }
}
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 23d452412ea..c707a1eed92 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -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);
}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_musgrave.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_musgrave.glsl
index 52332c45c3d..7ecca286acd 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_tex_musgrave.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_musgrave.glsl
@@ -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;
}
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 6d2b278472f..b4e12484bdc 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -885,7 +885,7 @@ typedef struct NodeTexVoronoi {
typedef struct NodeTexMusgrave {
NodeTexBase base;
int musgrave_type;
- char _pad[4];
+ int dimensions;
} NodeTexMusgrave;
typedef struct NodeTexWave {
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 0598f4807ec..a6481341868 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -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)
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
index 1a959b8faa8..daf4053f182 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
@@ -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);
}