Cycles: svn merge -r41225:41232 ^/trunk/blender
[blender.git] / intern / cycles / kernel / osl / nodes / node_musgrave_texture.osl
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18
19 #include "stdosl.h"
20 #include "node_texture.h"
21
22 /* Musgrave fBm
23  *
24  * H: fractal increment parameter
25  * lacunarity: gap between successive frequencies
26  * octaves: number of frequencies in the fBm
27  *
28  * from "Texturing and Modelling: A procedural approach"
29  */
30
31 float noise_musgrave_fBm(point p, string basis, float H, float lacunarity, float octaves)
32 {
33         float rmd;
34         float value = 0.0;
35         float pwr = 1.0;
36         float pwHL = pow(lacunarity, -H);
37         int i;
38
39         for(i = 0; i < (int)octaves; i++) {
40                 value += noise_basis(p, basis) * pwr;
41                 pwr *= pwHL;
42                 p *= lacunarity;
43         }
44
45         rmd = octaves - floor(octaves);
46         if(rmd != 0.0)
47                 value += rmd * noise_basis(p, basis) * pwr;
48
49         return value;
50 }
51
52 /* Musgrave Multifractal
53  *
54  * H: highest fractal dimension
55  * lacunarity: gap between successive frequencies
56  * octaves: number of frequencies in the fBm
57  */
58
59 float noise_musgrave_multi_fractal(point p, string basis, float H, float lacunarity, float octaves)
60 {
61         float rmd;
62         float value = 1.0;
63         float pwr = 1.0;
64         float pwHL = pow(lacunarity, -H);
65         int i;
66
67         for(i = 0; i < (int)octaves; i++) {
68                 value *= (pwr * noise_basis(p, basis) + 1.0);
69                 pwr *= pwHL;
70                 p *= lacunarity;
71         }
72
73         rmd = octaves - floor(octaves);
74         if(rmd != 0.0)
75                 value *= (rmd * pwr * noise_basis(p, basis) + 1.0); /* correct? */
76
77         return value;
78 }
79
80 /* Musgrave Heterogeneous Terrain
81  *
82  * H: fractal dimension of the roughest area
83  * lacunarity: gap between successive frequencies
84  * octaves: number of frequencies in the fBm
85  * offset: raises the terrain from `sea level'
86  */
87
88 float noise_musgrave_hetero_terrain(point p, string basis, float H, float lacunarity, float octaves, float offset)
89 {
90         float value, increment, rmd;
91         float pwHL = pow(lacunarity, -H);
92         float pwr = pwHL;
93         int i;
94
95         /* first unscaled octave of function; later octaves are scaled */
96         value = offset + noise_basis(p, basis);
97         p *= lacunarity;
98
99         for(i = 1; i < (int)octaves; i++) {
100                 increment = (noise_basis(p, basis) + offset) * pwr * value;
101                 value += increment;
102                 pwr *= pwHL;
103                 p *= lacunarity;
104         }
105
106         rmd = octaves - floor(octaves);
107         if(rmd != 0.0) {
108                 increment = (noise_basis(p, basis) + offset) * pwr * value;
109                 value += rmd * increment;
110         }
111
112         return value;
113 }
114
115 /* Hybrid Additive/Multiplicative Multifractal Terrain
116  *
117  * H: fractal dimension of the roughest area
118  * lacunarity: gap between successive frequencies
119  * octaves: number of frequencies in the fBm
120  * offset: raises the terrain from `sea level'
121  */
122
123 float noise_musgrave_hybrid_multi_fractal(point p, string basis, float H, float lacunarity, float octaves, float offset, float gain)
124 {
125         float result, signal, weight, rmd;
126         float pwHL = pow(lacunarity, -H);
127         float pwr = pwHL;
128         int i;
129
130         result = noise_basis(p, basis) + offset;
131         weight = gain * result;
132         p *= lacunarity;
133
134         for(i = 1; (weight > 0.001) && (i < (int)octaves); i++) {
135                 if(weight > 1.0)
136                         weight = 1.0;
137
138                 signal = (noise_basis(p, basis) + offset) * pwr;
139                 pwr *= pwHL;
140                 result += weight * signal;
141                 weight *= gain * signal;
142                 p *= lacunarity;
143         }
144
145         rmd = octaves - floor(octaves);
146         if(rmd != 0.0)
147                 result += rmd * ((noise_basis(p, basis) + offset) * pwr);
148
149         return result;
150 }
151
152 /* Ridged Multifractal Terrain
153  *
154  * H: fractal dimension of the roughest area
155  * lacunarity: gap between successive frequencies
156  * octaves: number of frequencies in the fBm
157  * offset: raises the terrain from `sea level'
158  */
159
160 float noise_musgrave_ridged_multi_fractal(point p, string basis, float H, float lacunarity, float octaves, float offset, float gain)
161 {
162         float result, signal, weight;
163         float pwHL = pow(lacunarity, -H);
164         float pwr = pwHL;
165         int i;
166
167         signal = offset - fabs(noise_basis(p, basis));
168         signal *= signal;
169         result = signal;
170         weight = 1.0;
171
172         for(i = 1; i < (int)octaves; i++) {
173                 p *= lacunarity;
174                 weight = clamp(signal * gain, 0.0, 1.0);
175                 signal = offset - fabs(noise_basis(p, basis));
176                 signal *= signal;
177                 signal *= weight;
178                 result += signal * pwr;
179                 pwr *= pwHL;
180         }
181
182         return result;
183 }
184
185 /* Shader */
186
187 shader node_musgrave_texture(
188         string Type = "fBM",
189         string Basis = "Perlin",
190         float Dimension = 2.0,
191         float Lacunarity = 1.0,
192         float Octaves = 2.0,
193         float Offset = 0.0,
194         float Intensity = 1.0,
195         float Gain = 1.0,
196         float Size = 0.25,
197         point Vector = P,
198         output float Fac = 0.0)
199 {
200         float dimension = max(Dimension, 0.0);
201         float octaves = max(Octaves, 0.0);
202         float lacunarity = max(Lacunarity, 1e-5);
203         float size = nonzero(Size, 1e-5);
204
205         point p = Vector/size;
206
207         if(Type == "Multifractal")
208                 Fac = Intensity*noise_musgrave_multi_fractal(p, Basis, dimension, lacunarity, octaves);
209         else if(Type == "fBM")
210                 Fac = Intensity*noise_musgrave_fBm(p, Basis, dimension, lacunarity, octaves);
211         else if(Type == "Hybrid Multifractal")
212                 Fac = Intensity*noise_musgrave_hybrid_multi_fractal(p, Basis, dimension, lacunarity, octaves, Offset, Gain);
213         else if(Type == "Ridged Multifractal")
214                 Fac = Intensity*noise_musgrave_ridged_multi_fractal(p, Basis, dimension, lacunarity, octaves, Offset, Gain);
215         else if(Type == "Hetero Terrain")
216                 Fac = Intensity*noise_musgrave_hetero_terrain(p, Basis, dimension, lacunarity, octaves, Offset);
217 }
218