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:
authorOmarSquircleArt <omar.squircleart@gmail.com>2019-09-09 22:06:55 +0300
committerOmarSquircleArt <omar.squircleart@gmail.com>2019-09-09 22:06:55 +0300
commitf2176b3ff3c5df9ab43d1b0489e3bb350d1015f6 (patch)
treef64f3e8453f4c54de37ecd625f6796b43bccd398 /intern/cycles/kernel/svm
parentc2d37929b4aaaef87bad1d2e90cc76d0c4765e8d (diff)
Shading: Extend Musgrave node to other dimensions.
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
Diffstat (limited to 'intern/cycles/kernel/svm')
-rw-r--r--intern/cycles/kernel/svm/svm.h2
-rw-r--r--intern/cycles/kernel/svm/svm_musgrave.h799
2 files changed, 698 insertions, 103 deletions
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