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