Blender V2.61 - r43446

svm_musgrave.h

Go to the documentation of this file.
00001 /*
00002  * Copyright 2011, Blender Foundation.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 CCL_NAMESPACE_BEGIN
00020 
00021 /* Musgrave fBm
00022  *
00023  * H: fractal increment parameter
00024  * lacunarity: gap between successive frequencies
00025  * octaves: number of frequencies in the fBm
00026  *
00027  * from "Texturing and Modelling: A procedural approach"
00028  */
00029 
00030 __device_noinline float noise_musgrave_fBm(float3 p, NodeNoiseBasis basis, float H, float lacunarity, float octaves)
00031 {
00032     float rmd;
00033     float value = 0.0f;
00034     float pwr = 1.0f;
00035     float pwHL = pow(lacunarity, -H);
00036     int i;
00037 
00038     for(i = 0; i < (int)octaves; i++) {
00039         value += snoise(p) * pwr;
00040         pwr *= pwHL;
00041         p *= lacunarity;
00042     }
00043 
00044     rmd = octaves - floor(octaves);
00045     if(rmd != 0.0f)
00046         value += rmd * snoise(p) * pwr;
00047 
00048     return value;
00049 }
00050 
00051 /* Musgrave Multifractal
00052  *
00053  * H: highest fractal dimension
00054  * lacunarity: gap between successive frequencies
00055  * octaves: number of frequencies in the fBm
00056  */
00057 
00058 __device_noinline float noise_musgrave_multi_fractal(float3 p, NodeNoiseBasis basis, float H, float lacunarity, float octaves)
00059 {
00060     float rmd;
00061     float value = 1.0f;
00062     float pwr = 1.0f;
00063     float pwHL = pow(lacunarity, -H);
00064     int i;
00065 
00066     for(i = 0; i < (int)octaves; i++) {
00067         value *= (pwr * snoise(p) + 1.0f);
00068         pwr *= pwHL;
00069         p *= lacunarity;
00070     }
00071 
00072     rmd = octaves - floor(octaves);
00073     if(rmd != 0.0f)
00074         value *= (rmd * pwr * snoise(p) + 1.0f); /* correct? */
00075 
00076     return value;
00077 }
00078 
00079 /* Musgrave Heterogeneous Terrain
00080  *
00081  * H: fractal dimension of the roughest area
00082  * lacunarity: gap between successive frequencies
00083  * octaves: number of frequencies in the fBm
00084  * offset: raises the terrain from `sea level'
00085  */
00086 
00087 __device_noinline float noise_musgrave_hetero_terrain(float3 p, NodeNoiseBasis basis, float H, float lacunarity, float octaves, float offset)
00088 {
00089     float value, increment, rmd;
00090     float pwHL = pow(lacunarity, -H);
00091     float pwr = pwHL;
00092     int i;
00093 
00094     /* first unscaled octave of function; later octaves are scaled */
00095     value = offset + snoise(p);
00096     p *= lacunarity;
00097 
00098     for(i = 1; i < (int)octaves; i++) {
00099         increment = (snoise(p) + offset) * pwr * value;
00100         value += increment;
00101         pwr *= pwHL;
00102         p *= lacunarity;
00103     }
00104 
00105     rmd = octaves - floor(octaves);
00106     if(rmd != 0.0f) {
00107         increment = (snoise(p) + offset) * pwr * value;
00108         value += rmd * increment;
00109     }
00110 
00111     return value;
00112 }
00113 
00114 /* Hybrid Additive/Multiplicative Multifractal Terrain
00115  *
00116  * H: fractal dimension of the roughest area
00117  * lacunarity: gap between successive frequencies
00118  * octaves: number of frequencies in the fBm
00119  * offset: raises the terrain from `sea level'
00120  */
00121 
00122 __device_noinline float noise_musgrave_hybrid_multi_fractal(float3 p, NodeNoiseBasis basis, float H, float lacunarity, float octaves, float offset, float gain)
00123 {
00124     float result, signal, weight, rmd;
00125     float pwHL = pow(lacunarity, -H);
00126     float pwr = pwHL;
00127     int i;
00128 
00129     result = snoise(p) + offset;
00130     weight = gain * result;
00131     p *= lacunarity;
00132 
00133     for(i = 1; (weight > 0.001f) && (i < (int)octaves); i++) {
00134         if(weight > 1.0f)
00135             weight = 1.0f;
00136 
00137         signal = (snoise(p) + offset) * pwr;
00138         pwr *= pwHL;
00139         result += weight * signal;
00140         weight *= gain * signal;
00141         p *= lacunarity;
00142     }
00143 
00144     rmd = octaves - floor(octaves);
00145     if(rmd != 0.0f)
00146         result += rmd * ((snoise(p) + offset) * pwr);
00147 
00148     return result;
00149 }
00150 
00151 /* Ridged Multifractal Terrain
00152  *
00153  * H: fractal dimension of the roughest area
00154  * lacunarity: gap between successive frequencies
00155  * octaves: number of frequencies in the fBm
00156  * offset: raises the terrain from `sea level'
00157  */
00158 
00159 __device_noinline float noise_musgrave_ridged_multi_fractal(float3 p, NodeNoiseBasis basis, float H, float lacunarity, float octaves, float offset, float gain)
00160 {
00161     float result, signal, weight;
00162     float pwHL = pow(lacunarity, -H);
00163     float pwr = pwHL;
00164     int i;
00165 
00166     signal = offset - fabsf(snoise(p));
00167     signal *= signal;
00168     result = signal;
00169     weight = 1.0f;
00170 
00171     for(i = 1; i < (int)octaves; i++) {
00172         p *= lacunarity;
00173         weight = clamp(signal * gain, 0.0f, 1.0f);
00174         signal = offset - fabsf(snoise(p));
00175         signal *= signal;
00176         signal *= weight;
00177         result += signal * pwr;
00178         pwr *= pwHL;
00179     }
00180 
00181     return result;
00182 }
00183 
00184 /* Shader */
00185 
00186 __device float svm_musgrave(NodeMusgraveType type, float dimension, float lacunarity, float octaves, float offset, float intensity, float gain, float scale, float3 p)
00187 {
00188     NodeNoiseBasis basis = NODE_NOISE_PERLIN;
00189     p *= scale;
00190 
00191     if(type == NODE_MUSGRAVE_MULTIFRACTAL)
00192         return intensity*noise_musgrave_multi_fractal(p, basis, dimension, lacunarity, octaves);
00193     else if(type == NODE_MUSGRAVE_FBM)
00194         return intensity*noise_musgrave_fBm(p, basis, dimension, lacunarity, octaves);
00195     else if(type == NODE_MUSGRAVE_HYBRID_MULTIFRACTAL)
00196         return intensity*noise_musgrave_hybrid_multi_fractal(p, basis, dimension, lacunarity, octaves, offset, gain);
00197     else if(type == NODE_MUSGRAVE_RIDGED_MULTIFRACTAL)
00198         return intensity*noise_musgrave_ridged_multi_fractal(p, basis, dimension, lacunarity, octaves, offset, gain);
00199     else if(type == NODE_MUSGRAVE_HETERO_TERRAIN)
00200         return intensity*noise_musgrave_hetero_terrain(p, basis, dimension, lacunarity, octaves, offset);
00201     
00202     return 0.0f;
00203 }
00204 
00205 __device void svm_node_tex_musgrave(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
00206 {
00207     uint4 node2 = read_node(kg, offset);
00208     uint4 node3 = read_node(kg, offset);
00209 
00210     uint type, co_offset, color_offset, fac_offset;
00211     uint dimension_offset, lacunarity_offset, detail_offset, offset_offset;
00212     uint gain_offset, scale_offset;
00213 
00214     decode_node_uchar4(node.y, &type, &co_offset, &color_offset, &fac_offset);
00215     decode_node_uchar4(node.z, &dimension_offset, &lacunarity_offset, &detail_offset, &offset_offset);
00216     decode_node_uchar4(node.w, &gain_offset, &scale_offset, NULL, NULL);
00217 
00218     float3 co = stack_load_float3(stack, co_offset);
00219     float dimension = stack_load_float_default(stack, dimension_offset, node2.x);
00220     float lacunarity = stack_load_float_default(stack, lacunarity_offset, node2.y);
00221     float detail = stack_load_float_default(stack, detail_offset, node2.z);
00222     float foffset = stack_load_float_default(stack, offset_offset, node2.w);
00223     float gain = stack_load_float_default(stack, gain_offset, node3.x);
00224     float scale = stack_load_float_default(stack, scale_offset, node3.y);
00225 
00226     dimension = fmaxf(dimension, 1e-5f);
00227     detail = clamp(detail, 0.0f, 16.0f);
00228     lacunarity = fmaxf(lacunarity, 1e-5f);
00229 
00230     float f = svm_musgrave((NodeMusgraveType)type,
00231         dimension, lacunarity, detail, foffset, 1.0f, gain, scale, co);
00232 
00233     if(stack_valid(fac_offset))
00234         stack_store_float(stack, fac_offset, f);
00235     if(stack_valid(color_offset))
00236         stack_store_float3(stack, color_offset, make_float3(f, f, f));
00237 }
00238 
00239 CCL_NAMESPACE_END
00240