diff --git a/intern/cycles/blender/shader.cpp b/intern/cycles/blender/shader.cpp index 7c8c63299a5..8280a8d4554 100644 --- a/intern/cycles/blender/shader.cpp +++ b/intern/cycles/blender/shader.cpp @@ -936,20 +936,12 @@ static ShaderNode *add_node(Scene *scene, BL::ShaderNodeTexNoise b_noise_node(b_node); NoiseTextureNode *noise = graph->create_node(); noise->set_dimensions(b_noise_node.noise_dimensions()); + noise->set_type((NodeNoiseType)b_noise_node.type()); noise->set_use_normalize(b_noise_node.normalize()); BL::TexMapping b_texture_mapping(b_noise_node.texture_mapping()); get_tex_mapping(noise, b_texture_mapping); node = noise; } - else if (b_node.is_a(&RNA_ShaderNodeTexMusgrave)) { - BL::ShaderNodeTexMusgrave b_musgrave_node(b_node); - MusgraveTextureNode *musgrave_node = graph->create_node(); - musgrave_node->set_musgrave_type((NodeMusgraveType)b_musgrave_node.musgrave_type()); - musgrave_node->set_dimensions(b_musgrave_node.musgrave_dimensions()); - BL::TexMapping b_texture_mapping(b_musgrave_node.texture_mapping()); - get_tex_mapping(musgrave_node, b_texture_mapping); - node = musgrave_node; - } else if (b_node.is_a(&RNA_ShaderNodeTexCoord)) { BL::ShaderNodeTexCoord b_tex_coord_node(b_node); TextureCoordinateNode *tex_coord = graph->create_node(); diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 5a2c3efaba6..22db2454920 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -178,7 +178,6 @@ set(SRC_KERNEL_SVM_HEADERS svm/math.h svm/math_util.h svm/mix.h - svm/musgrave.h svm/node_types_template.h svm/noise.h svm/noisetex.h diff --git a/intern/cycles/kernel/osl/shaders/CMakeLists.txt b/intern/cycles/kernel/osl/shaders/CMakeLists.txt index 766277d248c..3f2c2fc294f 100644 --- a/intern/cycles/kernel/osl/shaders/CMakeLists.txt +++ b/intern/cycles/kernel/osl/shaders/CMakeLists.txt @@ -61,7 +61,6 @@ set(SRC_OSL node_mix_float.osl node_mix_vector.osl node_mix_vector_non_uniform.osl - node_musgrave_texture.osl node_noise_texture.osl node_normal.osl node_normal_map.osl diff --git a/intern/cycles/kernel/osl/shaders/node_musgrave_texture.osl b/intern/cycles/kernel/osl/shaders/node_musgrave_texture.osl deleted file mode 100644 index b50d7c42b60..00000000000 --- a/intern/cycles/kernel/osl/shaders/node_musgrave_texture.osl +++ /dev/null @@ -1,803 +0,0 @@ -/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation - * - * SPDX-License-Identifier: Apache-2.0 */ - -#include "node_noise.h" -#include "stdcycles.h" -#include "vector2.h" -#include "vector4.h" - -#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 = 1.0; - float value = 0.0; - float weight = 1.0; - - for (int i = 0; (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) && (weight > 0.001)) { - if (weight > 1.0) { - weight = 1.0; - } - float signal = (safe_snoise(p) + offset) * pwr; - value += rmd * weight * signal; - } - - 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 = 1.0; - float value = 0.0; - float weight = 1.0; - - for (int i = 0; (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) && (weight > 0.001)) { - if (weight > 1.0) { - weight = 1.0; - } - float signal = (safe_snoise(p) + offset) * pwr; - value += rmd * weight * signal; - } - - 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 - * octaves: number of frequencies in the fBm - * - * from "Texturing and Modelling: A procedural approach" - */ - -float noise_musgrave_fBm_3d(vector3 co, float H, float lacunarity, float octaves) -{ - vector3 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; -} - -/* 3D Musgrave Multifractal - * - * H: highest fractal dimension - * lacunarity: gap between successive frequencies - * octaves: number of frequencies in the fBm - */ - -float noise_musgrave_multi_fractal_3d(vector3 co, float H, float lacunarity, float octaves) -{ - vector3 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; -} - -/* 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 noise_musgrave_hetero_terrain_3d( - vector3 co, float H, float lacunarity, float octaves, float offset) -{ - vector3 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; -} - -/* 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 noise_musgrave_hybrid_multi_fractal_3d( - vector3 co, float H, float lacunarity, float octaves, float offset, float gain) -{ - vector3 p = co; - float pwHL = pow(lacunarity, -H); - - float pwr = 1.0; - float value = 0.0; - float weight = 1.0; - - for (int i = 0; (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) && (weight > 0.001)) { - if (weight > 1.0) { - weight = 1.0; - } - float signal = (safe_snoise(p) + offset) * pwr; - value += rmd * weight * signal; - } - - 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 noise_musgrave_ridged_multi_fractal_3d( - vector3 co, float H, float lacunarity, float octaves, float offset, float gain) -{ - vector3 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; -} - -/* 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 = 1.0; - float value = 0.0; - float weight = 1.0; - - for (int i = 0; (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) && (weight > 0.001)) { - if (weight > 1.0) { - weight = 1.0; - } - float signal = (safe_snoise(p) + offset) * pwr; - value += rmd * weight * signal; - } - - 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 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 musgrave_type = "fBM", - string dimensions = "3D", - point Vector = P, - float W = 0.0, - float Dimension = 2.0, - float Scale = 5.0, - float Detail = 2.0, - float Lacunarity = 2.0, - float Offset = 0.0, - float Gain = 1.0, - output float Fac = 0.0) -{ - float dimension = max(Dimension, 1e-5); - float octaves = clamp(Detail, 0.0, 15.0); - float lacunarity = max(Lacunarity, 1e-5); - - vector3 s = Vector; - - if (use_mapping) - s = transform(mapping, s); - - if (dimensions == "1D") { - float p = W * Scale; - if (musgrave_type == "multifractal") { - Fac = noise_musgrave_multi_fractal_1d(p, dimension, lacunarity, octaves); - } - else if (musgrave_type == "fBM") { - Fac = noise_musgrave_fBm_1d(p, dimension, lacunarity, octaves); - } - else if (musgrave_type == "hybrid_multifractal") { - Fac = noise_musgrave_hybrid_multi_fractal_1d( - p, dimension, lacunarity, octaves, Offset, Gain); - } - else if (musgrave_type == "ridged_multifractal") { - Fac = noise_musgrave_ridged_multi_fractal_1d( - p, dimension, lacunarity, octaves, Offset, Gain); - } - else if (musgrave_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 (musgrave_type == "multifractal") { - Fac = noise_musgrave_multi_fractal_2d(p, dimension, lacunarity, octaves); - } - else if (musgrave_type == "fBM") { - Fac = noise_musgrave_fBm_2d(p, dimension, lacunarity, octaves); - } - else if (musgrave_type == "hybrid_multifractal") { - Fac = noise_musgrave_hybrid_multi_fractal_2d( - p, dimension, lacunarity, octaves, Offset, Gain); - } - else if (musgrave_type == "ridged_multifractal") { - Fac = noise_musgrave_ridged_multi_fractal_2d( - p, dimension, lacunarity, octaves, Offset, Gain); - } - else if (musgrave_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 (musgrave_type == "multifractal") { - Fac = noise_musgrave_multi_fractal_3d(p, dimension, lacunarity, octaves); - } - else if (musgrave_type == "fBM") { - Fac = noise_musgrave_fBm_3d(p, dimension, lacunarity, octaves); - } - else if (musgrave_type == "hybrid_multifractal") { - Fac = noise_musgrave_hybrid_multi_fractal_3d( - p, dimension, lacunarity, octaves, Offset, Gain); - } - else if (musgrave_type == "ridged_multifractal") { - Fac = noise_musgrave_ridged_multi_fractal_3d( - p, dimension, lacunarity, octaves, Offset, Gain); - } - else if (musgrave_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 (musgrave_type == "multifractal") { - Fac = noise_musgrave_multi_fractal_4d(p, dimension, lacunarity, octaves); - } - else if (musgrave_type == "fBM") { - Fac = noise_musgrave_fBm_4d(p, dimension, lacunarity, octaves); - } - else if (musgrave_type == "hybrid_multifractal") { - Fac = noise_musgrave_hybrid_multi_fractal_4d( - p, dimension, lacunarity, octaves, Offset, Gain); - } - else if (musgrave_type == "ridged_multifractal") { - Fac = noise_musgrave_ridged_multi_fractal_4d( - p, dimension, lacunarity, octaves, Offset, Gain); - } - else if (musgrave_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/osl/shaders/node_noise.h b/intern/cycles/kernel/osl/shaders/node_noise.h index 2ae8689a8e9..096e7ff75c6 100644 --- a/intern/cycles/kernel/osl/shaders/node_noise.h +++ b/intern/cycles/kernel/osl/shaders/node_noise.h @@ -79,116 +79,173 @@ float safe_snoise(vector4 p) return f; } -/* The fractal_noise functions are all exactly the same except for the input type. */ -float fractal_noise(float p, float details, float roughness, float lacunarity, int use_normalize) -{ - float fscale = 1.0; - float amp = 1.0; - float maxamp = 0.0; - float sum = 0.0; - float octaves = clamp(details, 0.0, 15.0); - int n = (int)octaves; - for (int i = 0; i <= n; i++) { - float t = safe_snoise(fscale * p); - sum += t * amp; - maxamp += amp; - amp *= clamp(roughness, 0.0, 1.0); - fscale *= lacunarity; +#define NOISE_FBM(T) \ + float noise_fbm(T co, float detail, float roughness, float lacunarity, int use_normalize) \ + { \ + T p = co; \ + float fscale = 1.0; \ + float amp = 1.0; \ + float maxamp = 0.0; \ + float sum = 0.0; \ +\ + for (int i = 0; i <= int(detail); i++) { \ + float t = safe_snoise(fscale * p); \ + sum += t * amp; \ + maxamp += amp; \ + amp *= roughness; \ + fscale *= lacunarity; \ + } \ + float rmd = detail - floor(detail); \ + if (rmd != 0.0) { \ + float t = safe_snoise(fscale * p); \ + float sum2 = sum + t * amp; \ + return use_normalize ? \ + mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) : \ + mix(sum, sum2, rmd); \ + } \ + else { \ + return use_normalize ? 0.5 * sum / maxamp + 0.5 : sum; \ + } \ } - float rmd = octaves - floor(octaves); - if (rmd != 0.0) { - float t = safe_snoise(fscale * p); - float sum2 = sum + t * amp; - return use_normalize ? mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) : - mix(sum, sum2, rmd); - } - else { - return use_normalize ? 0.5 * sum / maxamp + 0.5 : sum; - } -} -/* The fractal_noise functions are all exactly the same except for the input type. */ -float fractal_noise(vector2 p, float details, float roughness, float lacunarity, int use_normalize) -{ - float fscale = 1.0; - float amp = 1.0; - float maxamp = 0.0; - float sum = 0.0; - float octaves = clamp(details, 0.0, 15.0); - int n = (int)octaves; - for (int i = 0; i <= n; i++) { - float t = safe_snoise(fscale * p); - sum += t * amp; - maxamp += amp; - amp *= clamp(roughness, 0.0, 1.0); - fscale *= lacunarity; +#define NOISE_MULTI_FRACTAL(T) \ + float noise_multi_fractal(T co, float detail, float roughness, float lacunarity) \ + { \ + T p = co; \ + float value = 1.0; \ + float pwr = 1.0; \ +\ + for (int i = 0; i <= (int)detail; i++) { \ + value *= (pwr * safe_snoise(p) + 1.0); \ + pwr *= roughness; \ + p *= lacunarity; \ + } \ +\ + float rmd = detail - floor(detail); \ + if (rmd != 0.0) { \ + value *= (rmd * pwr * safe_snoise(p) + 1.0); /* correct? */ \ + } \ +\ + return value; \ } - float rmd = octaves - floor(octaves); - if (rmd != 0.0) { - float t = safe_snoise(fscale * p); - float sum2 = sum + t * amp; - return use_normalize ? mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) : - mix(sum, sum2, rmd); - } - else { - return use_normalize ? 0.5 * sum / maxamp + 0.5 : sum; - } -} -/* The fractal_noise functions are all exactly the same except for the input type. */ -float fractal_noise(vector3 p, float details, float roughness, float lacunarity, int use_normalize) -{ - float fscale = 1.0; - float amp = 1.0; - float maxamp = 0.0; - float sum = 0.0; - float octaves = clamp(details, 0.0, 15.0); - int n = (int)octaves; - for (int i = 0; i <= n; i++) { - float t = safe_snoise(fscale * p); - sum += t * amp; - maxamp += amp; - amp *= clamp(roughness, 0.0, 1.0); - fscale *= lacunarity; +#define NOISE_HETERO_TERRAIN(T) \ + float noise_hetero_terrain(T co, float detail, float roughness, float lacunarity, float offset) \ + { \ + T p = co; \ + float pwr = roughness; \ +\ + /* first unscaled octave of function; later octaves are scaled */ \ + float value = offset + safe_snoise(p); \ + p *= lacunarity; \ +\ + for (int i = 1; i <= (int)detail; i++) { \ + float increment = (safe_snoise(p) + offset) * pwr * value; \ + value += increment; \ + pwr *= roughness; \ + p *= lacunarity; \ + } \ +\ + float rmd = detail - floor(detail); \ + if (rmd != 0.0) { \ + float increment = (safe_snoise(p) + offset) * pwr * value; \ + value += rmd * increment; \ + } \ +\ + return value; \ } - float rmd = octaves - floor(octaves); - if (rmd != 0.0) { - float t = safe_snoise(fscale * p); - float sum2 = sum + t * amp; - return use_normalize ? mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) : - mix(sum, sum2, rmd); - } - else { - return use_normalize ? 0.5 * sum / maxamp + 0.5 : sum; - } -} -/* The fractal_noise functions are all exactly the same except for the input type. */ -float fractal_noise(vector4 p, float details, float roughness, float lacunarity, int use_normalize) -{ - float fscale = 1.0; - float amp = 1.0; - float maxamp = 0.0; - float sum = 0.0; - float octaves = clamp(details, 0.0, 15.0); - int n = (int)octaves; - for (int i = 0; i <= n; i++) { - float t = safe_snoise(fscale * p); - sum += t * amp; - maxamp += amp; - amp *= clamp(roughness, 0.0, 1.0); - fscale *= lacunarity; +#define NOISE_HYBRID_MULTI_FRACTAL(T) \ + float noise_hybrid_multi_fractal( \ + T co, float detail, float roughness, float lacunarity, float offset, float gain) \ + { \ + T p = co; \ + float pwr = 1.0; \ + float value = 0.0; \ + float weight = 1.0; \ +\ + for (int i = 0; (weight > 0.001) && (i <= (int)detail); i++) { \ + if (weight > 1.0) { \ + weight = 1.0; \ + } \ +\ + float signal = (safe_snoise(p) + offset) * pwr; \ + pwr *= roughness; \ + value += weight * signal; \ + weight *= gain * signal; \ + p *= lacunarity; \ + } \ +\ + float rmd = detail - floor(detail); \ + if ((rmd != 0.0) && (weight > 0.001)) { \ + if (weight > 1.0) { \ + weight = 1.0; \ + } \ + float signal = (safe_snoise(p) + offset) * pwr; \ + value += rmd * weight * signal; \ + } \ +\ + return value; \ } - float rmd = octaves - floor(octaves); - if (rmd != 0.0) { - float t = safe_snoise(fscale * p); - float sum2 = sum + t * amp; - return use_normalize ? mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) : - mix(sum, sum2, rmd); + +#define NOISE_RIDGED_MULTI_FRACTAL(T) \ + float noise_ridged_multi_fractal( \ + T co, float detail, float roughness, float lacunarity, float offset, float gain) \ + { \ + T p = co; \ + float pwr = roughness; \ +\ + float signal = offset - fabs(safe_snoise(p)); \ + signal *= signal; \ + float value = signal; \ + float weight = 1.0; \ +\ + for (int i = 1; i <= (int)detail; 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 *= roughness; \ + } \ +\ + return value; \ } - else { - return use_normalize ? 0.5 * sum / maxamp + 0.5 : sum; - } -} + +/* Noise fBM */ + +NOISE_FBM(float) +NOISE_FBM(vector2) +NOISE_FBM(vector3) +NOISE_FBM(vector4) + +/* Noise Multifractal */ + +NOISE_MULTI_FRACTAL(float) +NOISE_MULTI_FRACTAL(vector2) +NOISE_MULTI_FRACTAL(vector3) +NOISE_MULTI_FRACTAL(vector4) + +/* Noise Hetero Terrain */ + +NOISE_HETERO_TERRAIN(float) +NOISE_HETERO_TERRAIN(vector2) +NOISE_HETERO_TERRAIN(vector3) +NOISE_HETERO_TERRAIN(vector4) + +/* Noise Hybrid Multifractal */ + +NOISE_HYBRID_MULTI_FRACTAL(float) +NOISE_HYBRID_MULTI_FRACTAL(vector2) +NOISE_HYBRID_MULTI_FRACTAL(vector3) +NOISE_HYBRID_MULTI_FRACTAL(vector4) + +/* Noise Ridged Multifractal */ + +NOISE_RIDGED_MULTI_FRACTAL(float) +NOISE_RIDGED_MULTI_FRACTAL(vector2) +NOISE_RIDGED_MULTI_FRACTAL(vector3) +NOISE_RIDGED_MULTI_FRACTAL(vector4) #undef vector3 diff --git a/intern/cycles/kernel/osl/shaders/node_noise_texture.osl b/intern/cycles/kernel/osl/shaders/node_noise_texture.osl index 72ad7ed3de3..7cbd583fb2e 100644 --- a/intern/cycles/kernel/osl/shaders/node_noise_texture.osl +++ b/intern/cycles/kernel/osl/shaders/node_noise_texture.osl @@ -9,6 +9,37 @@ #define vector3 point +#define NOISE_SELECT(T) \ + float noise_select(T p, \ + float detail, \ + float roughness, \ + float lacunarity, \ + float offset, \ + float gain, \ + string type, \ + int use_normalize) \ + { \ + if (type == "multifractal") { \ + return noise_multi_fractal(p, detail, roughness, lacunarity); \ + } \ + else if (type == "fBM") { \ + return noise_fbm(p, detail, roughness, lacunarity, use_normalize); \ + } \ + else if (type == "hybrid_multifractal") { \ + return noise_hybrid_multi_fractal(p, detail, roughness, lacunarity, offset, gain); \ + } \ + else if (type == "ridged_multifractal") { \ + return noise_ridged_multi_fractal(p, detail, roughness, lacunarity, offset, gain); \ + } \ + else if (type == "hetero_terrain") { \ + return noise_hetero_terrain(p, detail, roughness, lacunarity, offset); \ + } \ + else { \ + error("Unknown Type!"); \ + return 0.0; \ + } \ + } + /* The following offset functions generate random offsets to be added to texture * coordinates to act as a seed since the noise functions don't have seed values. * A seed value is needed for generating distortion textures and color outputs. @@ -43,11 +74,21 @@ vector4 random_vector4_offset(float seed) 100.0 + noise("hash", seed, 3.0) * 100.0); } +/* Noise Select */ + +NOISE_SELECT(float) +NOISE_SELECT(vector2) +NOISE_SELECT(vector3) +NOISE_SELECT(vector4) + float noise_texture(float co, float detail, float roughness, float lacunarity, + float offset, + float gain, float distortion, + string type, int use_normalize, output color Color) { @@ -56,11 +97,24 @@ float noise_texture(float co, p += safe_snoise(p + random_float_offset(0.0)) * distortion; } - float value = fractal_noise(p, detail, roughness, lacunarity, use_normalize); - Color = color( - value, - fractal_noise(p + random_float_offset(1.0), detail, roughness, lacunarity, use_normalize), - fractal_noise(p + random_float_offset(2.0), detail, roughness, lacunarity, use_normalize)); + float value = noise_select(p, detail, roughness, lacunarity, offset, gain, type, use_normalize); + Color = color(value, + noise_select(p + random_float_offset(1.0), + detail, + roughness, + lacunarity, + offset, + gain, + type, + use_normalize), + noise_select(p + random_float_offset(2.0), + detail, + roughness, + lacunarity, + offset, + gain, + type, + use_normalize)); return value; } @@ -68,7 +122,10 @@ float noise_texture(vector2 co, float detail, float roughness, float lacunarity, + float offset, + float gain, float distortion, + string type, int use_normalize, output color Color) { @@ -78,11 +135,24 @@ float noise_texture(vector2 co, safe_snoise(p + random_vector2_offset(1.0)) * distortion); } - float value = fractal_noise(p, detail, roughness, lacunarity, use_normalize); - Color = color( - value, - fractal_noise(p + random_vector2_offset(2.0), detail, roughness, lacunarity, use_normalize), - fractal_noise(p + random_vector2_offset(3.0), detail, roughness, lacunarity, use_normalize)); + float value = noise_select(p, detail, roughness, lacunarity, offset, gain, type, use_normalize); + Color = color(value, + noise_select(p + random_vector2_offset(2.0), + detail, + roughness, + lacunarity, + offset, + gain, + type, + use_normalize), + noise_select(p + random_vector2_offset(3.0), + detail, + roughness, + lacunarity, + offset, + gain, + type, + use_normalize)); return value; } @@ -90,7 +160,10 @@ float noise_texture(vector3 co, float detail, float roughness, float lacunarity, + float offset, + float gain, float distortion, + string type, int use_normalize, output color Color) { @@ -101,11 +174,24 @@ float noise_texture(vector3 co, safe_snoise(p + random_vector3_offset(2.0)) * distortion); } - float value = fractal_noise(p, detail, roughness, lacunarity, use_normalize); - Color = color( - value, - fractal_noise(p + random_vector3_offset(3.0), detail, roughness, lacunarity, use_normalize), - fractal_noise(p + random_vector3_offset(4.0), detail, roughness, lacunarity, use_normalize)); + float value = noise_select(p, detail, roughness, lacunarity, offset, gain, type, use_normalize); + Color = color(value, + noise_select(p + random_vector3_offset(3.0), + detail, + roughness, + lacunarity, + offset, + gain, + type, + use_normalize), + noise_select(p + random_vector3_offset(4.0), + detail, + roughness, + lacunarity, + offset, + gain, + type, + use_normalize)); return value; } @@ -113,7 +199,10 @@ float noise_texture(vector4 co, float detail, float roughness, float lacunarity, + float offset, + float gain, float distortion, + string type, int use_normalize, output color Color) { @@ -125,23 +214,39 @@ float noise_texture(vector4 co, safe_snoise(p + random_vector4_offset(3.0)) * distortion); } - float value = fractal_noise(p, detail, roughness, lacunarity, use_normalize); - Color = color( - value, - fractal_noise(p + random_vector4_offset(4.0), detail, roughness, lacunarity, use_normalize), - fractal_noise(p + random_vector4_offset(5.0), detail, roughness, lacunarity, use_normalize)); + float value = noise_select(p, detail, roughness, lacunarity, offset, gain, type, use_normalize); + Color = color(value, + noise_select(p + random_vector4_offset(4.0), + detail, + roughness, + lacunarity, + offset, + gain, + type, + use_normalize), + noise_select(p + random_vector4_offset(5.0), + detail, + roughness, + lacunarity, + offset, + gain, + type, + use_normalize)); return value; } shader node_noise_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 dimensions = "3D", - int use_normalize = 0, + string type = "fBM", + int use_normalize = 1, vector3 Vector = vector3(0, 0, 0), float W = 0.0, float Scale = 5.0, float Detail = 2.0, float Roughness = 0.5, + float Offset = 0.0, + float Gain = 1.0, float Lacunarity = 2.0, float Distortion = 0.0, output float Fac = 0.0, @@ -151,24 +256,45 @@ shader node_noise_texture(int use_mapping = 0, if (use_mapping) p = transform(mapping, p); + float detail = clamp(Detail, 0.0, 15.0); + float roughness = max(Roughness, 0.0); + p *= Scale; float w = W * Scale; - if (dimensions == "1D") - Fac = noise_texture(w, Detail, Roughness, Lacunarity, Distortion, use_normalize, Color); - else if (dimensions == "2D") + if (dimensions == "1D") { Fac = noise_texture( - vector2(p[0], p[1]), Detail, Roughness, Lacunarity, Distortion, use_normalize, Color); - else if (dimensions == "3D") - Fac = noise_texture(p, Detail, Roughness, Lacunarity, Distortion, use_normalize, Color); - else if (dimensions == "4D") - Fac = noise_texture(vector4(p[0], p[1], p[2], w), - Detail, - Roughness, + w, detail, roughness, Lacunarity, Offset, Gain, Distortion, type, use_normalize, Color); + } + else if (dimensions == "2D") { + Fac = noise_texture(vector2(p[0], p[1]), + detail, + roughness, Lacunarity, + Offset, + Gain, Distortion, + type, use_normalize, Color); - else - error("Unknown dimension!"); + } + else if (dimensions == "3D") { + Fac = noise_texture( + p, detail, roughness, Lacunarity, Offset, Gain, Distortion, type, use_normalize, Color); + } + else if (dimensions == "4D") { + Fac = noise_texture(vector4(p[0], p[1], p[2], w), + detail, + roughness, + Lacunarity, + Offset, + Gain, + Distortion, + type, + use_normalize, + Color); + } + else { + error("Unknown Dimension!"); + } } diff --git a/intern/cycles/kernel/osl/shaders/node_wave_texture.osl b/intern/cycles/kernel/osl/shaders/node_wave_texture.osl index 67c4bf3e6c2..27f822ce5ef 100644 --- a/intern/cycles/kernel/osl/shaders/node_wave_texture.osl +++ b/intern/cycles/kernel/osl/shaders/node_wave_texture.osl @@ -56,7 +56,7 @@ float wave(point p_input, n += phase; if (distortion != 0.0) { - n = n + (distortion * (fractal_noise(p * dscale, detail, droughness, 2.0, 1) * 2.0 - 1.0)); + n = n + (distortion * (noise_fbm(p * dscale, detail, droughness, 2.0, 1) * 2.0 - 1.0)); } if (profile == "sine") { diff --git a/intern/cycles/kernel/svm/fractal_noise.h b/intern/cycles/kernel/svm/fractal_noise.h index 63e6a808c6b..956ae74af08 100644 --- a/intern/cycles/kernel/svm/fractal_noise.h +++ b/intern/cycles/kernel/svm/fractal_noise.h @@ -8,24 +8,24 @@ CCL_NAMESPACE_BEGIN -/* The fractal_noise_[1-4] functions are all exactly the same except for the input type. */ -ccl_device_noinline float fractal_noise_1d( - float p, float octaves, float roughness, float lacunarity, bool normalize) +/* Fractal Brownian motion*/ + +ccl_device_noinline float noise_fbm( + float p, float detail, float roughness, float lacunarity, bool normalize) { float fscale = 1.0f; float amp = 1.0f; float maxamp = 0.0f; float sum = 0.0f; - octaves = clamp(octaves, 0.0f, 15.0f); - int n = float_to_int(octaves); - for (int i = 0; i <= n; i++) { + + for (int i = 0; i <= float_to_int(detail); i++) { float t = snoise_1d(fscale * p); sum += t * amp; maxamp += amp; - amp *= clamp(roughness, 0.0f, 1.0f); + amp *= roughness; fscale *= lacunarity; } - float rmd = octaves - floorf(octaves); + float rmd = detail - floorf(detail); if (rmd != 0.0f) { float t = snoise_1d(fscale * p); float sum2 = sum + t * amp; @@ -37,24 +37,22 @@ ccl_device_noinline float fractal_noise_1d( } } -/* The fractal_noise_[1-4] functions are all exactly the same except for the input type. */ -ccl_device_noinline float fractal_noise_2d( - float2 p, float octaves, float roughness, float lacunarity, bool normalize) +ccl_device_noinline float noise_fbm( + float2 p, float detail, float roughness, float lacunarity, bool normalize) { float fscale = 1.0f; float amp = 1.0f; float maxamp = 0.0f; float sum = 0.0f; - octaves = clamp(octaves, 0.0f, 15.0f); - int n = float_to_int(octaves); - for (int i = 0; i <= n; i++) { + + for (int i = 0; i <= float_to_int(detail); i++) { float t = snoise_2d(fscale * p); sum += t * amp; maxamp += amp; - amp *= clamp(roughness, 0.0f, 1.0f); + amp *= roughness; fscale *= lacunarity; } - float rmd = octaves - floorf(octaves); + float rmd = detail - floorf(detail); if (rmd != 0.0f) { float t = snoise_2d(fscale * p); float sum2 = sum + t * amp; @@ -66,24 +64,22 @@ ccl_device_noinline float fractal_noise_2d( } } -/* The fractal_noise_[1-4] functions are all exactly the same except for the input type. */ -ccl_device_noinline float fractal_noise_3d( - float3 p, float octaves, float roughness, float lacunarity, bool normalize) +ccl_device_noinline float noise_fbm( + float3 p, float detail, float roughness, float lacunarity, bool normalize) { float fscale = 1.0f; float amp = 1.0f; float maxamp = 0.0f; float sum = 0.0f; - octaves = clamp(octaves, 0.0f, 15.0f); - int n = float_to_int(octaves); - for (int i = 0; i <= n; i++) { + + for (int i = 0; i <= float_to_int(detail); i++) { float t = snoise_3d(fscale * p); sum += t * amp; maxamp += amp; - amp *= clamp(roughness, 0.0f, 1.0f); + amp *= roughness; fscale *= lacunarity; } - float rmd = octaves - floorf(octaves); + float rmd = detail - floorf(detail); if (rmd != 0.0f) { float t = snoise_3d(fscale * p); float sum2 = sum + t * amp; @@ -95,24 +91,22 @@ ccl_device_noinline float fractal_noise_3d( } } -/* The fractal_noise_[1-4] functions are all exactly the same except for the input type. */ -ccl_device_noinline float fractal_noise_4d( - float4 p, float octaves, float roughness, float lacunarity, bool normalize) +ccl_device_noinline float noise_fbm( + float4 p, float detail, float roughness, float lacunarity, bool normalize) { float fscale = 1.0f; float amp = 1.0f; float maxamp = 0.0f; float sum = 0.0f; - octaves = clamp(octaves, 0.0f, 15.0f); - int n = float_to_int(octaves); - for (int i = 0; i <= n; i++) { + + for (int i = 0; i <= float_to_int(detail); i++) { float t = snoise_4d(fscale * p); sum += t * amp; maxamp += amp; - amp *= clamp(roughness, 0.0f, 1.0f); + amp *= roughness; fscale *= lacunarity; } - float rmd = octaves - floorf(octaves); + float rmd = detail - floorf(detail); if (rmd != 0.0f) { float t = snoise_4d(fscale * p); float sum2 = sum + t * amp; @@ -124,4 +118,416 @@ ccl_device_noinline float fractal_noise_4d( } } +/* Multifractal */ + +ccl_device_noinline float noise_multi_fractal(float p, + float detail, + float roughness, + float lacunarity) +{ + float value = 1.0f; + float pwr = 1.0f; + + for (int i = 0; i <= float_to_int(detail); i++) { + value *= (pwr * snoise_1d(p) + 1.0f); + pwr *= roughness; + p *= lacunarity; + } + + float rmd = detail - floorf(detail); + if (rmd != 0.0f) { + value *= (rmd * pwr * snoise_1d(p) + 1.0f); /* correct? */ + } + + return value; +} + +ccl_device_noinline float noise_multi_fractal(float2 p, + float detail, + float roughness, + float lacunarity) +{ + float value = 1.0f; + float pwr = 1.0f; + + for (int i = 0; i <= float_to_int(detail); i++) { + value *= (pwr * snoise_2d(p) + 1.0f); + pwr *= roughness; + p *= lacunarity; + } + + float rmd = detail - floorf(detail); + if (rmd != 0.0f) { + value *= (rmd * pwr * snoise_2d(p) + 1.0f); /* correct? */ + } + + return value; +} + +ccl_device_noinline float noise_multi_fractal(float3 p, + float detail, + float roughness, + float lacunarity) +{ + float value = 1.0f; + float pwr = 1.0f; + + for (int i = 0; i <= float_to_int(detail); i++) { + value *= (pwr * snoise_3d(p) + 1.0f); + pwr *= roughness; + p *= lacunarity; + } + + float rmd = detail - floorf(detail); + if (rmd != 0.0f) { + value *= (rmd * pwr * snoise_3d(p) + 1.0f); /* correct? */ + } + + return value; +} + +ccl_device_noinline float noise_multi_fractal(float4 p, + float detail, + float roughness, + float lacunarity) +{ + float value = 1.0f; + float pwr = 1.0f; + + for (int i = 0; i <= float_to_int(detail); i++) { + value *= (pwr * snoise_4d(p) + 1.0f); + pwr *= roughness; + p *= lacunarity; + } + + float rmd = detail - floorf(detail); + if (rmd != 0.0f) { + value *= (rmd * pwr * snoise_4d(p) + 1.0f); /* correct? */ + } + + return value; +} + +/* Heterogeneous Terrain */ + +ccl_device_noinline float noise_hetero_terrain( + float p, float detail, float roughness, float lacunarity, float offset) +{ + float pwr = roughness; + + /* 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(detail); i++) { + float increment = (snoise_1d(p) + offset) * pwr * value; + value += increment; + pwr *= roughness; + p *= lacunarity; + } + + float rmd = detail - floorf(detail); + if (rmd != 0.0f) { + float increment = (snoise_1d(p) + offset) * pwr * value; + value += rmd * increment; + } + + return value; +} + +ccl_device_noinline float noise_hetero_terrain( + float2 p, float detail, float roughness, float lacunarity, float offset) +{ + float pwr = roughness; + + /* 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(detail); i++) { + float increment = (snoise_2d(p) + offset) * pwr * value; + value += increment; + pwr *= roughness; + p *= lacunarity; + } + + float rmd = detail - floorf(detail); + if (rmd != 0.0f) { + float increment = (snoise_2d(p) + offset) * pwr * value; + value += rmd * increment; + } + + return value; +} + +ccl_device_noinline float noise_hetero_terrain( + float3 p, float detail, float roughness, float lacunarity, float offset) +{ + float pwr = roughness; + + /* first unscaled octave of function; later octaves are scaled */ + float value = offset + snoise_3d(p); + p *= lacunarity; + + for (int i = 1; i <= float_to_int(detail); i++) { + float increment = (snoise_3d(p) + offset) * pwr * value; + value += increment; + pwr *= roughness; + p *= lacunarity; + } + + float rmd = detail - floorf(detail); + if (rmd != 0.0f) { + float increment = (snoise_3d(p) + offset) * pwr * value; + value += rmd * increment; + } + + return value; +} + +ccl_device_noinline float noise_hetero_terrain( + float4 p, float detail, float roughness, float lacunarity, float offset) +{ + float pwr = roughness; + + /* 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(detail); i++) { + float increment = (snoise_4d(p) + offset) * pwr * value; + value += increment; + pwr *= roughness; + p *= lacunarity; + } + + float rmd = detail - floorf(detail); + if (rmd != 0.0f) { + float increment = (snoise_4d(p) + offset) * pwr * value; + value += rmd * increment; + } + + return value; +} + +/* Hybrid Additive/Multiplicative Multifractal Terrain */ + +ccl_device_noinline float noise_hybrid_multi_fractal( + float p, float detail, float roughness, float lacunarity, float offset, float gain) +{ + float pwr = 1.0f; + float value = 0.0f; + float weight = 1.0f; + + for (int i = 0; (weight > 0.001f) && (i <= float_to_int(detail)); i++) { + if (weight > 1.0f) { + weight = 1.0f; + } + + float signal = (snoise_1d(p) + offset) * pwr; + pwr *= roughness; + value += weight * signal; + weight *= gain * signal; + p *= lacunarity; + } + + float rmd = detail - floorf(detail); + if ((rmd != 0.0f) && (weight > 0.001f)) { + if (weight > 1.0f) { + weight = 1.0f; + } + float signal = (snoise_1d(p) + offset) * pwr; + value += rmd * weight * signal; + } + + return value; +} + +ccl_device_noinline float noise_hybrid_multi_fractal( + float2 p, float detail, float roughness, float lacunarity, float offset, float gain) +{ + float pwr = 1.0f; + float value = 0.0f; + float weight = 1.0f; + + for (int i = 0; (weight > 0.001f) && (i <= float_to_int(detail)); i++) { + if (weight > 1.0f) { + weight = 1.0f; + } + + float signal = (snoise_2d(p) + offset) * pwr; + pwr *= roughness; + value += weight * signal; + weight *= gain * signal; + p *= lacunarity; + } + + float rmd = detail - floorf(detail); + if ((rmd != 0.0f) && (weight > 0.001f)) { + if (weight > 1.0f) { + weight = 1.0f; + } + float signal = (snoise_2d(p) + offset) * pwr; + value += rmd * weight * signal; + } + + return value; +} + +ccl_device_noinline float noise_hybrid_multi_fractal( + float3 p, float detail, float roughness, float lacunarity, float offset, float gain) +{ + float pwr = 1.0f; + float value = 0.0f; + float weight = 1.0f; + + for (int i = 0; (weight > 0.001f) && (i <= float_to_int(detail)); i++) { + if (weight > 1.0f) { + weight = 1.0f; + } + + float signal = (snoise_3d(p) + offset) * pwr; + pwr *= roughness; + value += weight * signal; + weight *= gain * signal; + p *= lacunarity; + } + + float rmd = detail - floorf(detail); + if ((rmd != 0.0f) && (weight > 0.001f)) { + if (weight > 1.0f) { + weight = 1.0f; + } + float signal = (snoise_3d(p) + offset) * pwr; + value += rmd * weight * signal; + } + + return value; +} + +ccl_device_noinline float noise_hybrid_multi_fractal( + float4 p, float detail, float roughness, float lacunarity, float offset, float gain) +{ + float pwr = 1.0f; + float value = 0.0f; + float weight = 1.0f; + + for (int i = 0; (weight > 0.001f) && (i <= float_to_int(detail)); i++) { + if (weight > 1.0f) { + weight = 1.0f; + } + + float signal = (snoise_4d(p) + offset) * pwr; + pwr *= roughness; + value += weight * signal; + weight *= gain * signal; + p *= lacunarity; + } + + float rmd = detail - floorf(detail); + if ((rmd != 0.0f) && (weight > 0.001f)) { + if (weight > 1.0f) { + weight = 1.0f; + } + float signal = (snoise_4d(p) + offset) * pwr; + value += rmd * weight * signal; + } + + return value; +} + +/* Ridged Multifractal Terrain */ + +ccl_device_noinline float noise_ridged_multi_fractal( + float p, float detail, float roughness, float lacunarity, float offset, float gain) +{ + float pwr = roughness; + + float signal = offset - fabsf(snoise_1d(p)); + signal *= signal; + float value = signal; + float weight = 1.0f; + + for (int i = 1; i <= float_to_int(detail); i++) { + p *= lacunarity; + weight = saturatef(signal * gain); + signal = offset - fabsf(snoise_1d(p)); + signal *= signal; + signal *= weight; + value += signal * pwr; + pwr *= roughness; + } + + return value; +} + +ccl_device_noinline float noise_ridged_multi_fractal( + float2 p, float detail, float roughness, float lacunarity, float offset, float gain) +{ + float pwr = roughness; + + float signal = offset - fabsf(snoise_2d(p)); + signal *= signal; + float value = signal; + float weight = 1.0f; + + for (int i = 1; i <= float_to_int(detail); i++) { + p *= lacunarity; + weight = saturatef(signal * gain); + signal = offset - fabsf(snoise_2d(p)); + signal *= signal; + signal *= weight; + value += signal * pwr; + pwr *= roughness; + } + + return value; +} + +ccl_device_noinline float noise_ridged_multi_fractal( + float3 p, float detail, float roughness, float lacunarity, float offset, float gain) +{ + float pwr = roughness; + + float signal = offset - fabsf(snoise_3d(p)); + signal *= signal; + float value = signal; + float weight = 1.0f; + + for (int i = 1; i <= float_to_int(detail); i++) { + p *= lacunarity; + weight = saturatef(signal * gain); + signal = offset - fabsf(snoise_3d(p)); + signal *= signal; + signal *= weight; + value += signal * pwr; + pwr *= roughness; + } + + return value; +} + +ccl_device_noinline float noise_ridged_multi_fractal( + float4 p, float detail, float roughness, float lacunarity, float offset, float gain) +{ + float pwr = roughness; + + float signal = offset - fabsf(snoise_4d(p)); + signal *= signal; + float value = signal; + float weight = 1.0f; + + for (int i = 1; i <= float_to_int(detail); i++) { + p *= lacunarity; + weight = saturatef(signal * gain); + signal = offset - fabsf(snoise_4d(p)); + signal *= signal; + signal *= weight; + value += signal * pwr; + pwr *= roughness; + } + + return value; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/musgrave.h b/intern/cycles/kernel/svm/musgrave.h deleted file mode 100644 index 6ea48fa8390..00000000000 --- a/intern/cycles/kernel/svm/musgrave.h +++ /dev/null @@ -1,854 +0,0 @@ -/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation - * - * SPDX-License-Identifier: Apache-2.0 */ - -#pragma once - -#include "kernel/svm/noise.h" - -CCL_NAMESPACE_BEGIN - -/* 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" - */ - -ccl_device_noinline_cpu float noise_musgrave_fBm_1d(float co, - float H, - float lacunarity, - float octaves) -{ - float 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_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 = 1.0f; - float value = 0.0f; - float weight = 1.0f; - - for (int i = 0; (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) && (weight > 0.001f)) { - if (weight > 1.0f) { - weight = 1.0f; - } - float signal = (snoise_1d(p) + offset) * pwr; - value += rmd * weight * signal; - } - - 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 = saturatef(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 = 1.0f; - float value = 0.0f; - float weight = 1.0f; - - for (int i = 0; (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) && (weight > 0.001f)) { - if (weight > 1.0f) { - weight = 1.0f; - } - float signal = (snoise_2d(p) + offset) * pwr; - value += rmd * weight * signal; - } - - 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 = saturatef(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; - } - - float rmd = octaves - floorf(octaves); - if (rmd != 0.0f) { - value += rmd * snoise_3d(p) * pwr; - } - - return value; -} - -/* 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_3d(float3 co, - float H, - float lacunarity, - float octaves) -{ - float3 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_3d(p) + 1.0f); - pwr *= pwHL; - p *= lacunarity; - } - - float rmd = octaves - floorf(octaves); - if (rmd != 0.0f) { - value *= (rmd * pwr * snoise_3d(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' - */ - -ccl_device_noinline_cpu float noise_musgrave_hetero_terrain_3d( - float3 co, float H, float lacunarity, float octaves, float offset) -{ - float3 p = co; - float pwHL = powf(lacunarity, -H); - float pwr = pwHL; - - /* first unscaled octave of function; later octaves are scaled */ - float value = offset + snoise_3d(p); - p *= lacunarity; - - for (int i = 1; i < float_to_int(octaves); i++) { - float increment = (snoise_3d(p) + offset) * pwr * value; - value += increment; - pwr *= pwHL; - p *= lacunarity; - } - - float rmd = octaves - floorf(octaves); - if (rmd != 0.0f) { - float increment = (snoise_3d(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' - */ - -ccl_device_noinline_cpu float noise_musgrave_hybrid_multi_fractal_3d( - float3 co, float H, float lacunarity, float octaves, float offset, float gain) -{ - float3 p = co; - float pwHL = powf(lacunarity, -H); - - float pwr = 1.0f; - float value = 0.0f; - float weight = 1.0f; - - for (int i = 0; (weight > 0.001f) && (i < float_to_int(octaves)); i++) { - if (weight > 1.0f) { - weight = 1.0f; - } - - float signal = (snoise_3d(p) + offset) * pwr; - pwr *= pwHL; - value += weight * signal; - weight *= gain * signal; - p *= lacunarity; - } - - float rmd = octaves - floorf(octaves); - if ((rmd != 0.0f) && (weight > 0.001f)) { - if (weight > 1.0f) { - weight = 1.0f; - } - float signal = (snoise_3d(p) + offset) * pwr; - value += rmd * weight * signal; - } - - 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' - */ - -ccl_device_noinline_cpu float noise_musgrave_ridged_multi_fractal_3d( - float3 co, float H, float lacunarity, float octaves, float offset, float gain) -{ - float3 p = co; - float pwHL = powf(lacunarity, -H); - float pwr = pwHL; - - float signal = offset - fabsf(snoise_3d(p)); - signal *= signal; - float value = signal; - float weight = 1.0f; - - for (int i = 1; i < float_to_int(octaves); i++) { - p *= lacunarity; - weight = saturatef(signal * gain); - signal = offset - fabsf(snoise_3d(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" - */ - -ccl_device_noinline_cpu float noise_musgrave_fBm_4d(float4 co, - float H, - float lacunarity, - float octaves) -{ - 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 value; -} - -/* 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) -{ - float4 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_4d(p) + 1.0f); - pwr *= pwHL; - p *= lacunarity; - } - - float rmd = octaves - floorf(octaves); - if (rmd != 0.0f) { - value *= (rmd * pwr * snoise_4d(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' - */ - -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 = 1.0f; - float value = 0.0f; - float weight = 1.0f; - - for (int i = 0; (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) && (weight > 0.001f)) { - if (weight > 1.0f) { - weight = 1.0f; - } - float signal = (snoise_4d(p) + offset) * pwr; - value += rmd * weight * signal; - } - - 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 = saturatef(signal * gain); - signal = offset - fabsf(snoise_4d(p)); - signal *= signal; - signal *= weight; - value += signal * pwr; - pwr *= pwHL; - } - - return value; -} - -ccl_device_noinline int svm_node_tex_musgrave(KernelGlobals kg, - ccl_private ShaderData *sd, - ccl_private 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, 15.0f); - lacunarity = fmaxf(lacunarity, 1e-5f); - - 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; - } - - stack_store_float(stack, fac_stack_offset, fac); - return offset; -} - -CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/node_types_template.h b/intern/cycles/kernel/svm/node_types_template.h index afda2a7a019..3893fc9a000 100644 --- a/intern/cycles/kernel/svm/node_types_template.h +++ b/intern/cycles/kernel/svm/node_types_template.h @@ -69,7 +69,6 @@ SHADER_NODE_TYPE(NODE_TEX_ENVIRONMENT) SHADER_NODE_TYPE(NODE_TEX_SKY) SHADER_NODE_TYPE(NODE_TEX_GRADIENT) SHADER_NODE_TYPE(NODE_TEX_VORONOI) -SHADER_NODE_TYPE(NODE_TEX_MUSGRAVE) SHADER_NODE_TYPE(NODE_TEX_WAVE) SHADER_NODE_TYPE(NODE_TEX_MAGIC) SHADER_NODE_TYPE(NODE_TEX_CHECKER) @@ -111,5 +110,6 @@ SHADER_NODE_TYPE(NODE_MIX_VECTOR_NON_UNIFORM) /* Padding for struct alignment. */ SHADER_NODE_TYPE(NODE_PAD1) +SHADER_NODE_TYPE(NODE_PAD2) #undef SHADER_NODE_TYPE diff --git a/intern/cycles/kernel/svm/noisetex.h b/intern/cycles/kernel/svm/noisetex.h index a75eb98d301..92ef657f836 100644 --- a/intern/cycles/kernel/svm/noisetex.h +++ b/intern/cycles/kernel/svm/noisetex.h @@ -42,11 +42,47 @@ ccl_device_inline float4 random_float4_offset(float seed) 100.0f + hash_float2_to_float(make_float2(seed, 3.0f)) * 100.0f); } +template +ccl_device float noise_select(T p, + float detail, + float roughness, + float lacunarity, + float offset, + float gain, + int type, + bool normalize) +{ + switch ((NodeNoiseType)type) { + case NODE_NOISE_MULTIFRACTAL: { + return noise_multi_fractal(p, detail, roughness, lacunarity); + } + case NODE_NOISE_FBM: { + return noise_fbm(p, detail, roughness, lacunarity, normalize); + } + case NODE_NOISE_HYBRID_MULTIFRACTAL: { + return noise_hybrid_multi_fractal(p, detail, roughness, lacunarity, offset, gain); + } + case NODE_NOISE_RIDGED_MULTIFRACTAL: { + return noise_ridged_multi_fractal(p, detail, roughness, lacunarity, offset, gain); + } + case NODE_NOISE_HETERO_TERRAIN: { + return noise_hetero_terrain(p, detail, roughness, lacunarity, offset); + } + default: { + kernel_assert(0); + return 0.0; + } + } +} + ccl_device void noise_texture_1d(float co, float detail, float roughness, float lacunarity, + float offset, + float gain, float distortion, + int type, bool normalize, bool color_is_needed, ccl_private float *value, @@ -57,12 +93,25 @@ ccl_device void noise_texture_1d(float co, p += snoise_1d(p + random_float_offset(0.0f)) * distortion; } - *value = fractal_noise_1d(p, detail, roughness, lacunarity, normalize); + *value = noise_select(p, detail, roughness, lacunarity, offset, gain, type, normalize); if (color_is_needed) { - *color = make_float3( - *value, - fractal_noise_1d(p + random_float_offset(1.0f), detail, roughness, lacunarity, normalize), - fractal_noise_1d(p + random_float_offset(2.0f), detail, roughness, lacunarity, normalize)); + *color = make_float3(*value, + noise_select(p + random_float_offset(1.0f), + detail, + roughness, + lacunarity, + offset, + gain, + type, + normalize), + noise_select(p + random_float_offset(2.0f), + detail, + roughness, + lacunarity, + offset, + gain, + type, + normalize)); } } @@ -70,7 +119,10 @@ ccl_device void noise_texture_2d(float2 co, float detail, float roughness, float lacunarity, + float offset, + float gain, float distortion, + int type, bool normalize, bool color_is_needed, ccl_private float *value, @@ -82,13 +134,25 @@ ccl_device void noise_texture_2d(float2 co, snoise_2d(p + random_float2_offset(1.0f)) * distortion); } - *value = fractal_noise_2d(p, detail, roughness, lacunarity, normalize); + *value = noise_select(p, detail, roughness, lacunarity, offset, gain, type, normalize); if (color_is_needed) { - *color = make_float3( - *value, - fractal_noise_2d(p + random_float2_offset(2.0f), detail, roughness, lacunarity, normalize), - fractal_noise_2d( - p + random_float2_offset(3.0f), detail, roughness, lacunarity, normalize)); + *color = make_float3(*value, + noise_select(p + random_float2_offset(2.0f), + detail, + roughness, + lacunarity, + offset, + gain, + type, + normalize), + noise_select(p + random_float2_offset(3.0f), + detail, + roughness, + lacunarity, + offset, + gain, + type, + normalize)); } } @@ -96,7 +160,10 @@ ccl_device void noise_texture_3d(float3 co, float detail, float roughness, float lacunarity, + float offset, + float gain, float distortion, + int type, bool normalize, bool color_is_needed, ccl_private float *value, @@ -109,13 +176,25 @@ ccl_device void noise_texture_3d(float3 co, snoise_3d(p + random_float3_offset(2.0f)) * distortion); } - *value = fractal_noise_3d(p, detail, roughness, lacunarity, normalize); + *value = noise_select(p, detail, roughness, lacunarity, offset, gain, type, normalize); if (color_is_needed) { - *color = make_float3( - *value, - fractal_noise_3d(p + random_float3_offset(3.0f), detail, roughness, lacunarity, normalize), - fractal_noise_3d( - p + random_float3_offset(4.0f), detail, roughness, lacunarity, normalize)); + *color = make_float3(*value, + noise_select(p + random_float3_offset(3.0f), + detail, + roughness, + lacunarity, + offset, + gain, + type, + normalize), + noise_select(p + random_float3_offset(4.0f), + detail, + roughness, + lacunarity, + offset, + gain, + type, + normalize)); } } @@ -123,7 +202,10 @@ ccl_device void noise_texture_4d(float4 co, float detail, float roughness, float lacunarity, + float offset, + float gain, float distortion, + int type, bool normalize, bool color_is_needed, ccl_private float *value, @@ -137,13 +219,25 @@ ccl_device void noise_texture_4d(float4 co, snoise_4d(p + random_float4_offset(3.0f)) * distortion); } - *value = fractal_noise_4d(p, detail, roughness, lacunarity, normalize); + *value = noise_select(p, detail, roughness, lacunarity, offset, gain, type, normalize); if (color_is_needed) { - *color = make_float3( - *value, - fractal_noise_4d(p + random_float4_offset(4.0f), detail, roughness, lacunarity, normalize), - fractal_noise_4d( - p + random_float4_offset(5.0f), detail, roughness, lacunarity, normalize)); + *color = make_float3(*value, + noise_select(p + random_float4_offset(4.0f), + detail, + roughness, + lacunarity, + offset, + gain, + type, + normalize), + noise_select(p + random_float4_offset(5.0f), + detail, + roughness, + lacunarity, + offset, + gain, + type, + normalize)); } } @@ -153,24 +247,29 @@ ccl_device_noinline int svm_node_tex_noise(KernelGlobals kg, uint offsets1, uint offsets2, uint offsets3, - int offset) + int node_offset) { uint vector_stack_offset, w_stack_offset, scale_stack_offset, detail_stack_offset; - uint roughness_stack_offset, lacunarity_stack_offset, distortion_stack_offset, - value_stack_offset; - uint color_stack_offset, dimensions, normalize; + uint roughness_stack_offset, lacunarity_stack_offset, offset_stack_offset, gain_stack_offset; + uint distortion_stack_offset, value_stack_offset, color_stack_offset; svm_unpack_node_uchar4( offsets1, &vector_stack_offset, &w_stack_offset, &scale_stack_offset, &detail_stack_offset); svm_unpack_node_uchar4(offsets2, &roughness_stack_offset, &lacunarity_stack_offset, - &distortion_stack_offset, - &value_stack_offset); - svm_unpack_node_uchar3(offsets3, &color_stack_offset, &dimensions, &normalize); + &offset_stack_offset, + &gain_stack_offset); + svm_unpack_node_uchar3( + offsets3, &distortion_stack_offset, &value_stack_offset, &color_stack_offset); - uint4 defaults1 = read_node(kg, &offset); - uint4 defaults2 = read_node(kg, &offset); + uint4 defaults1 = read_node(kg, &node_offset); + uint4 defaults2 = read_node(kg, &node_offset); + uint4 properties = read_node(kg, &node_offset); + + uint dimensions = properties.x; + uint type = properties.y; + uint normalize = properties.z; float3 vector = stack_load_float3(stack, vector_stack_offset); float w = stack_load_float_default(stack, w_stack_offset, defaults1.x); @@ -178,7 +277,12 @@ ccl_device_noinline int svm_node_tex_noise(KernelGlobals kg, float detail = stack_load_float_default(stack, detail_stack_offset, defaults1.z); float roughness = stack_load_float_default(stack, roughness_stack_offset, defaults1.w); float lacunarity = stack_load_float_default(stack, lacunarity_stack_offset, defaults2.x); - float distortion = stack_load_float_default(stack, distortion_stack_offset, defaults2.y); + float offset = stack_load_float_default(stack, offset_stack_offset, defaults2.y); + float gain = stack_load_float_default(stack, gain_stack_offset, defaults2.z); + float distortion = stack_load_float_default(stack, distortion_stack_offset, defaults2.w); + + detail = clamp(detail, 0.0f, 15.0f); + roughness = fmaxf(roughness, 0.0f); vector *= scale; w *= scale; @@ -191,7 +295,10 @@ ccl_device_noinline int svm_node_tex_noise(KernelGlobals kg, detail, roughness, lacunarity, + offset, + gain, distortion, + type, normalize, stack_valid(color_stack_offset), &value, @@ -202,7 +309,10 @@ ccl_device_noinline int svm_node_tex_noise(KernelGlobals kg, detail, roughness, lacunarity, + offset, + gain, distortion, + type, normalize, stack_valid(color_stack_offset), &value, @@ -213,7 +323,10 @@ ccl_device_noinline int svm_node_tex_noise(KernelGlobals kg, detail, roughness, lacunarity, + offset, + gain, distortion, + type, normalize, stack_valid(color_stack_offset), &value, @@ -224,7 +337,10 @@ ccl_device_noinline int svm_node_tex_noise(KernelGlobals kg, detail, roughness, lacunarity, + offset, + gain, distortion, + type, normalize, stack_valid(color_stack_offset), &value, @@ -240,7 +356,7 @@ ccl_device_noinline int svm_node_tex_noise(KernelGlobals kg, if (stack_valid(color_stack_offset)) { stack_store_float3(stack, color_stack_offset, color); } - return offset; + return node_offset; } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index 45f7099f069..df95cef8b5e 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -178,7 +178,6 @@ CCL_NAMESPACE_END #include "kernel/svm/mapping.h" #include "kernel/svm/math.h" #include "kernel/svm/mix.h" -#include "kernel/svm/musgrave.h" #include "kernel/svm/noisetex.h" #include "kernel/svm/normal.h" #include "kernel/svm/ramp.h" @@ -481,9 +480,6 @@ ccl_device void svm_eval_nodes(KernelGlobals kg, offset = svm_node_tex_voronoi( kg, sd, stack, node.y, node.z, node.w, offset); break; - SVM_CASE(NODE_TEX_MUSGRAVE) - offset = svm_node_tex_musgrave(kg, sd, stack, node.y, node.z, node.w, offset); - break; SVM_CASE(NODE_TEX_WAVE) offset = svm_node_tex_wave(kg, sd, stack, node, offset); break; diff --git a/intern/cycles/kernel/svm/types.h b/intern/cycles/kernel/svm/types.h index 1cf96a3f7e3..90421ac1860 100644 --- a/intern/cycles/kernel/svm/types.h +++ b/intern/cycles/kernel/svm/types.h @@ -268,13 +268,13 @@ typedef enum NodeConvert { NODE_CONVERT_IV } NodeConvert; -typedef enum NodeMusgraveType { - NODE_MUSGRAVE_MULTIFRACTAL, - NODE_MUSGRAVE_FBM, - NODE_MUSGRAVE_HYBRID_MULTIFRACTAL, - NODE_MUSGRAVE_RIDGED_MULTIFRACTAL, - NODE_MUSGRAVE_HETERO_TERRAIN -} NodeMusgraveType; +typedef enum NodeNoiseType { + NODE_NOISE_MULTIFRACTAL, + NODE_NOISE_FBM, + NODE_NOISE_HYBRID_MULTIFRACTAL, + NODE_NOISE_RIDGED_MULTIFRACTAL, + NODE_NOISE_HETERO_TERRAIN +} NodeNoiseType; typedef enum NodeWaveType { NODE_WAVE_BANDS, NODE_WAVE_RINGS } NodeWaveType; diff --git a/intern/cycles/kernel/svm/wave.h b/intern/cycles/kernel/svm/wave.h index df3acfa351d..2b908056443 100644 --- a/intern/cycles/kernel/svm/wave.h +++ b/intern/cycles/kernel/svm/wave.h @@ -57,7 +57,7 @@ ccl_device_noinline_cpu float svm_wave(NodeWaveType type, n += phase; if (distortion != 0.0f) { - n += distortion * (fractal_noise_3d(p * dscale, detail, droughness, 2.0f, true) * 2.0f - 1.0f); + n += distortion * (noise_fbm(p * dscale, detail, droughness, 2.0f, true) * 2.0f - 1.0f); } if (profile == NODE_WAVE_PROFILE_SIN) { diff --git a/intern/cycles/scene/shader_nodes.cpp b/intern/cycles/scene/shader_nodes.cpp index a86b1e71da8..a746ad1d4e8 100644 --- a/intern/cycles/scene/shader_nodes.cpp +++ b/intern/cycles/scene/shader_nodes.cpp @@ -1137,6 +1137,14 @@ NODE_DEFINE(NoiseTextureNode) dimensions_enum.insert("4D", 4); SOCKET_ENUM(dimensions, "Dimensions", dimensions_enum, 3); + static NodeEnum type_enum; + type_enum.insert("multifractal", NODE_NOISE_MULTIFRACTAL); + type_enum.insert("fBM", NODE_NOISE_FBM); + type_enum.insert("hybrid_multifractal", NODE_NOISE_HYBRID_MULTIFRACTAL); + type_enum.insert("ridged_multifractal", NODE_NOISE_RIDGED_MULTIFRACTAL); + type_enum.insert("hetero_terrain", NODE_NOISE_HETERO_TERRAIN); + SOCKET_ENUM(type, "Type", type_enum, NODE_NOISE_FBM); + SOCKET_BOOLEAN(use_normalize, "Normalize", true); SOCKET_IN_POINT(vector, "Vector", zero_float3(), SocketType::LINK_TEXTURE_GENERATED); @@ -1145,6 +1153,8 @@ NODE_DEFINE(NoiseTextureNode) SOCKET_IN_FLOAT(detail, "Detail", 2.0f); SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f); SOCKET_IN_FLOAT(lacunarity, "Lacunarity", 2.0f); + SOCKET_IN_FLOAT(offset, "Offset", 0.0f); + SOCKET_IN_FLOAT(gain, "Gain", 1.0f); SOCKET_IN_FLOAT(distortion, "Distortion", 0.0f); SOCKET_OUT_FLOAT(fac, "Fac"); @@ -1163,6 +1173,8 @@ void NoiseTextureNode::compile(SVMCompiler &compiler) ShaderInput *detail_in = input("Detail"); ShaderInput *roughness_in = input("Roughness"); ShaderInput *lacunarity_in = input("Lacunarity"); + ShaderInput *offset_in = input("Offset"); + ShaderInput *gain_in = input("Gain"); ShaderInput *distortion_in = input("Distortion"); ShaderOutput *fac_out = output("Fac"); ShaderOutput *color_out = output("Color"); @@ -1173,6 +1185,8 @@ void NoiseTextureNode::compile(SVMCompiler &compiler) int detail_stack_offset = compiler.stack_assign_if_linked(detail_in); int roughness_stack_offset = compiler.stack_assign_if_linked(roughness_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 distortion_stack_offset = compiler.stack_assign_if_linked(distortion_in); int fac_stack_offset = compiler.stack_assign_if_linked(fac_out); int color_stack_offset = compiler.stack_assign_if_linked(color_out); @@ -1181,19 +1195,18 @@ void NoiseTextureNode::compile(SVMCompiler &compiler) NODE_TEX_NOISE, compiler.encode_uchar4( vector_stack_offset, w_stack_offset, scale_stack_offset, detail_stack_offset), - compiler.encode_uchar4(roughness_stack_offset, - lacunarity_stack_offset, - distortion_stack_offset, - fac_stack_offset), - compiler.encode_uchar4(color_stack_offset, dimensions, use_normalize)); + compiler.encode_uchar4( + roughness_stack_offset, lacunarity_stack_offset, offset_stack_offset, gain_stack_offset), + compiler.encode_uchar4(distortion_stack_offset, fac_stack_offset, color_stack_offset)); compiler.add_node( __float_as_int(w), __float_as_int(scale), __float_as_int(detail), __float_as_int(roughness)); compiler.add_node(__float_as_int(lacunarity), - __float_as_int(distortion), - SVM_STACK_INVALID, - SVM_STACK_INVALID); + __float_as_int(offset), + __float_as_int(gain), + __float_as_int(distortion)); + compiler.add_node(dimensions, type, use_normalize, SVM_STACK_INVALID); tex_mapping.compile_end(compiler, vector_in, vector_stack_offset); } @@ -1202,6 +1215,7 @@ void NoiseTextureNode::compile(OSLCompiler &compiler) { tex_mapping.compile(compiler); compiler.parameter(this, "dimensions"); + compiler.parameter(this, "type"); compiler.parameter(this, "use_normalize"); compiler.add(this, "node_noise_texture"); } @@ -1461,91 +1475,6 @@ void WhiteNoiseTextureNode::compile(OSLCompiler &compiler) compiler.add(this, "node_white_noise_texture"); } -/* Musgrave Texture */ - -NODE_DEFINE(MusgraveTextureNode) -{ - NodeType *type = NodeType::add("musgrave_texture", create, NodeType::SHADER); - - 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); - type_enum.insert("hybrid_multifractal", NODE_MUSGRAVE_HYBRID_MULTIFRACTAL); - type_enum.insert("ridged_multifractal", NODE_MUSGRAVE_RIDGED_MULTIFRACTAL); - type_enum.insert("hetero_terrain", NODE_MUSGRAVE_HETERO_TERRAIN); - SOCKET_ENUM(musgrave_type, "Type", type_enum, NODE_MUSGRAVE_FBM); - - SOCKET_IN_POINT(vector, "Vector", zero_float3(), 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", 2.0f); - SOCKET_IN_FLOAT(offset, "Offset", 0.0f); - SOCKET_IN_FLOAT(gain, "Gain", 1.0f); - - SOCKET_OUT_FLOAT(fac, "Fac"); - - return type; -} - -MusgraveTextureNode::MusgraveTextureNode() : TextureNode(get_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 *offset_in = input("Offset"); - ShaderInput *gain_in = input("Gain"); - ShaderOutput *fac_out = output("Fac"); - - 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(musgrave_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_stack_offset); -} - -void MusgraveTextureNode::compile(OSLCompiler &compiler) -{ - tex_mapping.compile(compiler); - - compiler.parameter(this, "musgrave_type"); - compiler.parameter(this, "dimensions"); - compiler.add(this, "node_musgrave_texture"); -} - /* Wave Texture */ NODE_DEFINE(WaveTextureNode) diff --git a/intern/cycles/scene/shader_nodes.h b/intern/cycles/scene/shader_nodes.h index 5e349ade9f4..c5643c2166a 100644 --- a/intern/cycles/scene/shader_nodes.h +++ b/intern/cycles/scene/shader_nodes.h @@ -228,12 +228,15 @@ class NoiseTextureNode : public TextureNode { SHADER_NODE_CLASS(NoiseTextureNode) NODE_SOCKET_API(int, dimensions) + NODE_SOCKET_API(NodeNoiseType, type) NODE_SOCKET_API(bool, use_normalize) NODE_SOCKET_API(float, w) NODE_SOCKET_API(float, scale) NODE_SOCKET_API(float, detail) NODE_SOCKET_API(float, roughness) NODE_SOCKET_API(float, lacunarity) + NODE_SOCKET_API(float, offset) + NODE_SOCKET_API(float, gain) NODE_SOCKET_API(float, distortion) NODE_SOCKET_API(float3, vector) }; @@ -269,22 +272,6 @@ class VoronoiTextureNode : public TextureNode { NODE_SOCKET_API(float3, vector) }; -class MusgraveTextureNode : public TextureNode { - public: - SHADER_NODE_CLASS(MusgraveTextureNode) - - NODE_SOCKET_API(int, dimensions) - NODE_SOCKET_API(NodeMusgraveType, musgrave_type) - NODE_SOCKET_API(float, w) - NODE_SOCKET_API(float, scale) - NODE_SOCKET_API(float, detail) - NODE_SOCKET_API(float, dimension) - NODE_SOCKET_API(float, lacunarity) - NODE_SOCKET_API(float, offset) - NODE_SOCKET_API(float, gain) - NODE_SOCKET_API(float3, vector) -}; - class WaveTextureNode : public TextureNode { public: SHADER_NODE_CLASS(WaveTextureNode) diff --git a/scripts/startup/bl_ui/node_add_menu_geometry.py b/scripts/startup/bl_ui/node_add_menu_geometry.py index 4089e5b67b2..8636f7d27fa 100644 --- a/scripts/startup/bl_ui/node_add_menu_geometry.py +++ b/scripts/startup/bl_ui/node_add_menu_geometry.py @@ -522,7 +522,6 @@ class NODE_MT_category_GEO_TEXTURE(Menu): node_add_menu.add_node_type(layout, "ShaderNodeTexGradient") node_add_menu.add_node_type(layout, "GeometryNodeImageTexture") node_add_menu.add_node_type(layout, "ShaderNodeTexMagic") - node_add_menu.add_node_type(layout, "ShaderNodeTexMusgrave") node_add_menu.add_node_type(layout, "ShaderNodeTexNoise") node_add_menu.add_node_type(layout, "ShaderNodeTexVoronoi") node_add_menu.add_node_type(layout, "ShaderNodeTexWave") diff --git a/scripts/startup/bl_ui/node_add_menu_shader.py b/scripts/startup/bl_ui/node_add_menu_shader.py index b181dc50b19..eec7028a010 100644 --- a/scripts/startup/bl_ui/node_add_menu_shader.py +++ b/scripts/startup/bl_ui/node_add_menu_shader.py @@ -292,7 +292,6 @@ class NODE_MT_category_shader_texture(Menu): node_add_menu.add_node_type(layout, "ShaderNodeTexIES") node_add_menu.add_node_type(layout, "ShaderNodeTexImage") node_add_menu.add_node_type(layout, "ShaderNodeTexMagic") - node_add_menu.add_node_type(layout, "ShaderNodeTexMusgrave") node_add_menu.add_node_type(layout, "ShaderNodeTexNoise") node_add_menu.add_node_type(layout, "ShaderNodeTexPointDensity") node_add_menu.add_node_type(layout, "ShaderNodeTexSky") diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 574bcc60eba..136f1d09e0c 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -906,7 +906,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i #define SH_NODE_TEX_MAGIC 148 #define SH_NODE_TEX_WAVE 149 #define SH_NODE_TEX_NOISE 150 -#define SH_NODE_TEX_MUSGRAVE 152 +#define SH_NODE_TEX_MUSGRAVE_DEPRECATED 152 #define SH_NODE_TEX_COORD 155 #define SH_NODE_ADD_SHADER 156 #define SH_NODE_TEX_ENVIRONMENT 157 diff --git a/source/blender/blenlib/BLI_noise.hh b/source/blender/blenlib/BLI_noise.hh index b68d76265e8..c0bc7bf2f60 100644 --- a/source/blender/blenlib/BLI_noise.hh +++ b/source/blender/blenlib/BLI_noise.hh @@ -72,268 +72,65 @@ float perlin(float2 position); float perlin(float3 position); float perlin(float4 position); -/* Fractal perlin noise in the range [0, 1]. */ +/* Perlin fractal Brownian motion. */ -float perlin_fractal( - float position, float octaves, float roughness, float lacunarity, bool normalize); -float perlin_fractal( - float2 position, float octaves, float roughness, float lacunarity, bool normalize); -float perlin_fractal( - float3 position, float octaves, float roughness, float lacunarity, bool normalize); -float perlin_fractal( - float4 position, float octaves, float roughness, float lacunarity, bool normalize); +template +float perlin_fbm(T p, float detail, float roughness, float lacunarity, bool normalize); -/* Positive distorted fractal perlin noise. */ +/* Distorted fractal perlin noise. */ -float perlin_fractal_distorted(float position, - float octaves, - float roughness, - float lacunarity, - float distortion, - bool normalize); -float perlin_fractal_distorted(float2 position, - float octaves, - float roughness, - float lacunarity, - float distortion, - bool normalize); -float perlin_fractal_distorted(float3 position, - float octaves, - float roughness, - float lacunarity, - float distortion, - bool normalize); -float perlin_fractal_distorted(float4 position, - float octaves, +template +float perlin_fractal_distorted(T position, + float detail, float roughness, float lacunarity, + float offset, + float gain, float distortion, + int type, bool normalize); -/* Positive distorted fractal perlin noise that outputs a float3. */ +/* Distorted fractal perlin noise that outputs a float3. */ float3 perlin_float3_fractal_distorted(float position, - float octaves, + float detail, float roughness, float lacunarity, + float offset, + float gain, float distortion, + int type, bool normalize); float3 perlin_float3_fractal_distorted(float2 position, - float octaves, + float detail, float roughness, float lacunarity, + float offset, + float gain, float distortion, + int type, bool normalize); float3 perlin_float3_fractal_distorted(float3 position, - float octaves, + float detail, float roughness, float lacunarity, + float offset, + float gain, float distortion, + int type, bool normalize); float3 perlin_float3_fractal_distorted(float4 position, - float octaves, + float detail, float roughness, float lacunarity, + float offset, + float gain, float distortion, + int type, bool normalize); /** \} */ -/* -------------------------------------------------------------------- */ -/** \name Musgrave Multi Fractal - * \{ */ - -/** - * 1D Ridged Multi-fractal Terrain - * - * \param H: fractal dimension of the roughest area. - * \param lacunarity: gap between successive frequencies. - * \param octaves: number of frequencies in the fBm. - * \param offset: raises the terrain from `sea level'. - */ -float musgrave_ridged_multi_fractal( - float co, float H, float lacunarity, float octaves, float offset, float gain); -/** - * 2D Ridged Multi-fractal Terrain - * - * \param H: fractal dimension of the roughest area. - * \param lacunarity: gap between successive frequencies. - * \param octaves: number of frequencies in the fBm. - * \param offset: raises the terrain from `sea level'. - */ -float musgrave_ridged_multi_fractal( - const float2 co, float H, float lacunarity, float octaves, float offset, float gain); -/** - * 3D Ridged Multi-fractal Terrain - * - * \param H: fractal dimension of the roughest area. - * \param lacunarity: gap between successive frequencies. - * \param octaves: number of frequencies in the fBm. - * \param offset: raises the terrain from `sea level'. - */ -float musgrave_ridged_multi_fractal( - const float3 co, float H, float lacunarity, float octaves, float offset, float gain); -/** - * 4D Ridged Multi-fractal Terrain - * - * \param H: fractal dimension of the roughest area. - * \param lacunarity: gap between successive frequencies. - * \param octaves: number of frequencies in the fBm. - * \param offset: raises the terrain from `sea level'. - */ -float musgrave_ridged_multi_fractal( - const float4 co, float H, float lacunarity, float octaves, float offset, float gain); - -/** - * 1D Hybrid Additive/Multiplicative Multi-fractal Terrain - * - * \param H: fractal dimension of the roughest area. - * \param lacunarity: gap between successive frequencies. - * \param octaves: number of frequencies in the fBm. - * \param offset: raises the terrain from `sea level'. - */ -float musgrave_hybrid_multi_fractal( - float co, float H, float lacunarity, float octaves, float offset, float gain); -/** - * 2D Hybrid Additive/Multiplicative Multi-fractal Terrain - * - * \param H: fractal dimension of the roughest area. - * \param lacunarity: gap between successive frequencies. - * \param octaves: number of frequencies in the fBm. - * \param offset: raises the terrain from `sea level'. - */ -float musgrave_hybrid_multi_fractal( - const float2 co, float H, float lacunarity, float octaves, float offset, float gain); -/** - * 3D Hybrid Additive/Multiplicative Multi-fractal Terrain - * - * \param H: fractal dimension of the roughest area. - * \param lacunarity: gap between successive frequencies. - * \param octaves: number of frequencies in the fBm. - * \param offset: raises the terrain from `sea level'. - */ -float musgrave_hybrid_multi_fractal( - const float3 co, float H, float lacunarity, float octaves, float offset, float gain); -/** - * 4D Hybrid Additive/Multiplicative Multi-fractal Terrain - * - * \param H: fractal dimension of the roughest area. - * \param lacunarity: gap between successive frequencies. - * \param octaves: number of frequencies in the fBm. - * \param offset: raises the terrain from `sea level'. - */ -float musgrave_hybrid_multi_fractal( - const float4 co, float H, float lacunarity, float octaves, float offset, float gain); - -/** - * 1D Musgrave fBm - * - * \param H: fractal increment parameter. - * \param lacunarity: gap between successive frequencies. - * \param octaves: number of frequencies in the fBm. - */ -float musgrave_fBm(float co, float H, float lacunarity, float octaves); - -/** - * 2D Musgrave fBm - * - * \param H: fractal increment parameter. - * \param lacunarity: gap between successive frequencies. - * \param octaves: number of frequencies in the fBm. - */ -float musgrave_fBm(const float2 co, float H, float lacunarity, float octaves); -/** - * 3D Musgrave fBm - * - * \param H: fractal increment parameter. - * \param lacunarity: gap between successive frequencies. - * \param octaves: number of frequencies in the fBm. - */ -float musgrave_fBm(const float3 co, float H, float lacunarity, float octaves); -/** - * 4D Musgrave fBm - * - * \param H: fractal increment parameter. - * \param lacunarity: gap between successive frequencies. - * \param octaves: number of frequencies in the fBm. - */ -float musgrave_fBm(const float4 co, float H, float lacunarity, float octaves); - -/** - * 1D Musgrave Multi-fractal - * - * \param H: highest fractal dimension. - * \param lacunarity: gap between successive frequencies. - * \param octaves: number of frequencies in the fBm. - */ -float musgrave_multi_fractal(float co, float H, float lacunarity, float octaves); -/** - * 2D Musgrave Multi-fractal - * - * \param H: highest fractal dimension. - * \param lacunarity: gap between successive frequencies. - * \param octaves: number of frequencies in the fBm. - */ -float musgrave_multi_fractal(const float2 co, float H, float lacunarity, float octaves); -/** - * 3D Musgrave Multi-fractal - * - * \param H: highest fractal dimension. - * \param lacunarity: gap between successive frequencies. - * \param octaves: number of frequencies in the fBm. - */ -float musgrave_multi_fractal(const float3 co, float H, float lacunarity, float octaves); -/** - * 4D Musgrave Multi-fractal - * - * \param H: highest fractal dimension. - * \param lacunarity: gap between successive frequencies. - * \param octaves: number of frequencies in the fBm. - */ -float musgrave_multi_fractal(const float4 co, float H, float lacunarity, float octaves); - -/** - * 1D Musgrave Heterogeneous Terrain - * - * \param H: fractal dimension of the roughest area. - * \param lacunarity: gap between successive frequencies. - * \param octaves: number of frequencies in the fBm. - * \param offset: raises the terrain from `sea level'. - */ -float musgrave_hetero_terrain(float co, float H, float lacunarity, float octaves, float offset); -/** - * 2D Musgrave Heterogeneous Terrain - * - * \param H: fractal dimension of the roughest area. - * \param lacunarity: gap between successive frequencies. - * \param octaves: number of frequencies in the fBm. - * \param offset: raises the terrain from `sea level'. - */ -float musgrave_hetero_terrain( - const float2 co, float H, float lacunarity, float octaves, float offset); -/** - * 3D Musgrave Heterogeneous Terrain - * - * \param H: fractal dimension of the roughest area. - * \param lacunarity: gap between successive frequencies. - * \param octaves: number of frequencies in the fBm. - * \param offset: raises the terrain from `sea level'. - */ -float musgrave_hetero_terrain( - const float3 co, float H, float lacunarity, float octaves, float offset); -/** - * 4D Musgrave Heterogeneous Terrain - * - * \param H: fractal dimension of the roughest area. - * \param lacunarity: gap between successive frequencies. - * \param octaves: number of frequencies in the fBm. - * \param offset: raises the terrain from `sea level'. - */ -float musgrave_hetero_terrain( - const float4 co, float H, float lacunarity, float octaves, float offset); - -/** \} */ - /* -------------------------------------------------------------------- */ /** \name Voronoi Noise * \{ */ diff --git a/source/blender/blenlib/intern/noise.cc b/source/blender/blenlib/intern/noise.cc index 3ec0dc2858d..3e0770b8063 100644 --- a/source/blender/blenlib/intern/noise.cc +++ b/source/blender/blenlib/intern/noise.cc @@ -530,28 +530,28 @@ float perlin(float4 position) return perlin_signed(position) / 2.0f + 0.5f; } -/* Positive fractal perlin noise. */ +/* Fractal perlin noise. */ +/* fBM = Fractal Brownian Motion */ template -float perlin_fractal_template( - T position, float octaves, float roughness, float lacunarity, bool normalize) +float perlin_fbm( + T p, const float detail, const float roughness, const float lacunarity, const bool normalize) { float fscale = 1.0f; float amp = 1.0f; float maxamp = 0.0f; float sum = 0.0f; - octaves = CLAMPIS(octaves, 0.0f, 15.0f); - int n = int(octaves); - for (int i = 0; i <= n; i++) { - float t = perlin_signed(fscale * position); + + for (int i = 0; i <= int(detail); i++) { + float t = perlin_signed(fscale * p); sum += t * amp; maxamp += amp; - amp *= CLAMPIS(roughness, 0.0f, 1.0f); + amp *= roughness; fscale *= lacunarity; } - float rmd = octaves - std::floor(octaves); + float rmd = detail - std::floor(detail); if (rmd != 0.0f) { - float t = perlin_signed(fscale * position); + float t = perlin_signed(fscale * p); float sum2 = sum + t * amp; return normalize ? mix(0.5f * sum / maxamp + 0.5f, 0.5f * sum2 / (maxamp + amp) + 0.5f, rmd) : mix(sum, sum2, rmd); @@ -561,28 +561,161 @@ float perlin_fractal_template( } } -float perlin_fractal( - float position, float octaves, float roughness, float lacunarity, bool normalize) +/* Explicit instantiation for Wave Texture. */ +template float perlin_fbm(float3 p, + const float detail, + const float roughness, + const float lacunarity, + const bool normalize); + +template +float perlin_multi_fractal(T p, const float detail, const float roughness, const float lacunarity) { - return perlin_fractal_template(position, octaves, roughness, lacunarity, normalize); + float value = 1.0f; + float pwr = 1.0f; + + for (int i = 0; i <= int(detail); i++) { + value *= (pwr * perlin_signed(p) + 1.0f); + pwr *= roughness; + p *= lacunarity; + } + + const float rmd = detail - floorf(detail); + if (rmd != 0.0f) { + value *= (rmd * pwr * perlin_signed(p) + 1.0f); /* correct? */ + } + + return value; } -float perlin_fractal( - float2 position, float octaves, float roughness, float lacunarity, bool normalize) +template +float perlin_hetero_terrain( + T p, const float detail, const float roughness, const float lacunarity, const float offset) { - return perlin_fractal_template(position, octaves, roughness, lacunarity, normalize); + float pwr = roughness; + + /* First unscaled octave of function; later octaves are scaled. */ + float value = offset + perlin_signed(p); + p *= lacunarity; + + for (int i = 1; i <= int(detail); i++) { + float increment = (perlin_signed(p) + offset) * pwr * value; + value += increment; + pwr *= roughness; + p *= lacunarity; + } + + const float rmd = detail - floorf(detail); + if (rmd != 0.0f) { + float increment = (perlin_signed(p) + offset) * pwr * value; + value += rmd * increment; + } + + return value; } -float perlin_fractal( - float3 position, float octaves, float roughness, float lacunarity, bool normalize) +template +float perlin_hybrid_multi_fractal(T p, + const float detail, + const float roughness, + const float lacunarity, + const float offset, + const float gain) { - return perlin_fractal_template(position, octaves, roughness, lacunarity, normalize); + float pwr = 1.0f; + float value = 0.0f; + float weight = 1.0f; + + for (int i = 0; (weight > 0.001f) && (i <= int(detail)); i++) { + if (weight > 1.0f) { + weight = 1.0f; + } + + float signal = (perlin_signed(p) + offset) * pwr; + pwr *= roughness; + value += weight * signal; + weight *= gain * signal; + p *= lacunarity; + } + + const float rmd = detail - floorf(detail); + if ((rmd != 0.0f) && (weight > 0.001f)) { + if (weight > 1.0f) { + weight = 1.0f; + } + float signal = (perlin_signed(p) + offset) * pwr; + value += rmd * weight * signal; + } + + return value; } -float perlin_fractal( - float4 position, float octaves, float roughness, float lacunarity, bool normalize) +template +float perlin_ridged_multi_fractal(T p, + const float detail, + const float roughness, + const float lacunarity, + const float offset, + const float gain) { - return perlin_fractal_template(position, octaves, roughness, lacunarity, normalize); + float pwr = roughness; + + float signal = offset - std::abs(perlin_signed(p)); + signal *= signal; + float value = signal; + float weight = 1.0f; + + for (int i = 1; i <= int(detail); i++) { + p *= lacunarity; + weight = CLAMPIS(signal * gain, 0.0f, 1.0f); + signal = offset - std::abs(perlin_signed(p)); + signal *= signal; + signal *= weight; + value += signal * pwr; + pwr *= roughness; + } + + return value; +} + +enum { + NOISE_SHD_PERLIN_MULTIFRACTAL = 0, + NOISE_SHD_PERLIN_FBM = 1, + NOISE_SHD_PERLIN_HYBRID_MULTIFRACTAL = 2, + NOISE_SHD_PERLIN_RIDGED_MULTIFRACTAL = 3, + NOISE_SHD_PERLIN_HETERO_TERRAIN = 4, +}; + +template +float perlin_select(T p, + float detail, + float roughness, + float lacunarity, + float offset, + float gain, + int type, + bool normalize) +{ + switch (type) { + case NOISE_SHD_PERLIN_MULTIFRACTAL: { + return perlin_multi_fractal(p, detail, roughness, lacunarity); + } + case NOISE_SHD_PERLIN_FBM: { + return perlin_fbm(p, detail, roughness, lacunarity, normalize); + } + case NOISE_SHD_PERLIN_HYBRID_MULTIFRACTAL: { + return perlin_hybrid_multi_fractal(p, detail, roughness, lacunarity, offset, gain); + } + case NOISE_SHD_PERLIN_RIDGED_MULTIFRACTAL: { + return perlin_ridged_multi_fractal(p, detail, roughness, lacunarity, offset, gain); + } + case NOISE_SHD_PERLIN_HETERO_TERRAIN: { + return perlin_hetero_terrain(p, detail, roughness, lacunarity, offset); + } + default: { + return 0.0; + } + } } /* The following offset functions generate random offsets to be added to @@ -646,746 +779,185 @@ BLI_INLINE float4 perlin_distortion(float4 position, float strength) perlin_signed(position + random_float4_offset(3.0f)) * strength); } -/* Positive distorted fractal perlin noise. */ +/* Distorted fractal perlin noise. */ -float perlin_fractal_distorted(float position, - float octaves, +template +float perlin_fractal_distorted(T position, + float detail, float roughness, float lacunarity, + float offset, + float gain, float distortion, + int type, bool normalize) { position += perlin_distortion(position, distortion); - return perlin_fractal(position, octaves, roughness, lacunarity, normalize); + return perlin_select(position, detail, roughness, lacunarity, offset, gain, type, normalize); } -float perlin_fractal_distorted(float2 position, - float octaves, - float roughness, - float lacunarity, - float distortion, - bool normalize) -{ - position += perlin_distortion(position, distortion); - return perlin_fractal(position, octaves, roughness, lacunarity, normalize); -} +template float perlin_fractal_distorted(float position, + float detail, + float roughness, + float lacunarity, + float offset, + float gain, + float distortion, + int type, + bool normalize); +template float perlin_fractal_distorted(float2 position, + float detail, + float roughness, + float lacunarity, + float offset, + float gain, + float distortion, + int type, + bool normalize); +template float perlin_fractal_distorted(float3 position, + float detail, + float roughness, + float lacunarity, + float offset, + float gain, + float distortion, + int type, + bool normalize); +template float perlin_fractal_distorted(float4 position, + float detail, + float roughness, + float lacunarity, + float offset, + float gain, + float distortion, + int type, + bool normalize); -float perlin_fractal_distorted(float3 position, - float octaves, - float roughness, - float lacunarity, - float distortion, - bool normalize) -{ - position += perlin_distortion(position, distortion); - return perlin_fractal(position, octaves, roughness, lacunarity, normalize); -} - -float perlin_fractal_distorted(float4 position, - float octaves, - float roughness, - float lacunarity, - float distortion, - bool normalize) -{ - position += perlin_distortion(position, distortion); - return perlin_fractal(position, octaves, roughness, lacunarity, normalize); -} - -/* Positive distorted fractal perlin noise that outputs a float3. The arbitrary seeds are for +/* Distorted fractal perlin noise that outputs a float3. The arbitrary seeds are for * compatibility with shading functions. */ float3 perlin_float3_fractal_distorted(float position, - float octaves, + float detail, float roughness, float lacunarity, + float offset, + float gain, float distortion, + int type, bool normalize) { position += perlin_distortion(position, distortion); return float3( - perlin_fractal(position, octaves, roughness, lacunarity, normalize), - perlin_fractal( - position + random_float_offset(1.0f), octaves, roughness, lacunarity, normalize), - perlin_fractal( - position + random_float_offset(2.0f), octaves, roughness, lacunarity, normalize)); + perlin_select(position, detail, roughness, lacunarity, offset, gain, type, normalize), + perlin_select(position + random_float_offset(1.0f), + detail, + roughness, + lacunarity, + offset, + gain, + type, + normalize), + perlin_select(position + random_float_offset(2.0f), + detail, + roughness, + lacunarity, + offset, + gain, + type, + normalize)); } float3 perlin_float3_fractal_distorted(float2 position, - float octaves, + float detail, float roughness, float lacunarity, + float offset, + float gain, float distortion, + int type, bool normalize) { position += perlin_distortion(position, distortion); - return float3( - perlin_fractal(position, octaves, roughness, lacunarity, normalize), - perlin_fractal( - position + random_float2_offset(2.0f), octaves, roughness, lacunarity, normalize), - perlin_fractal( - position + random_float2_offset(3.0f), octaves, roughness, lacunarity, normalize)); + return float3(perlin_select( + position, detail, roughness, lacunarity, offset, gain, type, normalize), + perlin_select(position + random_float2_offset(2.0f), + detail, + roughness, + lacunarity, + offset, + gain, + type, + normalize), + perlin_select(position + random_float2_offset(3.0f), + detail, + roughness, + lacunarity, + offset, + gain, + type, + normalize)); } float3 perlin_float3_fractal_distorted(float3 position, - float octaves, + float detail, float roughness, float lacunarity, + float offset, + float gain, float distortion, + int type, bool normalize) { position += perlin_distortion(position, distortion); - return float3( - perlin_fractal(position, octaves, roughness, lacunarity, normalize), - perlin_fractal( - position + random_float3_offset(3.0f), octaves, roughness, lacunarity, normalize), - perlin_fractal( - position + random_float3_offset(4.0f), octaves, roughness, lacunarity, normalize)); + return float3(perlin_select( + position, detail, roughness, lacunarity, offset, gain, type, normalize), + perlin_select(position + random_float3_offset(3.0f), + detail, + roughness, + lacunarity, + offset, + gain, + type, + normalize), + perlin_select(position + random_float3_offset(4.0f), + detail, + roughness, + lacunarity, + offset, + gain, + type, + normalize)); } float3 perlin_float3_fractal_distorted(float4 position, - float octaves, + float detail, float roughness, float lacunarity, + float offset, + float gain, float distortion, + int type, bool normalize) { position += perlin_distortion(position, distortion); - return float3( - perlin_fractal(position, octaves, roughness, lacunarity, normalize), - perlin_fractal( - position + random_float4_offset(4.0f), octaves, roughness, lacunarity, normalize), - perlin_fractal( - position + random_float4_offset(5.0f), octaves, roughness, lacunarity, normalize)); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Musgrave Noise - * \{ */ - -float musgrave_fBm(const float co, - const float H, - const float lacunarity, - const float octaves_unclamped) -{ - /* From "Texturing and Modelling: A procedural approach". */ - - float p = co; - float value = 0.0f; - float pwr = 1.0f; - const float pwHL = std::pow(lacunarity, -H); - const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - - 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; -} - -float musgrave_multi_fractal(const float co, - const float H, - const float lacunarity, - const float octaves_unclamped) -{ - float p = co; - float value = 1.0f; - float pwr = 1.0f; - const float pwHL = std::pow(lacunarity, -H); - const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - - 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; -} - -float musgrave_hetero_terrain(const float co, - const float H, - const float lacunarity, - const float octaves_unclamped, - const float offset) -{ - float p = co; - const float pwHL = std::pow(lacunarity, -H); - float pwr = pwHL; - const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - - /* 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; -} - -float musgrave_hybrid_multi_fractal(const float co, - const float H, - const float lacunarity, - const float octaves_unclamped, - const float offset, - const float gain) -{ - float p = co; - const float pwHL = std::pow(lacunarity, -H); - - float pwr = 1.0f; - float value = 0.0f; - float weight = 1.0f; - - const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - - for (int i = 0; (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) && (weight > 0.001f)) { - if (weight > 1.0f) { - weight = 1.0f; - } - float signal = (perlin_signed(p) + offset) * pwr; - value += rmd * weight * signal; - } - - return value; -} - -float musgrave_ridged_multi_fractal(const float co, - const float H, - const float lacunarity, - const float octaves_unclamped, - const float offset, - const float gain) -{ - float p = co; - const float pwHL = std::pow(lacunarity, -H); - float pwr = pwHL; - - float signal = offset - std::abs(perlin_signed(p)); - signal *= signal; - float value = signal; - float weight = 1.0f; - - const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - - for (int i = 1; i < int(octaves); i++) { - p *= lacunarity; - weight = CLAMPIS(signal * gain, 0.0f, 1.0f); - signal = offset - std::abs(perlin_signed(p)); - signal *= signal; - signal *= weight; - value += signal * pwr; - pwr *= pwHL; - } - - return value; -} - -float musgrave_fBm(const float2 co, - const float H, - const float lacunarity, - const float octaves_unclamped) -{ - /* From "Texturing and Modelling: A procedural approach". */ - - float2 p = co; - float value = 0.0f; - float pwr = 1.0f; - const float pwHL = std::pow(lacunarity, -H); - const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - - 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; -} - -float musgrave_multi_fractal(const float2 co, - const float H, - const float lacunarity, - const float octaves_unclamped) -{ - float2 p = co; - float value = 1.0f; - float pwr = 1.0f; - const float pwHL = std::pow(lacunarity, -H); - const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - - 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; -} - -float musgrave_hetero_terrain(const float2 co, - const float H, - const float lacunarity, - const float octaves_unclamped, - const float offset) -{ - float2 p = co; - const float pwHL = std::pow(lacunarity, -H); - float pwr = pwHL; - - /* First unscaled octave of function; later octaves are scaled. */ - float value = offset + perlin_signed(p); - p *= lacunarity; - - const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - - 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; -} - -float musgrave_hybrid_multi_fractal(const float2 co, - const float H, - const float lacunarity, - const float octaves_unclamped, - const float offset, - const float gain) -{ - float2 p = co; - const float pwHL = std::pow(lacunarity, -H); - - float pwr = 1.0f; - float value = 0.0f; - float weight = 1.0f; - - const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - - for (int i = 0; (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) && (weight > 0.001f)) { - if (weight > 1.0f) { - weight = 1.0f; - } - float signal = (perlin_signed(p) + offset) * pwr; - value += rmd * weight * signal; - } - - return value; -} - -float musgrave_ridged_multi_fractal(const float2 co, - const float H, - const float lacunarity, - const float octaves_unclamped, - const float offset, - const float gain) -{ - float2 p = co; - const float pwHL = std::pow(lacunarity, -H); - float pwr = pwHL; - - float signal = offset - std::abs(perlin_signed(p)); - signal *= signal; - float value = signal; - float weight = 1.0f; - - const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - - for (int i = 1; i < int(octaves); i++) { - p *= lacunarity; - weight = CLAMPIS(signal * gain, 0.0f, 1.0f); - signal = offset - std::abs(perlin_signed(p)); - signal *= signal; - signal *= weight; - value += signal * pwr; - pwr *= pwHL; - } - - return value; -} - -float musgrave_fBm(const float3 co, - const float H, - const float lacunarity, - const float octaves_unclamped) -{ - /* From "Texturing and Modelling: A procedural approach". */ - - float3 p = co; - float value = 0.0f; - float pwr = 1.0f; - const float pwHL = std::pow(lacunarity, -H); - - const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - - 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; -} - -float musgrave_multi_fractal(const float3 co, - const float H, - const float lacunarity, - const float octaves_unclamped) -{ - float3 p = co; - float value = 1.0f; - float pwr = 1.0f; - const float pwHL = std::pow(lacunarity, -H); - - const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - - 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; -} - -float musgrave_hetero_terrain(const float3 co, - const float H, - const float lacunarity, - const float octaves_unclamped, - const float offset) -{ - float3 p = co; - const float pwHL = std::pow(lacunarity, -H); - float pwr = pwHL; - - /* first unscaled octave of function; later octaves are scaled */ - float value = offset + perlin_signed(p); - p *= lacunarity; - - const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - - 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; -} - -float musgrave_hybrid_multi_fractal(const float3 co, - const float H, - const float lacunarity, - const float octaves_unclamped, - const float offset, - const float gain) -{ - float3 p = co; - const float pwHL = std::pow(lacunarity, -H); - - float pwr = 1.0f; - float value = 0.0f; - float weight = 1.0f; - - const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - - for (int i = 0; (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) && (weight > 0.001f)) { - if (weight > 1.0f) { - weight = 1.0f; - } - float signal = (perlin_signed(p) + offset) * pwr; - value += rmd * weight * signal; - } - - return value; -} - -float musgrave_ridged_multi_fractal(const float3 co, - const float H, - const float lacunarity, - const float octaves_unclamped, - const float offset, - const float gain) -{ - float3 p = co; - const float pwHL = std::pow(lacunarity, -H); - float pwr = pwHL; - - float signal = offset - std::abs(perlin_signed(p)); - signal *= signal; - float value = signal; - float weight = 1.0f; - - const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - - for (int i = 1; i < int(octaves); i++) { - p *= lacunarity; - weight = CLAMPIS(signal * gain, 0.0f, 1.0f); - signal = offset - std::abs(perlin_signed(p)); - signal *= signal; - signal *= weight; - value += signal * pwr; - pwr *= pwHL; - } - - return value; -} - -float musgrave_fBm(const float4 co, - const float H, - const float lacunarity, - const float octaves_unclamped) -{ - /* From "Texturing and Modelling: A procedural approach". */ - - float4 p = co; - float value = 0.0f; - float pwr = 1.0f; - const float pwHL = std::pow(lacunarity, -H); - - const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - - 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; -} - -float musgrave_multi_fractal(const float4 co, - const float H, - const float lacunarity, - const float octaves_unclamped) -{ - float4 p = co; - float value = 1.0f; - float pwr = 1.0f; - const float pwHL = std::pow(lacunarity, -H); - - const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - - 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; -} - -float musgrave_hetero_terrain(const float4 co, - const float H, - const float lacunarity, - const float octaves_unclamped, - const float offset) -{ - float4 p = co; - const float pwHL = std::pow(lacunarity, -H); - float pwr = pwHL; - - /* first unscaled octave of function; later octaves are scaled */ - float value = offset + perlin_signed(p); - p *= lacunarity; - - const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - - 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; -} - -float musgrave_hybrid_multi_fractal(const float4 co, - const float H, - const float lacunarity, - const float octaves_unclamped, - const float offset, - const float gain) -{ - float4 p = co; - const float pwHL = std::pow(lacunarity, -H); - - float pwr = 1.0f; - float value = 0.0f; - float weight = 1.0f; - - const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - - for (int i = 0; (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) && (weight > 0.001f)) { - if (weight > 1.0f) { - weight = 1.0f; - } - float signal = (perlin_signed(p) + offset) * pwr; - value += rmd * weight * signal; - } - - return value; -} - -float musgrave_ridged_multi_fractal(const float4 co, - const float H, - const float lacunarity, - const float octaves_unclamped, - const float offset, - const float gain) -{ - float4 p = co; - const float pwHL = std::pow(lacunarity, -H); - float pwr = pwHL; - - float signal = offset - std::abs(perlin_signed(p)); - signal *= signal; - float value = signal; - float weight = 1.0f; - - const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - - for (int i = 1; i < int(octaves); i++) { - p *= lacunarity; - weight = CLAMPIS(signal * gain, 0.0f, 1.0f); - signal = offset - std::abs(perlin_signed(p)); - signal *= signal; - signal *= weight; - value += signal * pwr; - pwr *= pwHL; - } - - return value; + return float3(perlin_select( + position, detail, roughness, lacunarity, offset, gain, type, normalize), + perlin_select(position + random_float4_offset(4.0f), + detail, + roughness, + lacunarity, + offset, + gain, + type, + normalize), + perlin_select(position + random_float4_offset(5.0f), + detail, + roughness, + lacunarity, + offset, + gain, + type, + normalize)); } /** \} */ diff --git a/source/blender/blenloader/intern/versioning_260.cc b/source/blender/blenloader/intern/versioning_260.cc index 415c28ded92..2e39e8eb399 100644 --- a/source/blender/blenloader/intern/versioning_260.cc +++ b/source/blender/blenloader/intern/versioning_260.cc @@ -614,7 +614,7 @@ static const char *node_get_static_idname(int type, int treetype) return "ShaderNodeTexMagic"; case SH_NODE_TEX_WAVE: return "ShaderNodeTexWave"; - case SH_NODE_TEX_MUSGRAVE: + case SH_NODE_TEX_MUSGRAVE_DEPRECATED: return "ShaderNodeTexMusgrave"; case SH_NODE_TEX_VORONOI: return "ShaderNodeTexVoronoi"; diff --git a/source/blender/blenloader/intern/versioning_280.cc b/source/blender/blenloader/intern/versioning_280.cc index d1b0c1694a4..46be4aa6a01 100644 --- a/source/blender/blenloader/intern/versioning_280.cc +++ b/source/blender/blenloader/intern/versioning_280.cc @@ -1853,7 +1853,7 @@ static void update_mapping_node_inputs_and_properties(bNodeTree *ntree) static void update_musgrave_node_dimensions(bNodeTree *ntree) { LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { - if (node->type == SH_NODE_TEX_MUSGRAVE && node->storage) { + if (node->type == SH_NODE_TEX_MUSGRAVE_DEPRECATED && node->storage) { NodeTexMusgrave *tex = (NodeTexMusgrave *)node->storage; tex->dimensions = 3; } @@ -1867,7 +1867,7 @@ static void update_musgrave_node_dimensions(bNodeTree *ntree) 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->fromnode && link->fromnode->type == SH_NODE_TEX_MUSGRAVE_DEPRECATED) { if (link->fromsock->type == SOCK_RGBA) { link->fromsock = link->fromsock->next; } diff --git a/source/blender/blenloader/intern/versioning_400.cc b/source/blender/blenloader/intern/versioning_400.cc index 43ecc2fcc5a..8a7fb4f5d67 100644 --- a/source/blender/blenloader/intern/versioning_400.cc +++ b/source/blender/blenloader/intern/versioning_400.cc @@ -692,6 +692,447 @@ static void version_principled_bsdf_sheen(bNodeTree *ntree) } } +static void versioning_update_noise_texture_node(bNodeTree *ntree) +{ + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + if (node->type != SH_NODE_TEX_NOISE) { + continue; + } + + (static_cast(node->storage))->type = SHD_NOISE_FBM; + + bNodeSocket *roughness_socket = nodeFindSocket(node, SOCK_IN, "Roughness"); + if (roughness_socket == nullptr) { + /* Noise Texture node was created before the Roughness input was added. */ + continue; + } + + float *roughness = version_cycles_node_socket_float_value(roughness_socket); + + bNodeLink *roughness_link = nullptr; + bNode *roughness_from_node = nullptr; + bNodeSocket *roughness_from_socket = nullptr; + + LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) { + /* Find links, nodes and sockets. */ + if (link->tosock == roughness_socket) { + roughness_link = link; + roughness_from_node = link->fromnode; + roughness_from_socket = link->fromsock; + } + } + + if (roughness_link != nullptr) { + /* Add Clamp node before Roughness input. */ + + bNode *clamp_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_CLAMP); + clamp_node->parent = node->parent; + clamp_node->custom1 = NODE_CLAMP_MINMAX; + clamp_node->locx = node->locx; + clamp_node->locy = node->locy - 300.0f; + clamp_node->flag |= NODE_HIDDEN; + bNodeSocket *clamp_socket_value = nodeFindSocket(clamp_node, SOCK_IN, "Value"); + bNodeSocket *clamp_socket_min = nodeFindSocket(clamp_node, SOCK_IN, "Min"); + bNodeSocket *clamp_socket_max = nodeFindSocket(clamp_node, SOCK_IN, "Max"); + bNodeSocket *clamp_socket_out = nodeFindSocket(clamp_node, SOCK_OUT, "Result"); + + *version_cycles_node_socket_float_value(clamp_socket_min) = 0.0f; + *version_cycles_node_socket_float_value(clamp_socket_max) = 1.0f; + + nodeRemLink(ntree, roughness_link); + nodeAddLink( + ntree, roughness_from_node, roughness_from_socket, clamp_node, clamp_socket_value); + nodeAddLink(ntree, clamp_node, clamp_socket_out, node, roughness_socket); + } + else { + *roughness = std::clamp(*roughness, 0.0f, 1.0f); + } + } + + version_socket_update_is_used(ntree); +} + +static void versioning_replace_musgrave_texture_node(bNodeTree *ntree) +{ + version_node_input_socket_name(ntree, SH_NODE_TEX_MUSGRAVE_DEPRECATED, "Dimension", "Roughness"); + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + if (node->type != SH_NODE_TEX_MUSGRAVE_DEPRECATED) { + continue; + } + + STRNCPY(node->idname, "ShaderNodeTexNoise"); + node->type = SH_NODE_TEX_NOISE; + NodeTexNoise *data = MEM_cnew(__func__); + data->base = (static_cast(node->storage))->base; + data->dimensions = (static_cast(node->storage))->dimensions; + data->normalize = false; + data->type = (static_cast(node->storage))->musgrave_type; + MEM_freeN(node->storage); + node->storage = data; + + bNodeLink *detail_link = nullptr; + bNode *detail_from_node = nullptr; + bNodeSocket *detail_from_socket = nullptr; + + bNodeLink *roughness_link = nullptr; + bNode *roughness_from_node = nullptr; + bNodeSocket *roughness_from_socket = nullptr; + + bNodeLink *lacunarity_link = nullptr; + bNode *lacunarity_from_node = nullptr; + bNodeSocket *lacunarity_from_socket = nullptr; + + LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) { + /* Find links, nodes and sockets. */ + if (link->tonode == node) { + if (STREQ(link->tosock->identifier, "Detail")) { + detail_link = link; + detail_from_node = link->fromnode; + detail_from_socket = link->fromsock; + } + if (STREQ(link->tosock->identifier, "Roughness")) { + roughness_link = link; + roughness_from_node = link->fromnode; + roughness_from_socket = link->fromsock; + } + if (STREQ(link->tosock->identifier, "Lacunarity")) { + lacunarity_link = link; + lacunarity_from_node = link->fromnode; + lacunarity_from_socket = link->fromsock; + } + } + } + + uint8_t noise_type = (static_cast(node->storage))->type; + float locy_offset = 0.0f; + + bNodeSocket *fac_socket = nodeFindSocket(node, SOCK_OUT, "Fac"); + /* Clear label because Musgrave output socket label is set to "Height" instead of "Fac". */ + fac_socket->label[0] = '\0'; + + bNodeSocket *detail_socket = nodeFindSocket(node, SOCK_IN, "Detail"); + float *detail = version_cycles_node_socket_float_value(detail_socket); + + if (detail_link != nullptr) { + locy_offset -= 80.0f; + + /* Add Minimum Math node and Subtract Math node before Detail input. */ + + bNode *min_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH); + min_node->parent = node->parent; + min_node->custom1 = NODE_MATH_MINIMUM; + min_node->locx = node->locx; + min_node->locy = node->locy - 320.0f; + min_node->flag |= NODE_HIDDEN; + bNodeSocket *min_socket_A = static_cast(BLI_findlink(&min_node->inputs, 0)); + bNodeSocket *min_socket_B = static_cast(BLI_findlink(&min_node->inputs, 1)); + bNodeSocket *min_socket_out = nodeFindSocket(min_node, SOCK_OUT, "Value"); + + bNode *sub1_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH); + sub1_node->parent = node->parent; + sub1_node->custom1 = NODE_MATH_SUBTRACT; + sub1_node->locx = node->locx; + sub1_node->locy = node->locy - 360.0f; + sub1_node->flag |= NODE_HIDDEN; + bNodeSocket *sub1_socket_A = static_cast(BLI_findlink(&sub1_node->inputs, 0)); + bNodeSocket *sub1_socket_B = static_cast(BLI_findlink(&sub1_node->inputs, 1)); + bNodeSocket *sub1_socket_out = nodeFindSocket(sub1_node, SOCK_OUT, "Value"); + + *version_cycles_node_socket_float_value(min_socket_B) = 14.0f; + *version_cycles_node_socket_float_value(sub1_socket_B) = 1.0f; + + nodeRemLink(ntree, detail_link); + nodeAddLink(ntree, detail_from_node, detail_from_socket, sub1_node, sub1_socket_A); + nodeAddLink(ntree, sub1_node, sub1_socket_out, min_node, min_socket_A); + nodeAddLink(ntree, min_node, min_socket_out, node, detail_socket); + + if ((noise_type == SHD_NOISE_RIDGED_MULTIFRACTAL) || + (noise_type == SHD_NOISE_HETERO_TERRAIN)) { + locy_offset -= 40.0f; + + /* Add Greater Than Math node before Subtract Math node. */ + + bNode *greater_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH); + greater_node->parent = node->parent; + greater_node->custom1 = NODE_MATH_GREATER_THAN; + greater_node->locx = node->locx; + greater_node->locy = node->locy - 400.0f; + greater_node->flag |= NODE_HIDDEN; + bNodeSocket *greater_socket_A = static_cast( + BLI_findlink(&greater_node->inputs, 0)); + bNodeSocket *greater_socket_B = static_cast( + BLI_findlink(&greater_node->inputs, 1)); + bNodeSocket *greater_socket_out = nodeFindSocket(greater_node, SOCK_OUT, "Value"); + + *version_cycles_node_socket_float_value(greater_socket_B) = 1.0f; + + nodeAddLink(ntree, detail_from_node, detail_from_socket, greater_node, greater_socket_A); + nodeAddLink(ntree, greater_node, greater_socket_out, sub1_node, sub1_socket_B); + } + else { + /* Add Clamp node and Multiply Math node behind Fac output. */ + + bNode *clamp_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_CLAMP); + clamp_node->parent = node->parent; + clamp_node->custom1 = NODE_CLAMP_MINMAX; + clamp_node->locx = node->locx; + clamp_node->locy = node->locy + 40.0f; + clamp_node->flag |= NODE_HIDDEN; + bNodeSocket *clamp_socket_value = nodeFindSocket(clamp_node, SOCK_IN, "Value"); + bNodeSocket *clamp_socket_min = nodeFindSocket(clamp_node, SOCK_IN, "Min"); + bNodeSocket *clamp_socket_max = nodeFindSocket(clamp_node, SOCK_IN, "Max"); + bNodeSocket *clamp_socket_out = nodeFindSocket(clamp_node, SOCK_OUT, "Result"); + + bNode *mul_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH); + mul_node->parent = node->parent; + mul_node->custom1 = NODE_MATH_MULTIPLY; + mul_node->locx = node->locx; + mul_node->locy = node->locy + 80.0f; + mul_node->flag |= NODE_HIDDEN; + bNodeSocket *mul_socket_A = static_cast(BLI_findlink(&mul_node->inputs, 0)); + bNodeSocket *mul_socket_B = static_cast(BLI_findlink(&mul_node->inputs, 1)); + bNodeSocket *mul_socket_out = nodeFindSocket(mul_node, SOCK_OUT, "Value"); + + *version_cycles_node_socket_float_value(clamp_socket_min) = 0.0f; + *version_cycles_node_socket_float_value(clamp_socket_max) = 1.0f; + + if (noise_type == SHD_NOISE_MULTIFRACTAL) { + /* Add Subtract Math node and Add Math node after Multiply Math node. */ + + bNode *sub2_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH); + sub2_node->parent = node->parent; + sub2_node->custom1 = NODE_MATH_SUBTRACT; + sub2_node->custom2 = SHD_MATH_CLAMP; + sub2_node->locx = node->locx; + sub2_node->locy = node->locy + 120.0f; + sub2_node->flag |= NODE_HIDDEN; + bNodeSocket *sub2_socket_A = static_cast( + BLI_findlink(&sub2_node->inputs, 0)); + bNodeSocket *sub2_socket_B = static_cast( + BLI_findlink(&sub2_node->inputs, 1)); + bNodeSocket *sub2_socket_out = nodeFindSocket(sub2_node, SOCK_OUT, "Value"); + + bNode *add_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH); + add_node->parent = node->parent; + add_node->custom1 = NODE_MATH_ADD; + add_node->locx = node->locx; + add_node->locy = node->locy + 160.0f; + add_node->flag |= NODE_HIDDEN; + bNodeSocket *add_socket_A = static_cast( + BLI_findlink(&add_node->inputs, 0)); + bNodeSocket *add_socket_B = static_cast( + BLI_findlink(&add_node->inputs, 1)); + bNodeSocket *add_socket_out = nodeFindSocket(add_node, SOCK_OUT, "Value"); + + *version_cycles_node_socket_float_value(sub2_socket_A) = 1.0f; + + LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) { + if (link->fromsock == fac_socket) { + nodeAddLink(ntree, add_node, add_socket_out, link->tonode, link->tosock); + nodeRemLink(ntree, link); + } + } + + nodeAddLink(ntree, mul_node, mul_socket_out, add_node, add_socket_A); + nodeAddLink(ntree, detail_from_node, detail_from_socket, sub2_node, sub2_socket_B); + nodeAddLink(ntree, sub2_node, sub2_socket_out, add_node, add_socket_B); + } + else { + LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) { + if (link->fromsock == fac_socket) { + nodeAddLink(ntree, mul_node, mul_socket_out, link->tonode, link->tosock); + nodeRemLink(ntree, link); + } + } + } + + nodeAddLink(ntree, node, fac_socket, mul_node, mul_socket_A); + nodeAddLink(ntree, detail_from_node, detail_from_socket, clamp_node, clamp_socket_value); + nodeAddLink(ntree, clamp_node, clamp_socket_out, mul_node, mul_socket_B); + } + } + else { + if (*detail < 1.0f) { + if ((noise_type != SHD_NOISE_RIDGED_MULTIFRACTAL) && + (noise_type != SHD_NOISE_HETERO_TERRAIN)) { + /* Add Multiply Math node behind Fac output. */ + + bNode *mul_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH); + mul_node->parent = node->parent; + mul_node->custom1 = NODE_MATH_MULTIPLY; + mul_node->locx = node->locx; + mul_node->locy = node->locy + 40.0f; + mul_node->flag |= NODE_HIDDEN; + bNodeSocket *mul_socket_A = static_cast( + BLI_findlink(&mul_node->inputs, 0)); + bNodeSocket *mul_socket_B = static_cast( + BLI_findlink(&mul_node->inputs, 1)); + bNodeSocket *mul_socket_out = nodeFindSocket(mul_node, SOCK_OUT, "Value"); + + *version_cycles_node_socket_float_value(mul_socket_B) = *detail; + + if (noise_type == SHD_NOISE_MULTIFRACTAL) { + /* Add Add Math node after Multiply Math node. */ + + bNode *add_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH); + add_node->parent = node->parent; + add_node->custom1 = NODE_MATH_ADD; + add_node->locx = node->locx; + add_node->locy = node->locy + 80.0f; + add_node->flag |= NODE_HIDDEN; + bNodeSocket *add_socket_A = static_cast( + BLI_findlink(&add_node->inputs, 0)); + bNodeSocket *add_socket_B = static_cast( + BLI_findlink(&add_node->inputs, 1)); + bNodeSocket *add_socket_out = nodeFindSocket(add_node, SOCK_OUT, "Value"); + + *version_cycles_node_socket_float_value(add_socket_B) = 1.0f - *detail; + + LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) { + if (link->fromsock == fac_socket) { + nodeAddLink(ntree, add_node, add_socket_out, link->tonode, link->tosock); + nodeRemLink(ntree, link); + } + } + + nodeAddLink(ntree, mul_node, mul_socket_out, add_node, add_socket_A); + } + else { + LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) { + if (link->fromsock == fac_socket) { + nodeAddLink(ntree, mul_node, mul_socket_out, link->tonode, link->tosock); + nodeRemLink(ntree, link); + } + } + } + + nodeAddLink(ntree, node, fac_socket, mul_node, mul_socket_A); + + *detail = 0.0f; + } + } + else { + *detail = std::fminf(*detail - 1.0f, 14.0f); + } + } + + bNodeSocket *roughness_socket = nodeFindSocket(node, SOCK_IN, "Roughness"); + float *roughness = version_cycles_node_socket_float_value(roughness_socket); + bNodeSocket *lacunarity_socket = nodeFindSocket(node, SOCK_IN, "Lacunarity"); + float *lacunarity = version_cycles_node_socket_float_value(lacunarity_socket); + + *roughness = std::fmaxf(*roughness, 1e-5f); + *lacunarity = std::fmaxf(*lacunarity, 1e-5f); + + if (roughness_link != nullptr) { + /* Add Maximum Math node after output of roughness_from_node. Add Multiply Math node and + * Power Math node before Roughness input. */ + + bNode *max1_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH); + max1_node->parent = node->parent; + max1_node->custom1 = NODE_MATH_MAXIMUM; + max1_node->locx = node->locx; + max1_node->locy = node->locy - 400.0f + locy_offset; + max1_node->flag |= NODE_HIDDEN; + bNodeSocket *max1_socket_A = static_cast(BLI_findlink(&max1_node->inputs, 0)); + bNodeSocket *max1_socket_B = static_cast(BLI_findlink(&max1_node->inputs, 1)); + bNodeSocket *max1_socket_out = nodeFindSocket(max1_node, SOCK_OUT, "Value"); + + bNode *mul_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH); + mul_node->parent = node->parent; + mul_node->custom1 = NODE_MATH_MULTIPLY; + mul_node->locx = node->locx; + mul_node->locy = node->locy - 360.0f + locy_offset; + mul_node->flag |= NODE_HIDDEN; + bNodeSocket *mul_socket_A = static_cast(BLI_findlink(&mul_node->inputs, 0)); + bNodeSocket *mul_socket_B = static_cast(BLI_findlink(&mul_node->inputs, 1)); + bNodeSocket *mul_socket_out = nodeFindSocket(mul_node, SOCK_OUT, "Value"); + + bNode *pow_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH); + pow_node->parent = node->parent; + pow_node->custom1 = NODE_MATH_POWER; + pow_node->locx = node->locx; + pow_node->locy = node->locy - 320.0f + locy_offset; + pow_node->flag |= NODE_HIDDEN; + bNodeSocket *pow_socket_A = static_cast(BLI_findlink(&pow_node->inputs, 0)); + bNodeSocket *pow_socket_B = static_cast(BLI_findlink(&pow_node->inputs, 1)); + bNodeSocket *pow_socket_out = nodeFindSocket(pow_node, SOCK_OUT, "Value"); + + *version_cycles_node_socket_float_value(max1_socket_B) = -1e-5f; + *version_cycles_node_socket_float_value(mul_socket_B) = -1.0f; + *version_cycles_node_socket_float_value(pow_socket_A) = *lacunarity; + + nodeRemLink(ntree, roughness_link); + nodeAddLink(ntree, roughness_from_node, roughness_from_socket, max1_node, max1_socket_A); + nodeAddLink(ntree, max1_node, max1_socket_out, mul_node, mul_socket_A); + nodeAddLink(ntree, mul_node, mul_socket_out, pow_node, pow_socket_B); + nodeAddLink(ntree, pow_node, pow_socket_out, node, roughness_socket); + + if (lacunarity_link != nullptr) { + /* Add Maximum Math node after output of lacunarity_from_node. */ + + bNode *max2_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH); + max2_node->parent = node->parent; + max2_node->custom1 = NODE_MATH_MAXIMUM; + max2_node->locx = node->locx; + max2_node->locy = node->locy - 440.0f + locy_offset; + max2_node->flag |= NODE_HIDDEN; + bNodeSocket *max2_socket_A = static_cast( + BLI_findlink(&max2_node->inputs, 0)); + bNodeSocket *max2_socket_B = static_cast( + BLI_findlink(&max2_node->inputs, 1)); + bNodeSocket *max2_socket_out = nodeFindSocket(max2_node, SOCK_OUT, "Value"); + + *version_cycles_node_socket_float_value(max2_socket_B) = -1e-5f; + + nodeRemLink(ntree, lacunarity_link); + nodeAddLink(ntree, lacunarity_from_node, lacunarity_from_socket, max2_node, max2_socket_A); + nodeAddLink(ntree, max2_node, max2_socket_out, pow_node, pow_socket_A); + nodeAddLink(ntree, max2_node, max2_socket_out, node, lacunarity_socket); + } + } + else if ((lacunarity_link != nullptr) && (roughness_link == nullptr)) { + /* Add Maximum Math node after output of lacunarity_from_node. Add Power Math node before + * Roughness input. */ + + bNode *max2_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH); + max2_node->parent = node->parent; + max2_node->custom1 = NODE_MATH_MAXIMUM; + max2_node->locx = node->locx; + max2_node->locy = node->locy - 360.0f + locy_offset; + max2_node->flag |= NODE_HIDDEN; + bNodeSocket *max2_socket_A = static_cast(BLI_findlink(&max2_node->inputs, 0)); + bNodeSocket *max2_socket_B = static_cast(BLI_findlink(&max2_node->inputs, 1)); + bNodeSocket *max2_socket_out = nodeFindSocket(max2_node, SOCK_OUT, "Value"); + + bNode *pow_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH); + pow_node->parent = node->parent; + pow_node->custom1 = NODE_MATH_POWER; + pow_node->locx = node->locx; + pow_node->locy = node->locy - 320.0f + locy_offset; + pow_node->flag |= NODE_HIDDEN; + bNodeSocket *pow_socket_A = static_cast(BLI_findlink(&pow_node->inputs, 0)); + bNodeSocket *pow_socket_B = static_cast(BLI_findlink(&pow_node->inputs, 1)); + bNodeSocket *pow_socket_out = nodeFindSocket(pow_node, SOCK_OUT, "Value"); + + *version_cycles_node_socket_float_value(max2_socket_B) = -1e-5f; + *version_cycles_node_socket_float_value(pow_socket_A) = *lacunarity; + *version_cycles_node_socket_float_value(pow_socket_B) = -(*roughness); + + nodeRemLink(ntree, lacunarity_link); + nodeAddLink(ntree, lacunarity_from_node, lacunarity_from_socket, max2_node, max2_socket_A); + nodeAddLink(ntree, max2_node, max2_socket_out, pow_node, pow_socket_A); + nodeAddLink(ntree, max2_node, max2_socket_out, node, lacunarity_socket); + nodeAddLink(ntree, pow_node, pow_socket_out, node, roughness_socket); + } + else { + *roughness = std::pow(*lacunarity, -(*roughness)); + } + } + + version_socket_update_is_used(ntree); +} + /* Convert subsurface inputs on the Principled BSDF. */ static void version_principled_bsdf_subsurface(bNodeTree *ntree) { @@ -1943,6 +2384,20 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain) } } + if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 4)) { + FOREACH_NODETREE_BEGIN (bmain, ntree, id) { + if (ntree->type != NTREE_CUSTOM) { + /* versioning_update_noise_texture_node must be done before + * versioning_replace_musgrave_texture_node. */ + versioning_update_noise_texture_node(ntree); + + /* Convert Musgrave Texture nodes to Noise Texture nodes. */ + versioning_replace_musgrave_texture_node(ntree); + } + } + FOREACH_NODETREE_END; + } + if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 5)) { /* Unify Material::blend_shadow and Cycles.use_transparent_shadows into the * Material::blend_flag. */ diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index b67eefcc71b..383347b9118 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -553,7 +553,6 @@ set(GLSL_SRC shaders/material/gpu_shader_material_tex_gradient.glsl shaders/material/gpu_shader_material_tex_image.glsl shaders/material/gpu_shader_material_tex_magic.glsl - shaders/material/gpu_shader_material_tex_musgrave.glsl shaders/material/gpu_shader_material_tex_noise.glsl shaders/material/gpu_shader_material_tex_sky.glsl shaders/material/gpu_shader_material_texture_coordinates.glsl diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_fractal_noise.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_fractal_noise.glsl index 67319fc7abe..34cbecc2487 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_fractal_noise.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_fractal_noise.glsl @@ -5,114 +5,198 @@ #pragma BLENDER_REQUIRE(gpu_shader_common_hash.glsl) #pragma BLENDER_REQUIRE(gpu_shader_material_noise.glsl) -/* The fractal_noise functions are all exactly the same except for the input type. */ -float fractal_noise(float p, float octaves, float roughness, float lacunarity, bool normalize) -{ - float fscale = 1.0; - float amp = 1.0; - float maxamp = 0.0; - float sum = 0.0; - octaves = clamp(octaves, 0.0, 15.0); - int n = int(octaves); - for (int i = 0; i <= n; i++) { - float t = snoise(fscale * p); - sum += t * amp; - maxamp += amp; - amp *= clamp(roughness, 0.0, 1.0); - fscale *= lacunarity; +#define NOISE_FBM(T) \ + float noise_fbm(T co, \ + float detail, \ + float roughness, \ + float lacunarity, \ + float offset, \ + float gain, \ + bool normalize) \ + { \ + T p = co; \ + float fscale = 1.0; \ + float amp = 1.0; \ + float maxamp = 0.0; \ + float sum = 0.0; \ +\ + for (int i = 0; i <= int(detail); i++) { \ + float t = snoise(fscale * p); \ + sum += t * amp; \ + maxamp += amp; \ + amp *= roughness; \ + fscale *= lacunarity; \ + } \ + float rmd = detail - floor(detail); \ + if (rmd != 0.0) { \ + float t = snoise(fscale * p); \ + float sum2 = sum + t * amp; \ + return normalize ? mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) : \ + mix(sum, sum2, rmd); \ + } \ + else { \ + return normalize ? 0.5 * sum / maxamp + 0.5 : sum; \ + } \ } - float rmd = octaves - floor(octaves); - if (rmd != 0.0) { - float t = snoise(fscale * p); - float sum2 = sum + t * amp; - return normalize ? mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) : - mix(sum, sum2, rmd); - } - else { - return normalize ? 0.5 * sum / maxamp + 0.5 : sum; - } -} -/* The fractal_noise functions are all exactly the same except for the input type. */ -float fractal_noise(vec2 p, float octaves, float roughness, float lacunarity, bool normalize) -{ - float fscale = 1.0; - float amp = 1.0; - float maxamp = 0.0; - float sum = 0.0; - octaves = clamp(octaves, 0.0, 15.0); - int n = int(octaves); - for (int i = 0; i <= n; i++) { - float t = snoise(fscale * p); - sum += t * amp; - maxamp += amp; - amp *= clamp(roughness, 0.0, 1.0); - fscale *= lacunarity; +#define NOISE_MULTI_FRACTAL(T) \ + float noise_multi_fractal(T co, \ + float detail, \ + float roughness, \ + float lacunarity, \ + float offset, \ + float gain, \ + bool normalize) \ + { \ + T p = co; \ + float value = 1.0; \ + float pwr = 1.0; \ +\ + for (int i = 0; i <= int(detail); i++) { \ + value *= (pwr * snoise(p) + 1.0); \ + pwr *= roughness; \ + p *= lacunarity; \ + } \ +\ + float rmd = detail - floor(detail); \ + if (rmd != 0.0) { \ + value *= (rmd * pwr * snoise(p) + 1.0); /* correct? */ \ + } \ +\ + return value; \ } - float rmd = octaves - floor(octaves); - if (rmd != 0.0) { - float t = snoise(fscale * p); - float sum2 = sum + t * amp; - return normalize ? mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) : - mix(sum, sum2, rmd); - } - else { - return normalize ? 0.5 * sum / maxamp + 0.5 : sum; - } -} -/* The fractal_noise functions are all exactly the same except for the input type. */ -float fractal_noise(vec3 p, float octaves, float roughness, float lacunarity, bool normalize) -{ - float fscale = 1.0; - float amp = 1.0; - float maxamp = 0.0; - float sum = 0.0; - octaves = clamp(octaves, 0.0, 15.0); - int n = int(octaves); - for (int i = 0; i <= n; i++) { - float t = snoise(fscale * p); - sum += t * amp; - maxamp += amp; - amp *= clamp(roughness, 0.0, 1.0); - fscale *= lacunarity; +#define NOISE_HETERO_TERRAIN(T) \ + float noise_hetero_terrain(T co, \ + float detail, \ + float roughness, \ + float lacunarity, \ + float offset, \ + float gain, \ + bool normalize) \ + { \ + T p = co; \ + float pwr = roughness; \ +\ + /* first unscaled octave of function; later octaves are scaled */ \ + float value = offset + snoise(p); \ + p *= lacunarity; \ +\ + for (int i = 1; i <= int(detail); i++) { \ + float increment = (snoise(p) + offset) * pwr * value; \ + value += increment; \ + pwr *= roughness; \ + p *= lacunarity; \ + } \ +\ + float rmd = detail - floor(detail); \ + if (rmd != 0.0) { \ + float increment = (snoise(p) + offset) * pwr * value; \ + value += rmd * increment; \ + } \ +\ + return value; \ } - float rmd = octaves - floor(octaves); - if (rmd != 0.0) { - float t = snoise(fscale * p); - float sum2 = sum + t * amp; - return normalize ? mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) : - mix(sum, sum2, rmd); - } - else { - return normalize ? 0.5 * sum / maxamp + 0.5 : sum; - } -} -/* The fractal_noise functions are all exactly the same except for the input type. */ -float fractal_noise(vec4 p, float octaves, float roughness, float lacunarity, bool normalize) -{ - float fscale = 1.0; - float amp = 1.0; - float maxamp = 0.0; - float sum = 0.0; - octaves = clamp(octaves, 0.0, 15.0); - int n = int(octaves); - for (int i = 0; i <= n; i++) { - float t = snoise(fscale * p); - sum += t * amp; - maxamp += amp; - amp *= clamp(roughness, 0.0, 1.0); - fscale *= lacunarity; +#define NOISE_HYBRID_MULTI_FRACTAL(T) \ + float noise_hybrid_multi_fractal(T co, \ + float detail, \ + float roughness, \ + float lacunarity, \ + float offset, \ + float gain, \ + bool normalize) \ + { \ + T p = co; \ + float pwr = 1.0; \ + float value = 0.0; \ + float weight = 1.0; \ +\ + for (int i = 0; (weight > 0.001) && (i <= int(detail)); i++) { \ + if (weight > 1.0) { \ + weight = 1.0; \ + } \ +\ + float signal = (snoise(p) + offset) * pwr; \ + pwr *= roughness; \ + value += weight * signal; \ + weight *= gain * signal; \ + p *= lacunarity; \ + } \ +\ + float rmd = detail - floor(detail); \ + if ((rmd != 0.0) && (weight > 0.001)) { \ + if (weight > 1.0) { \ + weight = 1.0; \ + } \ + float signal = (snoise(p) + offset) * pwr; \ + value += rmd * weight * signal; \ + } \ +\ + return value; \ } - float rmd = octaves - floor(octaves); - if (rmd != 0.0) { - float t = snoise(fscale * p); - float sum2 = sum + t * amp; - return normalize ? mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) : - mix(sum, sum2, rmd); + +#define NOISE_RIDGED_MULTI_FRACTAL(T) \ + float noise_ridged_multi_fractal(T co, \ + float detail, \ + float roughness, \ + float lacunarity, \ + float offset, \ + float gain, \ + bool normalize) \ + { \ + T p = co; \ + float pwr = roughness; \ +\ + float signal = offset - abs(snoise(p)); \ + signal *= signal; \ + float value = signal; \ + float weight = 1.0; \ +\ + for (int i = 1; i <= int(detail); i++) { \ + p *= lacunarity; \ + weight = clamp(signal * gain, 0.0, 1.0); \ + signal = offset - abs(snoise(p)); \ + signal *= signal; \ + signal *= weight; \ + value += signal * pwr; \ + pwr *= roughness; \ + } \ +\ + return value; \ } - else { - return normalize ? 0.5 * sum / maxamp + 0.5 : sum; - } -} + +/* Noise fBM */ + +NOISE_FBM(float) +NOISE_FBM(vec2) +NOISE_FBM(vec3) +NOISE_FBM(vec4) + +/* Noise Multifractal */ + +NOISE_MULTI_FRACTAL(float) +NOISE_MULTI_FRACTAL(vec2) +NOISE_MULTI_FRACTAL(vec3) +NOISE_MULTI_FRACTAL(vec4) + +/* Noise Hetero Terrain */ + +NOISE_HETERO_TERRAIN(float) +NOISE_HETERO_TERRAIN(vec2) +NOISE_HETERO_TERRAIN(vec3) +NOISE_HETERO_TERRAIN(vec4) + +/* Noise Hybrid Multifractal */ + +NOISE_HYBRID_MULTI_FRACTAL(float) +NOISE_HYBRID_MULTI_FRACTAL(vec2) +NOISE_HYBRID_MULTI_FRACTAL(vec3) +NOISE_HYBRID_MULTI_FRACTAL(vec4) + +/* Noise Ridged Multifractal */ + +NOISE_RIDGED_MULTI_FRACTAL(float) +NOISE_RIDGED_MULTI_FRACTAL(vec2) +NOISE_RIDGED_MULTI_FRACTAL(vec3) +NOISE_RIDGED_MULTI_FRACTAL(vec4) 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 deleted file mode 100644 index dd8c4a3a833..00000000000 --- a/source/blender/gpu/shaders/material/gpu_shader_material_tex_musgrave.glsl +++ /dev/null @@ -1,906 +0,0 @@ -/* SPDX-FileCopyrightText: 2019-2022 Blender Authors - * - * SPDX-License-Identifier: GPL-2.0-or-later */ - -/* 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" - */ - -#pragma BLENDER_REQUIRE(gpu_shader_common_hash.glsl) -#pragma BLENDER_REQUIRE(gpu_shader_material_noise.glsl) - -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 p = w * scale; - float H = max(dimension, 1e-5); - float octaves = clamp(detail, 0.0, 15.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 Multi-fractal - * - * 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, 15.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, 15.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 Multi-fractal 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, 15.0); - float lacunarity = max(lac, 1e-5); - - float pwHL = pow(lacunarity, -H); - - float pwr = 1.0; - float value = 0.0; - float weight = 1.0; - - for (int i = 0; (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) && (weight > 0.001f)) { - if (weight > 1.0) { - weight = 1.0; - } - float signal = (snoise(p) + offset) * pwr; - value += rmd * weight * signal; - } - - fac = value; -} - -/* 1D Ridged Multi-fractal 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, 15.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, 15.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 Multi-fractal - * - * 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, 15.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, 15.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 Multi-fractal 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, 15.0); - float lacunarity = max(lac, 1e-5); - - float pwHL = pow(lacunarity, -H); - - float pwr = 1.0; - float value = 0.0; - float weight = 1.0; - - for (int i = 0; (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) && (weight > 0.001f)) { - if (weight > 1.0) { - weight = 1.0; - } - float signal = (snoise(p) + offset) * pwr; - value += rmd * weight * signal; - } - - fac = value; -} - -/* 2D Ridged Multi-fractal 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, 15.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, 15.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; -} - -/* 3D Musgrave Multi-fractal - * - * H: highest fractal dimension - * lacunarity: gap between successive frequencies - * octaves: number of frequencies in the fBm - */ - -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) -{ - vec3 p = co * scale; - float H = max(dimension, 1e-5); - float octaves = clamp(detail, 0.0, 15.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; -} - -/* 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' - */ - -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) -{ - vec3 p = co * scale; - float H = max(dimension, 1e-5); - float octaves = clamp(detail, 0.0, 15.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; -} - -/* 3D Hybrid Additive/Multiplicative Multi-fractal 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_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, 15.0); - float lacunarity = max(lac, 1e-5); - - float pwHL = pow(lacunarity, -H); - - float pwr = 1.0; - float value = 0.0; - float weight = 1.0; - - for (int i = 0; (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) && (weight > 0.001f)) { - if (weight > 1.0) { - weight = 1.0; - } - float signal = (snoise(p) + offset) * pwr; - value += rmd * weight * signal; - } - - fac = value; -} - -/* 3D Ridged Multi-fractal 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_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, 15.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; -} - -/* 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) -{ - vec4 p = vec4(co, w) * scale; - float H = max(dimension, 1e-5); - float octaves = clamp(detail, 0.0, 15.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; -} - -/* 4D Musgrave Multi-fractal - * - * 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, 15.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, 15.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; -} - -/* 4D Hybrid Additive/Multiplicative Multi-fractal 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, 15.0); - float lacunarity = max(lac, 1e-5); - - float pwHL = pow(lacunarity, -H); - - float pwr = 1.0; - float value = 0.0; - float weight = 1.0; - - for (int i = 0; (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) && (weight > 0.001f)) { - if (weight > 1.0) { - weight = 1.0; - } - float signal = (snoise(p) + offset) * pwr; - value += rmd * weight * signal; - } - - fac = value; -} - -/* 4D Ridged Multi-fractal 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) -{ - vec4 p = vec4(co, w) * scale; - float H = max(dimension, 1e-5); - float octaves = clamp(detail, 0.0, 15.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; -} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_noise.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_noise.glsl index b21313c2a4a..f864a0427e2 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_tex_noise.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_noise.glsl @@ -14,6 +14,104 @@ #pragma BLENDER_REQUIRE(gpu_shader_material_noise.glsl) #pragma BLENDER_REQUIRE(gpu_shader_material_fractal_noise.glsl) +#define NOISE_FRACTAL_DISTORTED_1D(NOISE_TYPE) \ + if (distortion != 0.0) { \ + p += snoise(p + random_float_offset(0.0)) * distortion; \ + } \ +\ + value = NOISE_TYPE(p, detail, roughness, lacunarity, offset, gain, normalize != 0.0); \ + color = vec4(value, \ + NOISE_TYPE(p + random_float_offset(1.0), \ + detail, \ + roughness, \ + lacunarity, \ + offset, \ + gain, \ + normalize != 0.0), \ + NOISE_TYPE(p + random_float_offset(2.0), \ + detail, \ + roughness, \ + lacunarity, \ + offset, \ + gain, \ + normalize != 0.0), \ + 1.0); + +#define NOISE_FRACTAL_DISTORTED_2D(NOISE_TYPE) \ + if (distortion != 0.0) { \ + p += vec2(snoise(p + random_vec2_offset(0.0)) * distortion, \ + snoise(p + random_vec2_offset(1.0)) * distortion); \ + } \ +\ + value = NOISE_TYPE(p, detail, roughness, lacunarity, offset, gain, normalize != 0.0); \ + color = vec4(value, \ + NOISE_TYPE(p + random_vec2_offset(2.0), \ + detail, \ + roughness, \ + lacunarity, \ + offset, \ + gain, \ + normalize != 0.0), \ + NOISE_TYPE(p + random_vec2_offset(3.0), \ + detail, \ + roughness, \ + lacunarity, \ + offset, \ + gain, \ + normalize != 0.0), \ + 1.0); + +#define NOISE_FRACTAL_DISTORTED_3D(NOISE_TYPE) \ + if (distortion != 0.0) { \ + p += vec3(snoise(p + random_vec3_offset(0.0)) * distortion, \ + snoise(p + random_vec3_offset(1.0)) * distortion, \ + snoise(p + random_vec3_offset(2.0)) * distortion); \ + } \ +\ + value = NOISE_TYPE(p, detail, roughness, lacunarity, offset, gain, normalize != 0.0); \ + color = vec4(value, \ + NOISE_TYPE(p + random_vec3_offset(3.0), \ + detail, \ + roughness, \ + lacunarity, \ + offset, \ + gain, \ + normalize != 0.0), \ + NOISE_TYPE(p + random_vec3_offset(4.0), \ + detail, \ + roughness, \ + lacunarity, \ + offset, \ + gain, \ + normalize != 0.0), \ + 1.0); + +#define NOISE_FRACTAL_DISTORTED_4D(NOISE_TYPE) \ + if (distortion != 0.0) { \ + p += vec4(snoise(p + random_vec4_offset(0.0)) * distortion, \ + snoise(p + random_vec4_offset(1.0)) * distortion, \ + snoise(p + random_vec4_offset(2.0)) * distortion, \ + snoise(p + random_vec4_offset(3.0)) * distortion); \ + } \ +\ + value = NOISE_TYPE(p, detail, roughness, lacunarity, offset, gain, normalize != 0.0); \ + color = vec4(value, \ + NOISE_TYPE(p + random_vec4_offset(4.0), \ + detail, \ + roughness, \ + lacunarity, \ + offset, \ + gain, \ + normalize != 0.0), \ + NOISE_TYPE(p + random_vec4_offset(5.0), \ + detail, \ + roughness, \ + lacunarity, \ + offset, \ + gain, \ + normalize != 0.0), \ + 1.0); + float random_float_offset(float seed) { return 100.0 + hash_float_to_float(seed) * 100.0; @@ -40,104 +138,432 @@ vec4 random_vec4_offset(float seed) 100.0 + hash_vec2_to_float(vec2(seed, 3.0)) * 100.0); } -void node_noise_texture_1d(vec3 co, +/* Noise fBM */ + +void node_noise_tex_fbm_1d(vec3 co, float w, float scale, float detail, float roughness, float lacunarity, + float offset, + float gain, float distortion, float normalize, out float value, out vec4 color) { + detail = clamp(detail, 0.0, 15.0); + roughness = max(roughness, 0.0); + float p = w * scale; - if (distortion != 0.0) { - p += snoise(p + random_float_offset(0.0)) * distortion; - } - value = fractal_noise(p, detail, roughness, lacunarity, normalize != 0.0); - color = vec4( - value, - fractal_noise(p + random_float_offset(1.0), detail, roughness, lacunarity, normalize != 0.0), - fractal_noise(p + random_float_offset(2.0), detail, roughness, lacunarity, normalize != 0.0), - 1.0); + NOISE_FRACTAL_DISTORTED_1D(noise_fbm) } -void node_noise_texture_2d(vec3 co, +void node_noise_tex_fbm_2d(vec3 co, float w, float scale, float detail, float roughness, float lacunarity, + float offset, + float gain, float distortion, float normalize, out float value, out vec4 color) { + detail = clamp(detail, 0.0, 15.0); + roughness = max(roughness, 0.0); + vec2 p = co.xy * scale; - if (distortion != 0.0) { - p += vec2(snoise(p + random_vec2_offset(0.0)) * distortion, - snoise(p + random_vec2_offset(1.0)) * distortion); - } - value = fractal_noise(p, detail, roughness, lacunarity, normalize != 0.0); - color = vec4( - value, - fractal_noise(p + random_vec2_offset(2.0), detail, roughness, lacunarity, normalize != 0.0), - fractal_noise(p + random_vec2_offset(3.0), detail, roughness, lacunarity, normalize != 0.0), - 1.0); + NOISE_FRACTAL_DISTORTED_2D(noise_fbm) } -void node_noise_texture_3d(vec3 co, +void node_noise_tex_fbm_3d(vec3 co, float w, float scale, float detail, float roughness, float lacunarity, + float offset, + float gain, float distortion, float normalize, out float value, out vec4 color) { + detail = clamp(detail, 0.0, 15.0); + roughness = max(roughness, 0.0); + vec3 p = co * scale; - if (distortion != 0.0) { - p += vec3(snoise(p + random_vec3_offset(0.0)) * distortion, - snoise(p + random_vec3_offset(1.0)) * distortion, - snoise(p + random_vec3_offset(2.0)) * distortion); - } - value = fractal_noise(p, detail, roughness, lacunarity, normalize != 0.0); - color = vec4( - value, - fractal_noise(p + random_vec3_offset(3.0), detail, roughness, lacunarity, normalize != 0.0), - fractal_noise(p + random_vec3_offset(4.0), detail, roughness, lacunarity, normalize != 0.0), - 1.0); + NOISE_FRACTAL_DISTORTED_3D(noise_fbm) } -void node_noise_texture_4d(vec3 co, +void node_noise_tex_fbm_4d(vec3 co, float w, float scale, float detail, float roughness, float lacunarity, + float offset, + float gain, float distortion, float normalize, out float value, out vec4 color) { - vec4 p = vec4(co, w) * scale; - if (distortion != 0.0) { - p += vec4(snoise(p + random_vec4_offset(0.0)) * distortion, - snoise(p + random_vec4_offset(1.0)) * distortion, - snoise(p + random_vec4_offset(2.0)) * distortion, - snoise(p + random_vec4_offset(3.0)) * distortion); - } + detail = clamp(detail, 0.0, 15.0); + roughness = max(roughness, 0.0); - value = fractal_noise(p, detail, roughness, lacunarity, normalize != 0.0); - color = vec4( - value, - fractal_noise(p + random_vec4_offset(4.0), detail, roughness, lacunarity, normalize != 0.0), - fractal_noise(p + random_vec4_offset(5.0), detail, roughness, lacunarity, normalize != 0.0), - 1.0); + vec4 p = vec4(co, w) * scale; + + NOISE_FRACTAL_DISTORTED_4D(noise_fbm) +} + +/* Noise Multifractal */ + +void node_noise_tex_multi_fractal_1d(vec3 co, + float w, + float scale, + float detail, + float roughness, + float lacunarity, + float offset, + float gain, + float distortion, + float normalize, + out float value, + out vec4 color) +{ + detail = clamp(detail, 0.0, 15.0); + roughness = max(roughness, 0.0); + + float p = w * scale; + + NOISE_FRACTAL_DISTORTED_1D(noise_multi_fractal) +} + +void node_noise_tex_multi_fractal_2d(vec3 co, + float w, + float scale, + float detail, + float roughness, + float lacunarity, + float offset, + float gain, + float distortion, + float normalize, + out float value, + out vec4 color) +{ + detail = clamp(detail, 0.0, 15.0); + roughness = max(roughness, 0.0); + + vec2 p = co.xy * scale; + + NOISE_FRACTAL_DISTORTED_2D(noise_multi_fractal) +} + +void node_noise_tex_multi_fractal_3d(vec3 co, + float w, + float scale, + float detail, + float roughness, + float lacunarity, + float offset, + float gain, + float distortion, + float normalize, + out float value, + out vec4 color) +{ + detail = clamp(detail, 0.0, 15.0); + roughness = max(roughness, 0.0); + + vec3 p = co * scale; + + NOISE_FRACTAL_DISTORTED_3D(noise_multi_fractal) +} + +void node_noise_tex_multi_fractal_4d(vec3 co, + float w, + float scale, + float detail, + float roughness, + float lacunarity, + float offset, + float gain, + float distortion, + float normalize, + out float value, + out vec4 color) +{ + detail = clamp(detail, 0.0, 15.0); + roughness = max(roughness, 0.0); + + vec4 p = vec4(co, w) * scale; + + NOISE_FRACTAL_DISTORTED_4D(noise_multi_fractal) +} + +/* Noise Hetero Terrain */ + +void node_noise_tex_hetero_terrain_1d(vec3 co, + float w, + float scale, + float detail, + float roughness, + float lacunarity, + float offset, + float gain, + float distortion, + float normalize, + out float value, + out vec4 color) +{ + detail = clamp(detail, 0.0, 15.0); + roughness = max(roughness, 0.0); + + float p = w * scale; + + NOISE_FRACTAL_DISTORTED_1D(noise_hetero_terrain) +} + +void node_noise_tex_hetero_terrain_2d(vec3 co, + float w, + float scale, + float detail, + float roughness, + float lacunarity, + float offset, + float gain, + float distortion, + float normalize, + out float value, + out vec4 color) +{ + detail = clamp(detail, 0.0, 15.0); + roughness = max(roughness, 0.0); + + vec2 p = co.xy * scale; + + NOISE_FRACTAL_DISTORTED_2D(noise_hetero_terrain) +} + +void node_noise_tex_hetero_terrain_3d(vec3 co, + float w, + float scale, + float detail, + float roughness, + float lacunarity, + float offset, + float gain, + float distortion, + float normalize, + out float value, + out vec4 color) +{ + detail = clamp(detail, 0.0, 15.0); + roughness = max(roughness, 0.0); + + vec3 p = co * scale; + + NOISE_FRACTAL_DISTORTED_3D(noise_hetero_terrain) +} + +void node_noise_tex_hetero_terrain_4d(vec3 co, + float w, + float scale, + float detail, + float roughness, + float lacunarity, + float offset, + float gain, + float distortion, + float normalize, + out float value, + out vec4 color) +{ + detail = clamp(detail, 0.0, 15.0); + roughness = max(roughness, 0.0); + + vec4 p = vec4(co, w) * scale; + + NOISE_FRACTAL_DISTORTED_4D(noise_hetero_terrain) +} + +/* Noise Hybrid Multifractal */ + +void node_noise_tex_hybrid_multi_fractal_1d(vec3 co, + float w, + float scale, + float detail, + float roughness, + float lacunarity, + float offset, + float gain, + float distortion, + float normalize, + out float value, + out vec4 color) +{ + detail = clamp(detail, 0.0, 15.0); + roughness = max(roughness, 0.0); + + float p = w * scale; + + NOISE_FRACTAL_DISTORTED_1D(noise_hybrid_multi_fractal) +} + +void node_noise_tex_hybrid_multi_fractal_2d(vec3 co, + float w, + float scale, + float detail, + float roughness, + float lacunarity, + float offset, + float gain, + float distortion, + float normalize, + out float value, + out vec4 color) +{ + detail = clamp(detail, 0.0, 15.0); + roughness = max(roughness, 0.0); + + vec2 p = co.xy * scale; + + NOISE_FRACTAL_DISTORTED_2D(noise_hybrid_multi_fractal) +} + +void node_noise_tex_hybrid_multi_fractal_3d(vec3 co, + float w, + float scale, + float detail, + float roughness, + float lacunarity, + float offset, + float gain, + float distortion, + float normalize, + out float value, + out vec4 color) +{ + detail = clamp(detail, 0.0, 15.0); + roughness = max(roughness, 0.0); + + vec3 p = co * scale; + + NOISE_FRACTAL_DISTORTED_3D(noise_hybrid_multi_fractal) +} + +void node_noise_tex_hybrid_multi_fractal_4d(vec3 co, + float w, + float scale, + float detail, + float roughness, + float lacunarity, + float offset, + float gain, + float distortion, + float normalize, + out float value, + out vec4 color) +{ + detail = clamp(detail, 0.0, 15.0); + roughness = max(roughness, 0.0); + + vec4 p = vec4(co, w) * scale; + + NOISE_FRACTAL_DISTORTED_4D(noise_hybrid_multi_fractal) +} + +/* Noise Ridged Multifractal */ + +void node_noise_tex_ridged_multi_fractal_1d(vec3 co, + float w, + float scale, + float detail, + float roughness, + float lacunarity, + float offset, + float gain, + float distortion, + float normalize, + out float value, + out vec4 color) +{ + detail = clamp(detail, 0.0, 15.0); + roughness = max(roughness, 0.0); + + float p = w * scale; + + NOISE_FRACTAL_DISTORTED_1D(noise_ridged_multi_fractal) +} + +void node_noise_tex_ridged_multi_fractal_2d(vec3 co, + float w, + float scale, + float detail, + float roughness, + float lacunarity, + float offset, + float gain, + float distortion, + float normalize, + out float value, + out vec4 color) +{ + detail = clamp(detail, 0.0, 15.0); + roughness = max(roughness, 0.0); + + vec2 p = co.xy * scale; + + NOISE_FRACTAL_DISTORTED_2D(noise_ridged_multi_fractal) +} + +void node_noise_tex_ridged_multi_fractal_3d(vec3 co, + float w, + float scale, + float detail, + float roughness, + float lacunarity, + float offset, + float gain, + float distortion, + float normalize, + out float value, + out vec4 color) +{ + detail = clamp(detail, 0.0, 15.0); + roughness = max(roughness, 0.0); + + vec3 p = co * scale; + + NOISE_FRACTAL_DISTORTED_3D(noise_ridged_multi_fractal) +} + +void node_noise_tex_ridged_multi_fractal_4d(vec3 co, + float w, + float scale, + float detail, + float roughness, + float lacunarity, + float offset, + float gain, + float distortion, + float normalize, + out float value, + out vec4 color) +{ + detail = clamp(detail, 0.0, 15.0); + roughness = max(roughness, 0.0); + + vec4 p = vec4(co, w) * scale; + + NOISE_FRACTAL_DISTORTED_4D(noise_ridged_multi_fractal) } diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_wave.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_wave.glsl index e41fe75def8..c6245baa6e0 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_tex_wave.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_wave.glsl @@ -56,7 +56,7 @@ float calc_wave(vec3 p, if (distortion != 0.0) { n += distortion * - (fractal_noise(p * detail_scale, detail, detail_roughness, 2.0, true) * 2.0 - 1.0); + (noise_fbm(p * detail_scale, detail, detail_roughness, 2.0, 0.0, 0.0, true) * 2.0 - 1.0); } if (wave_profile == 0) { /* profile sin */ diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index cafc23093d7..2ac5816bdf4 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1282,8 +1282,9 @@ typedef struct NodeTexGradient { typedef struct NodeTexNoise { NodeTexBase base; int dimensions; + uint8_t type; uint8_t normalize; - char _pad[3]; + char _pad[2]; } NodeTexNoise; typedef struct NodeTexVoronoi { @@ -1297,9 +1298,9 @@ typedef struct NodeTexVoronoi { } NodeTexVoronoi; typedef struct NodeTexMusgrave { - NodeTexBase base; - int musgrave_type; - int dimensions; + NodeTexBase base DNA_DEPRECATED; + int musgrave_type DNA_DEPRECATED; + int dimensions DNA_DEPRECATED; } NodeTexMusgrave; typedef struct NodeTexWave { @@ -2039,7 +2040,7 @@ enum { SHD_VORONOI_N_SPHERE_RADIUS = 4, }; -/* musgrave texture */ +/* Deprecated Musgrave Texture. Keep for Versioning */ enum { SHD_MUSGRAVE_MULTIFRACTAL = 0, SHD_MUSGRAVE_FBM = 1, @@ -2048,6 +2049,15 @@ enum { SHD_MUSGRAVE_HETERO_TERRAIN = 4, }; +/* Noise Texture */ +enum { + SHD_NOISE_MULTIFRACTAL = 0, + SHD_NOISE_FBM = 1, + SHD_NOISE_HYBRID_MULTIFRACTAL = 2, + SHD_NOISE_RIDGED_MULTIFRACTAL = 3, + SHD_NOISE_HETERO_TERRAIN = 4, +}; + /* wave texture */ enum { SHD_WAVE_BANDS = 0, diff --git a/source/blender/makesrna/intern/rna_nodetree.cc b/source/blender/makesrna/intern/rna_nodetree.cc index c7954f5b786..ab4a0b1ae8f 100644 --- a/source/blender/makesrna/intern/rna_nodetree.cc +++ b/source/blender/makesrna/intern/rna_nodetree.cc @@ -4864,6 +4864,32 @@ static void def_sh_tex_gradient(StructRNA *srna) static void def_sh_tex_noise(StructRNA *srna) { + static const EnumPropertyItem prop_noise_type[] = { + {SHD_NOISE_MULTIFRACTAL, + "MULTIFRACTAL", + 0, + "Multifractal", + "More uneven result (varies with location), more similar to a real terrain"}, + {SHD_NOISE_RIDGED_MULTIFRACTAL, + "RIDGED_MULTIFRACTAL", + 0, + "Ridged Multifractal", + "Create sharp peaks"}, + {SHD_NOISE_HYBRID_MULTIFRACTAL, + "HYBRID_MULTIFRACTAL", + 0, + "Hybrid Multifractal", + "Create peaks and valleys with different roughness values"}, + {SHD_NOISE_FBM, "FBM", 0, "fBM", "The standard fractal Perlin noise"}, + {SHD_NOISE_HETERO_TERRAIN, + "HETERO_TERRAIN", + 0, + "Hetero Terrain", + "Similar to Hybrid Multifractal creates a heterogeneous terrain, but with the likeness of " + "river channels"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + PropertyRNA *prop; RNA_def_struct_sdna_from(srna, "NodeTexNoise", "storage"); @@ -4875,6 +4901,12 @@ static void def_sh_tex_noise(StructRNA *srna) RNA_def_property_ui_text(prop, "Dimensions", "Number of dimensions to output noise for"); RNA_def_property_update(prop, 0, "rna_ShaderNode_socket_update"); + prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, nullptr, "type"); + RNA_def_property_enum_items(prop, prop_noise_type); + RNA_def_property_ui_text(prop, "Type", "Type of the Noise texture"); + RNA_def_property_update(prop, 0, "rna_ShaderNode_socket_update"); + prop = RNA_def_property(srna, "normalize", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "normalize", 0); RNA_def_property_ui_text(prop, "Normalize", "Normalize outputs to 0.0 to 1.0 range"); @@ -4937,52 +4969,6 @@ static void def_sh_tex_magic(StructRNA *srna) RNA_def_property_update(prop, 0, "rna_Node_update"); } -static void def_sh_tex_musgrave(StructRNA *srna) -{ - static const EnumPropertyItem prop_musgrave_type[] = { - {SHD_MUSGRAVE_MULTIFRACTAL, - "MULTIFRACTAL", - 0, - "Multifractal", - "More uneven result (varies with location), more similar to a real terrain"}, - {SHD_MUSGRAVE_RIDGED_MULTIFRACTAL, - "RIDGED_MULTIFRACTAL", - 0, - "Ridged Multifractal", - "Create sharp peaks"}, - {SHD_MUSGRAVE_HYBRID_MULTIFRACTAL, - "HYBRID_MULTIFRACTAL", - 0, - "Hybrid Multifractal", - "Create peaks and valleys with different roughness values"}, - {SHD_MUSGRAVE_FBM, "FBM", 0, "fBM", "Produce an unnatural homogeneous and isotropic result"}, - {SHD_MUSGRAVE_HETERO_TERRAIN, - "HETERO_TERRAIN", - 0, - "Hetero Terrain", - "Similar to Hybrid Multifractal creates a heterogeneous terrain, but with the likeness of " - "river channels"}, - {0, nullptr, 0, nullptr, nullptr}, - }; - - PropertyRNA *prop; - - 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, nullptr, "dimensions"); - RNA_def_property_enum_items(prop, rna_enum_node_tex_dimensions_items); - RNA_def_property_ui_text(prop, "Dimensions", "Number of dimensions to output noise for"); - 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, nullptr, "musgrave_type"); - RNA_def_property_enum_items(prop, prop_musgrave_type); - RNA_def_property_ui_text(prop, "Type", "Type of the Musgrave texture"); - RNA_def_property_update(prop, 0, "rna_ShaderNode_socket_update"); -} - static void def_sh_tex_voronoi(StructRNA *srna) { static EnumPropertyItem prop_distance_items[] = { diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 924796a866c..1ec87220954 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -99,7 +99,6 @@ DefNode(ShaderNode, SH_NODE_TEX_GRADIENT, def_sh_tex_gradient, "TEX DefNode(ShaderNode, SH_NODE_TEX_NOISE, def_sh_tex_noise, "TEX_NOISE", TexNoise, "Noise Texture", "Generate fractal Perlin noise") DefNode(ShaderNode, SH_NODE_TEX_MAGIC, def_sh_tex_magic, "TEX_MAGIC", TexMagic, "Magic Texture", "Generate a psychedelic color texture") DefNode(ShaderNode, SH_NODE_TEX_WAVE, def_sh_tex_wave, "TEX_WAVE", TexWave, "Wave Texture", "Generate procedural bands or rings with noise") -DefNode(ShaderNode, SH_NODE_TEX_MUSGRAVE, def_sh_tex_musgrave, "TEX_MUSGRAVE", TexMusgrave, "Musgrave Texture", "Generate fractal Perlin noise. Allows for greater control over how octaves are combined than the Noise Texture node") DefNode(ShaderNode, SH_NODE_TEX_VORONOI, def_sh_tex_voronoi, "TEX_VORONOI", TexVoronoi, "Voronoi Texture", "Generate Worley noise based on the distance to random points. Typically used to generate textures such as stones, water, or biological cells") DefNode(ShaderNode, SH_NODE_TEX_CHECKER, def_sh_tex_checker, "TEX_CHECKER", TexChecker, "Checker Texture", "Generate a checkerboard texture") DefNode(ShaderNode, SH_NODE_TEX_BRICK, def_sh_tex_brick, "TEX_BRICK", TexBrick, "Brick Texture", "Generate a procedural texture producing bricks") diff --git a/source/blender/nodes/shader/CMakeLists.txt b/source/blender/nodes/shader/CMakeLists.txt index b3e7bd7a1ce..b62643e5f35 100644 --- a/source/blender/nodes/shader/CMakeLists.txt +++ b/source/blender/nodes/shader/CMakeLists.txt @@ -98,7 +98,6 @@ set(SRC nodes/node_shader_tex_gradient.cc nodes/node_shader_tex_image.cc nodes/node_shader_tex_magic.cc - nodes/node_shader_tex_musgrave.cc nodes/node_shader_tex_noise.cc nodes/node_shader_tex_pointdensity.cc nodes/node_shader_tex_sky.cc diff --git a/source/blender/nodes/shader/node_shader_register.cc b/source/blender/nodes/shader/node_shader_register.cc index d2f7214e51b..24831da5f70 100644 --- a/source/blender/nodes/shader/node_shader_register.cc +++ b/source/blender/nodes/shader/node_shader_register.cc @@ -88,7 +88,6 @@ void register_shader_nodes() register_node_type_sh_tex_ies(); register_node_type_sh_tex_image(); register_node_type_sh_tex_magic(); - register_node_type_sh_tex_musgrave(); register_node_type_sh_tex_noise(); register_node_type_sh_tex_pointdensity(); register_node_type_sh_tex_sky(); diff --git a/source/blender/nodes/shader/node_shader_register.hh b/source/blender/nodes/shader/node_shader_register.hh index 4d75586983f..268720045c5 100644 --- a/source/blender/nodes/shader/node_shader_register.hh +++ b/source/blender/nodes/shader/node_shader_register.hh @@ -87,7 +87,6 @@ void register_node_type_sh_tex_gradient(); void register_node_type_sh_tex_ies(); void register_node_type_sh_tex_image(); void register_node_type_sh_tex_magic(); -void register_node_type_sh_tex_musgrave(); void register_node_type_sh_tex_noise(); void register_node_type_sh_tex_pointdensity(); void register_node_type_sh_tex_sky(); diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc deleted file mode 100644 index 4c905b9c870..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc +++ /dev/null @@ -1,553 +0,0 @@ -/* SPDX-FileCopyrightText: 2005 Blender Authors - * - * SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "node_shader_util.hh" -#include "node_util.hh" - -#include "BKE_texture.h" - -#include "BLI_noise.hh" - -#include "NOD_multi_function.hh" - -#include "UI_interface.hh" -#include "UI_resources.hh" - -namespace blender::nodes::node_shader_tex_musgrave_cc { - -NODE_STORAGE_FUNCS(NodeTexMusgrave) - -static void sh_node_tex_musgrave_declare(NodeDeclarationBuilder &b) -{ - b.is_function_node(); - b.add_input("Vector").hide_value().implicit_field(implicit_field_inputs::position); - b.add_input("W").min(-1000.0f).max(1000.0f).make_available([](bNode &node) { - /* Default to 1 instead of 4, because it is much faster. */ - node_storage(node).dimensions = 1; - }); - b.add_input("Scale").min(-1000.0f).max(1000.0f).default_value(5.0f); - b.add_input("Detail").min(0.0f).max(15.0f).default_value(2.0f); - b.add_input("Dimension").min(0.0f).max(1000.0f).default_value(2.0f); - b.add_input("Lacunarity").min(0.0f).max(1000.0f).default_value(2.0f); - b.add_input("Offset").min(-1000.0f).max(1000.0f); - b.add_input("Gain").min(0.0f).max(1000.0f).default_value(1.0f); - b.add_output("Fac").no_muted_links(); -} - -static void node_shader_buts_tex_musgrave(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) -{ - uiItemR(layout, ptr, "musgrave_dimensions", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); - uiItemR(layout, ptr, "musgrave_type", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); -} - -static void node_shader_init_tex_musgrave(bNodeTree * /*ntree*/, bNode *node) -{ - NodeTexMusgrave *tex = MEM_cnew(__func__); - 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; -} - -static const char *gpu_shader_name_get(const int type, const int dimensions) -{ - BLI_assert(type >= 0 && type < 5); - BLI_assert(dimensions > 0 && dimensions < 5); - - switch (type) { - case SHD_MUSGRAVE_MULTIFRACTAL: - return std::array{"node_tex_musgrave_multi_fractal_1d", - "node_tex_musgrave_multi_fractal_2d", - "node_tex_musgrave_multi_fractal_3d", - "node_tex_musgrave_multi_fractal_4d"}[dimensions - 1]; - case SHD_MUSGRAVE_FBM: - return std::array{"node_tex_musgrave_fBm_1d", - "node_tex_musgrave_fBm_2d", - "node_tex_musgrave_fBm_3d", - "node_tex_musgrave_fBm_4d"}[dimensions - 1]; - case SHD_MUSGRAVE_HYBRID_MULTIFRACTAL: - return std::array{"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"}[dimensions - 1]; - case SHD_MUSGRAVE_RIDGED_MULTIFRACTAL: - return std::array{"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"}[dimensions - 1]; - case SHD_MUSGRAVE_HETERO_TERRAIN: - return std::array{"node_tex_musgrave_hetero_terrain_1d", - "node_tex_musgrave_hetero_terrain_2d", - "node_tex_musgrave_hetero_terrain_3d", - "node_tex_musgrave_hetero_terrain_4d"}[dimensions - 1]; - } - return nullptr; -} - -static int node_shader_gpu_tex_musgrave(GPUMaterial *mat, - bNode *node, - bNodeExecData * /*execdata*/, - GPUNodeStack *in, - GPUNodeStack *out) -{ - node_shader_gpu_default_tex_coord(mat, node, &in[0].link); - node_shader_gpu_tex_mapping(mat, node, in, out); - - NodeTexMusgrave *tex = (NodeTexMusgrave *)node->storage; - int dimensions = tex->dimensions; - int type = tex->musgrave_type; - - const char *name = gpu_shader_name_get(type, dimensions); - - return GPU_stack_link(mat, node, name, in, out); -} - -static void node_shader_update_tex_musgrave(bNodeTree *ntree, bNode *node) -{ - const NodeTexMusgrave &storage = node_storage(*node); - - 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"); - - bke::nodeSetSocketAvailability(ntree, inVectorSock, storage.dimensions != 1); - bke::nodeSetSocketAvailability( - ntree, inWSock, storage.dimensions == 1 || storage.dimensions == 4); - bke::nodeSetSocketAvailability(ntree, - inOffsetSock, - storage.musgrave_type != SHD_MUSGRAVE_MULTIFRACTAL && - storage.musgrave_type != SHD_MUSGRAVE_FBM); - bke::nodeSetSocketAvailability(ntree, - inGainSock, - storage.musgrave_type == SHD_MUSGRAVE_HYBRID_MULTIFRACTAL || - storage.musgrave_type == SHD_MUSGRAVE_RIDGED_MULTIFRACTAL); - - bNodeSocket *outFacSock = nodeFindSocket(node, SOCK_OUT, "Fac"); - node_sock_label(outFacSock, "Height"); -} - -class MusgraveFunction : public mf::MultiFunction { - private: - const int dimensions_; - const int musgrave_type_; - - public: - MusgraveFunction(const int dimensions, const int musgrave_type) - : dimensions_(dimensions), musgrave_type_(musgrave_type) - { - BLI_assert(dimensions >= 1 && dimensions <= 4); - BLI_assert(musgrave_type >= 0 && musgrave_type <= 4); - static std::array signatures{ - create_signature(1, SHD_MUSGRAVE_MULTIFRACTAL), - create_signature(2, SHD_MUSGRAVE_MULTIFRACTAL), - create_signature(3, SHD_MUSGRAVE_MULTIFRACTAL), - create_signature(4, SHD_MUSGRAVE_MULTIFRACTAL), - - create_signature(1, SHD_MUSGRAVE_FBM), - create_signature(2, SHD_MUSGRAVE_FBM), - create_signature(3, SHD_MUSGRAVE_FBM), - create_signature(4, SHD_MUSGRAVE_FBM), - - create_signature(1, SHD_MUSGRAVE_HYBRID_MULTIFRACTAL), - create_signature(2, SHD_MUSGRAVE_HYBRID_MULTIFRACTAL), - create_signature(3, SHD_MUSGRAVE_HYBRID_MULTIFRACTAL), - create_signature(4, SHD_MUSGRAVE_HYBRID_MULTIFRACTAL), - - create_signature(1, SHD_MUSGRAVE_RIDGED_MULTIFRACTAL), - create_signature(2, SHD_MUSGRAVE_RIDGED_MULTIFRACTAL), - create_signature(3, SHD_MUSGRAVE_RIDGED_MULTIFRACTAL), - create_signature(4, SHD_MUSGRAVE_RIDGED_MULTIFRACTAL), - - create_signature(1, SHD_MUSGRAVE_HETERO_TERRAIN), - create_signature(2, SHD_MUSGRAVE_HETERO_TERRAIN), - create_signature(3, SHD_MUSGRAVE_HETERO_TERRAIN), - create_signature(4, SHD_MUSGRAVE_HETERO_TERRAIN), - }; - this->set_signature(&signatures[dimensions + musgrave_type * 4 - 1]); - } - - static mf::Signature create_signature(const int dimensions, const int musgrave_type) - { - mf::Signature signature; - mf::SignatureBuilder builder{"Musgrave", signature}; - - if (ELEM(dimensions, 2, 3, 4)) { - builder.single_input("Vector"); - } - if (ELEM(dimensions, 1, 4)) { - builder.single_input("W"); - } - builder.single_input("Scale"); - builder.single_input("Detail"); - builder.single_input("Dimension"); - builder.single_input("Lacunarity"); - if (ELEM(musgrave_type, - SHD_MUSGRAVE_RIDGED_MULTIFRACTAL, - SHD_MUSGRAVE_HYBRID_MULTIFRACTAL, - SHD_MUSGRAVE_HETERO_TERRAIN)) - { - builder.single_input("Offset"); - } - if (ELEM(musgrave_type, SHD_MUSGRAVE_RIDGED_MULTIFRACTAL, SHD_MUSGRAVE_HYBRID_MULTIFRACTAL)) { - builder.single_input("Gain"); - } - - builder.single_output("Fac", mf::ParamFlag::SupportsUnusedOutput); - - return signature; - } - - void call(const IndexMask &mask, mf::Params params, mf::Context /*context*/) const override - { - auto get_vector = [&](int param_index) -> VArray { - return params.readonly_single_input(param_index, "Vector"); - }; - auto get_w = [&](int param_index) -> VArray { - return params.readonly_single_input(param_index, "W"); - }; - auto get_scale = [&](int param_index) -> VArray { - return params.readonly_single_input(param_index, "Scale"); - }; - auto get_detail = [&](int param_index) -> VArray { - return params.readonly_single_input(param_index, "Detail"); - }; - auto get_dimension = [&](int param_index) -> VArray { - return params.readonly_single_input(param_index, "Dimension"); - }; - auto get_lacunarity = [&](int param_index) -> VArray { - return params.readonly_single_input(param_index, "Lacunarity"); - }; - auto get_offset = [&](int param_index) -> VArray { - return params.readonly_single_input(param_index, "Offset"); - }; - auto get_gain = [&](int param_index) -> VArray { - return params.readonly_single_input(param_index, "Gain"); - }; - - auto get_r_factor = [&](int param_index) -> MutableSpan { - return params.uninitialized_single_output_if_required(param_index, "Fac"); - }; - - int param = ELEM(dimensions_, 2, 3, 4) + ELEM(dimensions_, 1, 4); - const VArray &scale = get_scale(param++); - const VArray &detail = get_detail(param++); - const VArray &dimension = get_dimension(param++); - const VArray &lacunarity = get_lacunarity(param++); - - switch (musgrave_type_) { - case SHD_MUSGRAVE_MULTIFRACTAL: { - MutableSpan r_factor = get_r_factor(param++); - const bool compute_factor = !r_factor.is_empty(); - switch (dimensions_) { - case 1: { - const VArray &w = get_w(0); - if (compute_factor) { - mask.foreach_index([&](const int64_t i) { - const float position = w[i] * scale[i]; - r_factor[i] = noise::musgrave_multi_fractal( - position, dimension[i], lacunarity[i], detail[i]); - }); - } - break; - } - case 2: { - const VArray &vector = get_vector(0); - if (compute_factor) { - mask.foreach_index([&](const int64_t i) { - const float3 pxyz = vector[i] * scale[i]; - const float2 position = float2(pxyz[0], pxyz[1]); - r_factor[i] = noise::musgrave_multi_fractal( - position, dimension[i], lacunarity[i], detail[i]); - }); - } - break; - } - case 3: { - const VArray &vector = get_vector(0); - if (compute_factor) { - mask.foreach_index([&](const int64_t i) { - const float3 position = vector[i] * scale[i]; - r_factor[i] = noise::musgrave_multi_fractal( - position, dimension[i], lacunarity[i], detail[i]); - }); - } - break; - } - case 4: { - const VArray &vector = get_vector(0); - const VArray &w = get_w(1); - if (compute_factor) { - mask.foreach_index([&](const int64_t i) { - const float3 pxyz = vector[i] * scale[i]; - const float pw = w[i] * scale[i]; - const float4 position{pxyz[0], pxyz[1], pxyz[2], pw}; - r_factor[i] = noise::musgrave_multi_fractal( - position, dimension[i], lacunarity[i], detail[i]); - }); - } - break; - } - } - break; - } - case SHD_MUSGRAVE_RIDGED_MULTIFRACTAL: { - const VArray &offset = get_offset(param++); - const VArray &gain = get_gain(param++); - MutableSpan r_factor = get_r_factor(param++); - const bool compute_factor = !r_factor.is_empty(); - switch (dimensions_) { - case 1: { - const VArray &w = get_w(0); - if (compute_factor) { - mask.foreach_index([&](const int64_t i) { - const float position = w[i] * scale[i]; - r_factor[i] = noise::musgrave_ridged_multi_fractal( - position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]); - }); - } - break; - } - case 2: { - const VArray &vector = get_vector(0); - if (compute_factor) { - mask.foreach_index([&](const int64_t i) { - const float3 pxyz = vector[i] * scale[i]; - const float2 position = float2(pxyz[0], pxyz[1]); - r_factor[i] = noise::musgrave_ridged_multi_fractal( - position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]); - }); - } - break; - } - case 3: { - const VArray &vector = get_vector(0); - if (compute_factor) { - mask.foreach_index([&](const int64_t i) { - const float3 position = vector[i] * scale[i]; - r_factor[i] = noise::musgrave_ridged_multi_fractal( - position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]); - }); - } - break; - } - case 4: { - const VArray &vector = get_vector(0); - const VArray &w = get_w(1); - if (compute_factor) { - mask.foreach_index([&](const int64_t i) { - const float3 pxyz = vector[i] * scale[i]; - const float pw = w[i] * scale[i]; - const float4 position{pxyz[0], pxyz[1], pxyz[2], pw}; - r_factor[i] = noise::musgrave_ridged_multi_fractal( - position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]); - }); - } - break; - } - } - break; - } - case SHD_MUSGRAVE_HYBRID_MULTIFRACTAL: { - const VArray &offset = get_offset(param++); - const VArray &gain = get_gain(param++); - MutableSpan r_factor = get_r_factor(param++); - const bool compute_factor = !r_factor.is_empty(); - switch (dimensions_) { - case 1: { - const VArray &w = get_w(0); - if (compute_factor) { - mask.foreach_index([&](const int64_t i) { - const float position = w[i] * scale[i]; - r_factor[i] = noise::musgrave_hybrid_multi_fractal( - position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]); - }); - } - break; - } - case 2: { - const VArray &vector = get_vector(0); - if (compute_factor) { - mask.foreach_index([&](const int64_t i) { - const float3 pxyz = vector[i] * scale[i]; - const float2 position = float2(pxyz[0], pxyz[1]); - r_factor[i] = noise::musgrave_hybrid_multi_fractal( - position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]); - }); - } - break; - } - case 3: { - const VArray &vector = get_vector(0); - if (compute_factor) { - mask.foreach_index([&](const int64_t i) { - const float3 position = vector[i] * scale[i]; - r_factor[i] = noise::musgrave_hybrid_multi_fractal( - position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]); - }); - } - break; - } - case 4: { - const VArray &vector = get_vector(0); - const VArray &w = get_w(1); - if (compute_factor) { - mask.foreach_index([&](const int64_t i) { - const float3 pxyz = vector[i] * scale[i]; - const float pw = w[i] * scale[i]; - const float4 position{pxyz[0], pxyz[1], pxyz[2], pw}; - r_factor[i] = noise::musgrave_hybrid_multi_fractal( - position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]); - }); - } - break; - } - } - break; - } - case SHD_MUSGRAVE_FBM: { - MutableSpan r_factor = get_r_factor(param++); - const bool compute_factor = !r_factor.is_empty(); - switch (dimensions_) { - case 1: { - const VArray &w = get_w(0); - if (compute_factor) { - mask.foreach_index([&](const int64_t i) { - const float position = w[i] * scale[i]; - r_factor[i] = noise::musgrave_fBm( - position, dimension[i], lacunarity[i], detail[i]); - }); - } - break; - } - case 2: { - const VArray &vector = get_vector(0); - if (compute_factor) { - mask.foreach_index([&](const int64_t i) { - const float3 pxyz = vector[i] * scale[i]; - const float2 position = float2(pxyz[0], pxyz[1]); - r_factor[i] = noise::musgrave_fBm( - position, dimension[i], lacunarity[i], detail[i]); - }); - } - break; - } - case 3: { - const VArray &vector = get_vector(0); - if (compute_factor) { - mask.foreach_index([&](const int64_t i) { - const float3 position = vector[i] * scale[i]; - r_factor[i] = noise::musgrave_fBm( - position, dimension[i], lacunarity[i], detail[i]); - }); - } - break; - } - case 4: { - const VArray &vector = get_vector(0); - const VArray &w = get_w(1); - if (compute_factor) { - mask.foreach_index([&](const int64_t i) { - const float3 pxyz = vector[i] * scale[i]; - const float pw = w[i] * scale[i]; - const float4 position{pxyz[0], pxyz[1], pxyz[2], pw}; - r_factor[i] = noise::musgrave_fBm( - position, dimension[i], lacunarity[i], detail[i]); - }); - } - break; - } - } - break; - } - case SHD_MUSGRAVE_HETERO_TERRAIN: { - const VArray &offset = get_offset(param++); - MutableSpan r_factor = get_r_factor(param++); - const bool compute_factor = !r_factor.is_empty(); - switch (dimensions_) { - case 1: { - const VArray &w = get_w(0); - if (compute_factor) { - mask.foreach_index([&](const int64_t i) { - const float position = w[i] * scale[i]; - r_factor[i] = noise::musgrave_hetero_terrain( - position, dimension[i], lacunarity[i], detail[i], offset[i]); - }); - } - break; - } - case 2: { - const VArray &vector = get_vector(0); - if (compute_factor) { - mask.foreach_index([&](const int64_t i) { - const float3 pxyz = vector[i] * scale[i]; - const float2 position = float2(pxyz[0], pxyz[1]); - r_factor[i] = noise::musgrave_hetero_terrain( - position, dimension[i], lacunarity[i], detail[i], offset[i]); - }); - } - break; - } - case 3: { - const VArray &vector = get_vector(0); - if (compute_factor) { - mask.foreach_index([&](const int64_t i) { - const float3 position = vector[i] * scale[i]; - r_factor[i] = noise::musgrave_hetero_terrain( - position, dimension[i], lacunarity[i], detail[i], offset[i]); - }); - } - break; - } - case 4: { - const VArray &vector = get_vector(0); - const VArray &w = get_w(1); - if (compute_factor) { - mask.foreach_index([&](const int64_t i) { - const float3 pxyz = vector[i] * scale[i]; - const float pw = w[i] * scale[i]; - const float4 position{pxyz[0], pxyz[1], pxyz[2], pw}; - r_factor[i] = noise::musgrave_hetero_terrain( - position, dimension[i], lacunarity[i], detail[i], offset[i]); - }); - } - break; - } - } - break; - } - } - } -}; - -static void sh_node_musgrave_build_multi_function(NodeMultiFunctionBuilder &builder) -{ - const bNode &node = builder.node(); - NodeTexMusgrave *tex = (NodeTexMusgrave *)node.storage; - builder.construct_and_set_matching_fn(tex->dimensions, tex->musgrave_type); -} - -} // namespace blender::nodes::node_shader_tex_musgrave_cc - -void register_node_type_sh_tex_musgrave() -{ - namespace file_ns = blender::nodes::node_shader_tex_musgrave_cc; - - static bNodeType ntype; - - sh_fn_node_type_base(&ntype, SH_NODE_TEX_MUSGRAVE, "Musgrave Texture", NODE_CLASS_TEXTURE); - ntype.declare = file_ns::sh_node_tex_musgrave_declare; - ntype.draw_buttons = file_ns::node_shader_buts_tex_musgrave; - blender::bke::node_type_size_preset(&ntype, blender::bke::eNodeSizePreset::MIDDLE); - ntype.initfunc = file_ns::node_shader_init_tex_musgrave; - node_type_storage( - &ntype, "NodeTexMusgrave", node_free_standard_storage, node_copy_standard_storage); - ntype.gpu_fn = file_ns::node_shader_gpu_tex_musgrave; - ntype.updatefunc = file_ns::node_shader_update_tex_musgrave; - ntype.build_multi_function = file_ns::sh_node_musgrave_build_multi_function; - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc b/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc index 1771ef14041..d3f23f02139 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc @@ -11,6 +11,8 @@ #include "NOD_multi_function.hh" +#include "RNA_access.hh" + #include "UI_interface.hh" #include "UI_resources.hh" @@ -38,6 +40,8 @@ static void sh_node_tex_noise_declare(NodeDeclarationBuilder &b) .max(1000.0f) .default_value(2.0f) .description("The scale of a Perlin noise octave relative to that of the previous octave"); + b.add_input("Offset").min(-1000.0f).max(1000.0f).default_value(0.0f); + b.add_input("Gain").min(0.0f).max(1000.0f).default_value(1.0f); b.add_input("Distortion").min(-1000.0f).max(1000.0f).default_value(0.0f); b.add_output("Fac").no_muted_links(); b.add_output("Color").no_muted_links(); @@ -46,7 +50,10 @@ static void sh_node_tex_noise_declare(NodeDeclarationBuilder &b) static void node_shader_buts_tex_noise(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) { uiItemR(layout, ptr, "noise_dimensions", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); - uiItemR(layout, ptr, "normalize", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); + uiItemR(layout, ptr, "type", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); + if (ELEM(RNA_enum_get(ptr, "type"), SHD_NOISE_FBM)) { + uiItemR(layout, ptr, "normalize", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); + } } static void node_shader_init_tex_noise(bNodeTree * /*ntree*/, bNode *node) @@ -55,18 +62,44 @@ static void node_shader_init_tex_noise(bNodeTree * /*ntree*/, bNode *node) BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); BKE_texture_colormapping_default(&tex->base.color_mapping); tex->dimensions = 3; + tex->type = SHD_NOISE_FBM; tex->normalize = true; node->storage = tex; } -static const char *gpu_shader_get_name(const int dimensions) +static const char *gpu_shader_get_name(const int dimensions, const int type) { - BLI_assert(dimensions >= 1 && dimensions <= 4); - return std::array{"node_noise_texture_1d", - "node_noise_texture_2d", - "node_noise_texture_3d", - "node_noise_texture_4d"}[dimensions - 1]; + BLI_assert(dimensions > 0 && dimensions < 5); + BLI_assert(type >= 0 && type < 5); + + switch (type) { + case SHD_NOISE_MULTIFRACTAL: + return std::array{"node_noise_tex_multi_fractal_1d", + "node_noise_tex_multi_fractal_2d", + "node_noise_tex_multi_fractal_3d", + "node_noise_tex_multi_fractal_4d"}[dimensions - 1]; + case SHD_NOISE_FBM: + return std::array{"node_noise_tex_fbm_1d", + "node_noise_tex_fbm_2d", + "node_noise_tex_fbm_3d", + "node_noise_tex_fbm_4d"}[dimensions - 1]; + case SHD_NOISE_HYBRID_MULTIFRACTAL: + return std::array{"node_noise_tex_hybrid_multi_fractal_1d", + "node_noise_tex_hybrid_multi_fractal_2d", + "node_noise_tex_hybrid_multi_fractal_3d", + "node_noise_tex_hybrid_multi_fractal_4d"}[dimensions - 1]; + case SHD_NOISE_RIDGED_MULTIFRACTAL: + return std::array{"node_noise_tex_ridged_multi_fractal_1d", + "node_noise_tex_ridged_multi_fractal_2d", + "node_noise_tex_ridged_multi_fractal_3d", + "node_noise_tex_ridged_multi_fractal_4d"}[dimensions - 1]; + case SHD_NOISE_HETERO_TERRAIN: + return std::array{"node_noise_tex_hetero_terrain_1d", + "node_noise_tex_hetero_terrain_2d", + "node_noise_tex_hetero_terrain_3d", + "node_noise_tex_hetero_terrain_4d"}[dimensions - 1]; + } return nullptr; } @@ -82,7 +115,7 @@ static int node_shader_gpu_tex_noise(GPUMaterial *mat, const NodeTexNoise &storage = node_storage(*node); float normalize = storage.normalize; - const char *name = gpu_shader_get_name(storage.dimensions); + const char *name = gpu_shader_get_name(storage.dimensions, storage.type); return GPU_stack_link(mat, node, name, in, out, GPU_constant(&normalize)); } @@ -90,31 +123,64 @@ static void node_shader_update_tex_noise(bNodeTree *ntree, bNode *node) { bNodeSocket *sockVector = nodeFindSocket(node, SOCK_IN, "Vector"); bNodeSocket *sockW = nodeFindSocket(node, SOCK_IN, "W"); + bNodeSocket *inOffsetSock = nodeFindSocket(node, SOCK_IN, "Offset"); + bNodeSocket *inGainSock = nodeFindSocket(node, SOCK_IN, "Gain"); const NodeTexNoise &storage = node_storage(*node); bke::nodeSetSocketAvailability(ntree, sockVector, storage.dimensions != 1); bke::nodeSetSocketAvailability(ntree, sockW, storage.dimensions == 1 || storage.dimensions == 4); + bke::nodeSetSocketAvailability(ntree, + inOffsetSock, + storage.type != SHD_NOISE_MULTIFRACTAL && + storage.type != SHD_NOISE_FBM); + bke::nodeSetSocketAvailability(ntree, + inGainSock, + storage.type == SHD_NOISE_HYBRID_MULTIFRACTAL || + storage.type == SHD_NOISE_RIDGED_MULTIFRACTAL); } class NoiseFunction : public mf::MultiFunction { private: int dimensions_; + int type_; bool normalize_; public: - NoiseFunction(int dimensions, bool normalize) : dimensions_(dimensions), normalize_(normalize) + NoiseFunction(int dimensions, int type, bool normalize) + : dimensions_(dimensions), type_(type), normalize_(normalize) { BLI_assert(dimensions >= 1 && dimensions <= 4); - static std::array signatures{ - create_signature(1), - create_signature(2), - create_signature(3), - create_signature(4), + BLI_assert(type >= 0 && type <= 4); + static std::array signatures{ + create_signature(1, SHD_NOISE_MULTIFRACTAL), + create_signature(2, SHD_NOISE_MULTIFRACTAL), + create_signature(3, SHD_NOISE_MULTIFRACTAL), + create_signature(4, SHD_NOISE_MULTIFRACTAL), + + create_signature(1, SHD_NOISE_FBM), + create_signature(2, SHD_NOISE_FBM), + create_signature(3, SHD_NOISE_FBM), + create_signature(4, SHD_NOISE_FBM), + + create_signature(1, SHD_NOISE_HYBRID_MULTIFRACTAL), + create_signature(2, SHD_NOISE_HYBRID_MULTIFRACTAL), + create_signature(3, SHD_NOISE_HYBRID_MULTIFRACTAL), + create_signature(4, SHD_NOISE_HYBRID_MULTIFRACTAL), + + create_signature(1, SHD_NOISE_RIDGED_MULTIFRACTAL), + create_signature(2, SHD_NOISE_RIDGED_MULTIFRACTAL), + create_signature(3, SHD_NOISE_RIDGED_MULTIFRACTAL), + create_signature(4, SHD_NOISE_RIDGED_MULTIFRACTAL), + + create_signature(1, SHD_NOISE_HETERO_TERRAIN), + create_signature(2, SHD_NOISE_HETERO_TERRAIN), + create_signature(3, SHD_NOISE_HETERO_TERRAIN), + create_signature(4, SHD_NOISE_HETERO_TERRAIN), }; - this->set_signature(&signatures[dimensions - 1]); + this->set_signature(&signatures[dimensions + type * 4 - 1]); } - static mf::Signature create_signature(int dimensions) + static mf::Signature create_signature(int dimensions, int type) { mf::Signature signature; mf::SignatureBuilder builder{"Noise", signature}; @@ -130,6 +196,16 @@ class NoiseFunction : public mf::MultiFunction { builder.single_input("Detail"); builder.single_input("Roughness"); builder.single_input("Lacunarity"); + if (ELEM(type, + SHD_NOISE_RIDGED_MULTIFRACTAL, + SHD_NOISE_HYBRID_MULTIFRACTAL, + SHD_NOISE_HETERO_TERRAIN)) + { + builder.single_input("Offset"); + } + if (ELEM(type, SHD_NOISE_RIDGED_MULTIFRACTAL, SHD_NOISE_HYBRID_MULTIFRACTAL)) { + builder.single_input("Gain"); + } builder.single_input("Distortion"); builder.single_output("Fac", mf::ParamFlag::SupportsUnusedOutput); @@ -145,6 +221,19 @@ class NoiseFunction : public mf::MultiFunction { const VArray &detail = params.readonly_single_input(param++, "Detail"); const VArray &roughness = params.readonly_single_input(param++, "Roughness"); const VArray &lacunarity = params.readonly_single_input(param++, "Lacunarity"); + /* Initialize to any other variable when unused to avoid unnecessary conditionals. */ + const VArray &offset = ELEM(type_, + SHD_NOISE_RIDGED_MULTIFRACTAL, + SHD_NOISE_HYBRID_MULTIFRACTAL, + SHD_NOISE_HETERO_TERRAIN) ? + params.readonly_single_input(param++, "Offset") : + scale; + /* Initialize to any other variable when unused to avoid unnecessary conditionals. */ + const VArray &gain = ELEM(type_, + SHD_NOISE_RIDGED_MULTIFRACTAL, + SHD_NOISE_HYBRID_MULTIFRACTAL) ? + params.readonly_single_input(param++, "Gain") : + scale; const VArray &distortion = params.readonly_single_input(param++, "Distortion"); MutableSpan r_factor = params.uninitialized_single_output_if_required(param++, @@ -161,15 +250,30 @@ class NoiseFunction : public mf::MultiFunction { if (compute_factor) { mask.foreach_index([&](const int64_t i) { const float position = w[i] * scale[i]; - r_factor[i] = noise::perlin_fractal_distorted( - position, detail[i], roughness[i], lacunarity[i], distortion[i], normalize_); + r_factor[i] = noise::perlin_fractal_distorted(position, + math::clamp(detail[i], 0.0f, 15.0f), + math::max(roughness[i], 0.0f), + lacunarity[i], + offset[i], + gain[i], + distortion[i], + type_, + normalize_); }); } if (compute_color) { mask.foreach_index([&](const int64_t i) { const float position = w[i] * scale[i]; const float3 c = noise::perlin_float3_fractal_distorted( - position, detail[i], roughness[i], lacunarity[i], distortion[i], normalize_); + position, + math::clamp(detail[i], 0.0f, 15.0f), + math::max(roughness[i], 0.0f), + lacunarity[i], + offset[i], + gain[i], + distortion[i], + type_, + normalize_); r_color[i] = ColorGeometry4f(c[0], c[1], c[2], 1.0f); }); } @@ -180,15 +284,30 @@ class NoiseFunction : public mf::MultiFunction { if (compute_factor) { mask.foreach_index([&](const int64_t i) { const float2 position = float2(vector[i] * scale[i]); - r_factor[i] = noise::perlin_fractal_distorted( - position, detail[i], roughness[i], lacunarity[i], distortion[i], normalize_); + r_factor[i] = noise::perlin_fractal_distorted(position, + math::clamp(detail[i], 0.0f, 15.0f), + math::max(roughness[i], 0.0f), + lacunarity[i], + offset[i], + gain[i], + distortion[i], + type_, + normalize_); }); } if (compute_color) { mask.foreach_index([&](const int64_t i) { const float2 position = float2(vector[i] * scale[i]); const float3 c = noise::perlin_float3_fractal_distorted( - position, detail[i], roughness[i], lacunarity[i], distortion[i], normalize_); + position, + math::clamp(detail[i], 0.0f, 15.0f), + math::max(roughness[i], 0.0f), + lacunarity[i], + offset[i], + gain[i], + distortion[i], + type_, + normalize_); r_color[i] = ColorGeometry4f(c[0], c[1], c[2], 1.0f); }); } @@ -199,15 +318,30 @@ class NoiseFunction : public mf::MultiFunction { if (compute_factor) { mask.foreach_index([&](const int64_t i) { const float3 position = vector[i] * scale[i]; - r_factor[i] = noise::perlin_fractal_distorted( - position, detail[i], roughness[i], lacunarity[i], distortion[i], normalize_); + r_factor[i] = noise::perlin_fractal_distorted(position, + math::clamp(detail[i], 0.0f, 15.0f), + math::max(roughness[i], 0.0f), + lacunarity[i], + offset[i], + gain[i], + distortion[i], + type_, + normalize_); }); } if (compute_color) { mask.foreach_index([&](const int64_t i) { const float3 position = vector[i] * scale[i]; const float3 c = noise::perlin_float3_fractal_distorted( - position, detail[i], roughness[i], lacunarity[i], distortion[i], normalize_); + position, + math::clamp(detail[i], 0.0f, 15.0f), + math::max(roughness[i], 0.0f), + lacunarity[i], + offset[i], + gain[i], + distortion[i], + type_, + normalize_); r_color[i] = ColorGeometry4f(c[0], c[1], c[2], 1.0f); }); } @@ -222,8 +356,15 @@ class NoiseFunction : public mf::MultiFunction { const float position_w = w[i] * scale[i]; const float4 position{ position_vector[0], position_vector[1], position_vector[2], position_w}; - r_factor[i] = noise::perlin_fractal_distorted( - position, detail[i], roughness[i], lacunarity[i], distortion[i], normalize_); + r_factor[i] = noise::perlin_fractal_distorted(position, + math::clamp(detail[i], 0.0f, 15.0f), + math::max(roughness[i], 0.0f), + lacunarity[i], + offset[i], + gain[i], + distortion[i], + type_, + normalize_); }); } if (compute_color) { @@ -233,7 +374,15 @@ class NoiseFunction : public mf::MultiFunction { const float4 position{ position_vector[0], position_vector[1], position_vector[2], position_w}; const float3 c = noise::perlin_float3_fractal_distorted( - position, detail[i], roughness[i], lacunarity[i], distortion[i], normalize_); + position, + math::clamp(detail[i], 0.0f, 15.0f), + math::max(roughness[i], 0.0f), + lacunarity[i], + offset[i], + gain[i], + distortion[i], + type_, + normalize_); r_color[i] = ColorGeometry4f(c[0], c[1], c[2], 1.0f); }); } @@ -254,7 +403,8 @@ class NoiseFunction : public mf::MultiFunction { static void sh_node_noise_build_multi_function(NodeMultiFunctionBuilder &builder) { const NodeTexNoise &storage = node_storage(builder.node()); - builder.construct_and_set_matching_fn(storage.dimensions, storage.normalize); + builder.construct_and_set_matching_fn( + storage.dimensions, storage.type, storage.normalize); } NODE_SHADER_MATERIALX_BEGIN diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_wave.cc b/source/blender/nodes/shader/nodes/node_shader_tex_wave.cc index e831f989b24..7abf88dc1df 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_wave.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_wave.cc @@ -183,7 +183,8 @@ class WaveFunction : public mf::MultiFunction { if (distortion[i] != 0.0f) { n += distortion[i] * - (noise::perlin_fractal(p * dscale[i], detail[i], droughness[i], 2.0f, true) * 2.0f - + (noise::perlin_fbm(p * dscale[i], detail[i], droughness[i], 2.0f, true) * + 2.0f - 1.0f); }