From 729b2d026d1379de92908b16e7492a509721c796 Mon Sep 17 00:00:00 2001 From: Charlie Jolly Date: Mon, 18 Oct 2021 10:12:22 +0100 Subject: Geometry Nodes: Add shader Musgrave texture node Port shader node musgrave texture Differential Revision: https://developer.blender.org/D12701 --- source/blender/blenlib/BLI_noise.hh | 99 +++++ source/blender/blenlib/intern/noise.cc | 718 +++++++++++++++++++++++++++++++++ 2 files changed, 817 insertions(+) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_noise.hh b/source/blender/blenlib/BLI_noise.hh index 93980e3569e..a7af69f42a9 100644 --- a/source/blender/blenlib/BLI_noise.hh +++ b/source/blender/blenlib/BLI_noise.hh @@ -112,6 +112,105 @@ float3 perlin_float3_fractal_distorted(float4 position, /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Musgrave Multi Fractal + * \{ */ + +float musgrave_ridged_multi_fractal(const float co, + const float H, + const float lacunarity, + const float octaves, + const float offset, + const float gain); +float musgrave_ridged_multi_fractal(const float2 co, + const float H, + const float lacunarity, + const float octaves, + const float offset, + const float gain); +float musgrave_ridged_multi_fractal(const float3 co, + const float H, + const float lacunarity, + const float octaves, + const float offset, + const float gain); +float musgrave_ridged_multi_fractal(const float4 co, + const float H, + const float lacunarity, + const float octaves, + const float offset, + const float gain); + +float musgrave_hybrid_multi_fractal(const float co, + const float H, + const float lacunarity, + const float octaves, + const float offset, + const float gain); +float musgrave_hybrid_multi_fractal(const float2 co, + const float H, + const float lacunarity, + const float octaves, + const float offset, + const float gain); +float musgrave_hybrid_multi_fractal(const float3 co, + const float H, + const float lacunarity, + const float octaves, + const float offset, + const float gain); +float musgrave_hybrid_multi_fractal(const float4 co, + const float H, + const float lacunarity, + const float octaves, + const float offset, + const float gain); + +float musgrave_fBm(const float co, const float H, const float lacunarity, const float octaves); +float musgrave_fBm(const float2 co, const float H, const float lacunarity, const float octaves); +float musgrave_fBm(const float3 co, const float H, const float lacunarity, const float octaves); +float musgrave_fBm(const float4 co, const float H, const float lacunarity, const float octaves); + +float musgrave_multi_fractal(const float co, + const float H, + const float lacunarity, + const float octaves); +float musgrave_multi_fractal(const float2 co, + const float H, + const float lacunarity, + const float octaves); +float musgrave_multi_fractal(const float3 co, + const float H, + const float lacunarity, + const float octaves); +float musgrave_multi_fractal(const float4 co, + const float H, + const float lacunarity, + const float octaves); + +float musgrave_hetero_terrain(const float co, + const float H, + const float lacunarity, + const float octaves, + const float offset); +float musgrave_hetero_terrain(const float2 co, + const float H, + const float lacunarity, + const float octaves, + const float offset); +float musgrave_hetero_terrain(const float3 co, + const float H, + const float lacunarity, + const float octaves, + const float offset); +float musgrave_hetero_terrain(const float4 co, + const float H, + const float lacunarity, + const float octaves, + const float offset); + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Voronoi Noise * \{ */ diff --git a/source/blender/blenlib/intern/noise.cc b/source/blender/blenlib/intern/noise.cc index a6c3377b71f..812e6ddd181 100644 --- a/source/blender/blenlib/intern/noise.cc +++ b/source/blender/blenlib/intern/noise.cc @@ -756,6 +756,724 @@ float3 perlin_float3_fractal_distorted(float4 position, perlin_fractal(position + random_float4_offset(5.0f), octaves, roughness)); } +/* -------------- + * Musgrave Noise + * -------------- + */ + +/* 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 musgrave_fBm(const float co, const float H, const float lacunarity, const float octaves) +{ + float p = co; + float value = 0.0f; + float pwr = 1.0f; + const float pwHL = powf(lacunarity, -H); + + for (int i = 0; i < (int)octaves; i++) { + value += perlin_signed(p) * pwr; + pwr *= pwHL; + p *= lacunarity; + } + + float rmd = octaves - floorf(octaves); + if (rmd != 0.0f) { + value += rmd * perlin_signed(p) * pwr; + } + + return value; +} + +/* 1D Musgrave Multifractal + * + * H: highest fractal dimension + * lacunarity: gap between successive frequencies + * octaves: number of frequencies in the fBm + */ + +float musgrave_multi_fractal(const float co, + const float H, + const float lacunarity, + const float octaves) +{ + float p = co; + float value = 1.0f; + float pwr = 1.0f; + const float pwHL = powf(lacunarity, -H); + + for (int i = 0; i < (int)octaves; i++) { + value *= (pwr * perlin_signed(p) + 1.0f); + pwr *= pwHL; + p *= lacunarity; + } + + const float rmd = octaves - floorf(octaves); + if (rmd != 0.0f) { + value *= (rmd * pwr * perlin_signed(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' + */ + +float musgrave_hetero_terrain( + const float co, const float H, const float lacunarity, const float octaves, const float offset) +{ + float p = co; + const float pwHL = powf(lacunarity, -H); + float pwr = pwHL; + + /* first unscaled octave of function; later octaves are scaled */ + float value = offset + perlin_signed(p); + p *= lacunarity; + + for (int i = 1; i < (int)octaves; i++) { + float increment = (perlin_signed(p) + offset) * pwr * value; + value += increment; + pwr *= pwHL; + p *= lacunarity; + } + + const float rmd = octaves - floorf(octaves); + if (rmd != 0.0f) { + float increment = (perlin_signed(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 musgrave_hybrid_multi_fractal(const float co, + const float H, + const float lacunarity, + const float octaves, + const float offset, + const float gain) +{ + float p = co; + const float pwHL = powf(lacunarity, -H); + float pwr = pwHL; + + float value = perlin_signed(p) + offset; + float weight = gain * value; + p *= lacunarity; + + for (int i = 1; (weight > 0.001f) && (i < (int)octaves); i++) { + if (weight > 1.0f) { + weight = 1.0f; + } + + float signal = (perlin_signed(p) + offset) * pwr; + pwr *= pwHL; + value += weight * signal; + weight *= gain * signal; + p *= lacunarity; + } + + const float rmd = octaves - floorf(octaves); + if (rmd != 0.0f) { + value += rmd * ((perlin_signed(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 musgrave_ridged_multi_fractal(const float co, + const float H, + const float lacunarity, + const float octaves, + const float offset, + const float gain) +{ + float p = co; + const float pwHL = powf(lacunarity, -H); + float pwr = pwHL; + + float signal = offset - fabsf(perlin_signed(p)); + signal *= signal; + float value = signal; + float weight = 1.0f; + + for (int i = 1; i < (int)octaves; i++) { + p *= lacunarity; + weight = CLAMPIS(signal * gain, 0.0f, 1.0f); + signal = offset - fabsf(perlin_signed(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 musgrave_fBm(const float2 co, const float H, const float lacunarity, const float octaves) +{ + float2 p = co; + float value = 0.0f; + float pwr = 1.0f; + const float pwHL = powf(lacunarity, -H); + + for (int i = 0; i < (int)octaves; i++) { + value += perlin_signed(p) * pwr; + pwr *= pwHL; + p *= lacunarity; + } + + const float rmd = octaves - floorf(octaves); + if (rmd != 0.0f) { + value += rmd * perlin_signed(p) * pwr; + } + + return value; +} + +/* 2D Musgrave Multifractal + * + * H: highest fractal dimension + * lacunarity: gap between successive frequencies + * octaves: number of frequencies in the fBm + */ + +float musgrave_multi_fractal(const float2 co, + const float H, + const float lacunarity, + const float octaves) +{ + float2 p = co; + float value = 1.0f; + float pwr = 1.0f; + const float pwHL = powf(lacunarity, -H); + + for (int i = 0; i < (int)octaves; i++) { + value *= (pwr * perlin_signed(p) + 1.0f); + pwr *= pwHL; + p *= lacunarity; + } + + const float rmd = octaves - floorf(octaves); + if (rmd != 0.0f) { + value *= (rmd * pwr * perlin_signed(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' + */ + +float musgrave_hetero_terrain(const float2 co, + const float H, + const float lacunarity, + const float octaves, + const float offset) +{ + float2 p = co; + const float pwHL = powf(lacunarity, -H); + float pwr = pwHL; + + /* first unscaled octave of function; later octaves are scaled */ + float value = offset + perlin_signed(p); + p *= lacunarity; + + for (int i = 1; i < (int)octaves; i++) { + float increment = (perlin_signed(p) + offset) * pwr * value; + value += increment; + pwr *= pwHL; + p *= lacunarity; + } + + const float rmd = octaves - floorf(octaves); + if (rmd != 0.0f) { + float increment = (perlin_signed(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 musgrave_hybrid_multi_fractal(const float2 co, + const float H, + const float lacunarity, + const float octaves, + const float offset, + const float gain) +{ + float2 p = co; + const float pwHL = powf(lacunarity, -H); + float pwr = pwHL; + + float value = perlin_signed(p) + offset; + float weight = gain * value; + p *= lacunarity; + + for (int i = 1; (weight > 0.001f) && (i < (int)octaves); i++) { + if (weight > 1.0f) { + weight = 1.0f; + } + + float signal = (perlin_signed(p) + offset) * pwr; + pwr *= pwHL; + value += weight * signal; + weight *= gain * signal; + p *= lacunarity; + } + + const float rmd = octaves - floorf(octaves); + if (rmd != 0.0f) { + value += rmd * ((perlin_signed(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 musgrave_ridged_multi_fractal(const float2 co, + const float H, + const float lacunarity, + const float octaves, + const float offset, + const float gain) +{ + float2 p = co; + const float pwHL = powf(lacunarity, -H); + float pwr = pwHL; + + float signal = offset - fabsf(perlin_signed(p)); + signal *= signal; + float value = signal; + float weight = 1.0f; + + for (int i = 1; i < (int)octaves; i++) { + p *= lacunarity; + weight = CLAMPIS(signal * gain, 0.0f, 1.0f); + signal = offset - fabsf(perlin_signed(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" + */ + +float musgrave_fBm(const float3 co, const float H, const float lacunarity, const float octaves) +{ + float3 p = co; + float value = 0.0f; + float pwr = 1.0f; + const float pwHL = powf(lacunarity, -H); + + for (int i = 0; i < (int)octaves; i++) { + value += perlin_signed(p) * pwr; + pwr *= pwHL; + p *= lacunarity; + } + + const float rmd = octaves - floorf(octaves); + if (rmd != 0.0f) { + value += rmd * perlin_signed(p) * pwr; + } + + return value; +} + +/* 3D Musgrave Multifractal + * + * H: highest fractal dimension + * lacunarity: gap between successive frequencies + * octaves: number of frequencies in the fBm + */ + +float musgrave_multi_fractal(const float3 co, + const float H, + const float lacunarity, + const float octaves) +{ + float3 p = co; + float value = 1.0f; + float pwr = 1.0f; + const float pwHL = powf(lacunarity, -H); + + for (int i = 0; i < (int)octaves; i++) { + value *= (pwr * perlin_signed(p) + 1.0f); + pwr *= pwHL; + p *= lacunarity; + } + + const float rmd = octaves - floorf(octaves); + if (rmd != 0.0f) { + value *= (rmd * pwr * perlin_signed(p) + 1.0f); /* correct? */ + } + + return value; +} + +/* 3D 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 musgrave_hetero_terrain(const float3 co, + const float H, + const float lacunarity, + const float octaves, + const float offset) +{ + float3 p = co; + const float pwHL = powf(lacunarity, -H); + float pwr = pwHL; + + /* first unscaled octave of function; later octaves are scaled */ + float value = offset + perlin_signed(p); + p *= lacunarity; + + for (int i = 1; i < (int)octaves; i++) { + float increment = (perlin_signed(p) + offset) * pwr * value; + value += increment; + pwr *= pwHL; + p *= lacunarity; + } + + const float rmd = octaves - floorf(octaves); + if (rmd != 0.0f) { + float increment = (perlin_signed(p) + offset) * pwr * value; + value += rmd * increment; + } + + return value; +} + +/* 3D 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 musgrave_hybrid_multi_fractal(const float3 co, + const float H, + const float lacunarity, + const float octaves, + const float offset, + const float gain) +{ + float3 p = co; + const float pwHL = powf(lacunarity, -H); + float pwr = pwHL; + + float value = perlin_signed(p) + offset; + float weight = gain * value; + p *= lacunarity; + + for (int i = 1; (weight > 0.001f) && (i < (int)octaves); i++) { + if (weight > 1.0f) { + weight = 1.0f; + } + + float signal = (perlin_signed(p) + offset) * pwr; + pwr *= pwHL; + value += weight * signal; + weight *= gain * signal; + p *= lacunarity; + } + + const float rmd = octaves - floorf(octaves); + if (rmd != 0.0f) { + value += rmd * ((perlin_signed(p) + offset) * pwr); + } + + return value; +} + +/* 3D 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 musgrave_ridged_multi_fractal(const float3 co, + const float H, + const float lacunarity, + const float octaves, + const float offset, + const float gain) +{ + float3 p = co; + const float pwHL = powf(lacunarity, -H); + float pwr = pwHL; + + float signal = offset - fabsf(perlin_signed(p)); + signal *= signal; + float value = signal; + float weight = 1.0f; + + for (int i = 1; i < (int)octaves; i++) { + p *= lacunarity; + weight = CLAMPIS(signal * gain, 0.0f, 1.0f); + signal = offset - fabsf(perlin_signed(p)); + signal *= signal; + signal *= weight; + 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 musgrave_fBm(const float4 co, const float H, const float lacunarity, const float octaves) +{ + float4 p = co; + float value = 0.0f; + float pwr = 1.0f; + const float pwHL = powf(lacunarity, -H); + + for (int i = 0; i < (int)octaves; i++) { + value += perlin_signed(p) * pwr; + pwr *= pwHL; + p *= lacunarity; + } + + const float rmd = octaves - floorf(octaves); + if (rmd != 0.0f) { + value += rmd * perlin_signed(p) * pwr; + } + + return value; +} + +/* 4D Musgrave Multifractal + * + * H: highest fractal dimension + * lacunarity: gap between successive frequencies + * octaves: number of frequencies in the fBm + */ + +float musgrave_multi_fractal(const float4 co, + const float H, + const float lacunarity, + const float octaves) +{ + float4 p = co; + float value = 1.0f; + float pwr = 1.0f; + const float pwHL = powf(lacunarity, -H); + + for (int i = 0; i < (int)octaves; i++) { + value *= (pwr * perlin_signed(p) + 1.0f); + pwr *= pwHL; + p *= lacunarity; + } + + const float rmd = octaves - floorf(octaves); + if (rmd != 0.0f) { + value *= (rmd * pwr * perlin_signed(p) + 1.0f); /* 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 musgrave_hetero_terrain(const float4 co, + const float H, + const float lacunarity, + const float octaves, + const float offset) +{ + float4 p = co; + const float pwHL = powf(lacunarity, -H); + float pwr = pwHL; + + /* first unscaled octave of function; later octaves are scaled */ + float value = offset + perlin_signed(p); + p *= lacunarity; + + for (int i = 1; i < (int)octaves; i++) { + float increment = (perlin_signed(p) + offset) * pwr * value; + value += increment; + pwr *= pwHL; + p *= lacunarity; + } + + const float rmd = octaves - floorf(octaves); + if (rmd != 0.0f) { + float increment = (perlin_signed(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 musgrave_hybrid_multi_fractal(const float4 co, + const float H, + const float lacunarity, + const float octaves, + const float offset, + const float gain) +{ + float4 p = co; + const float pwHL = powf(lacunarity, -H); + float pwr = pwHL; + + float value = perlin_signed(p) + offset; + float weight = gain * value; + p *= lacunarity; + + for (int i = 1; (weight > 0.001f) && (i < (int)octaves); i++) { + if (weight > 1.0f) { + weight = 1.0f; + } + + float signal = (perlin_signed(p) + offset) * pwr; + pwr *= pwHL; + value += weight * signal; + weight *= gain * signal; + p *= lacunarity; + } + + const float rmd = octaves - floorf(octaves); + if (rmd != 0.0f) { + value += rmd * ((perlin_signed(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' + */ + +float musgrave_ridged_multi_fractal(const float4 co, + const float H, + const float lacunarity, + const float octaves, + const float offset, + const float gain) +{ + float4 p = co; + const float pwHL = powf(lacunarity, -H); + float pwr = pwHL; + + float signal = offset - fabsf(perlin_signed(p)); + signal *= signal; + float value = signal; + float weight = 1.0f; + + for (int i = 1; i < (int)octaves; i++) { + p *= lacunarity; + weight = CLAMPIS(signal * gain, 0.0f, 1.0f); + signal = offset - fabsf(perlin_signed(p)); + signal *= signal; + signal *= weight; + value += signal * pwr; + pwr *= pwHL; + } + + return value; +} + /* * Voronoi: Ported from Cycles code. * -- cgit v1.2.3