Merge branch 'master' into blender2.8
[blender.git] / intern / cycles / kernel / shaders / node_musgrave_texture.osl
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "stdosl.h"
18 #include "node_texture.h"
19
20 /* Musgrave fBm
21  *
22  * H: fractal increment parameter
23  * lacunarity: gap between successive frequencies
24  * octaves: number of frequencies in the fBm
25  *
26  * from "Texturing and Modelling: A procedural approach"
27  */
28
29 float noise_musgrave_fBm(point ip, float H, float lacunarity, float octaves)
30 {
31         float rmd;
32         float value = 0.0;
33         float pwr = 1.0;
34         float pwHL = pow(lacunarity, -H);
35         int i;
36         point p = ip;
37
38         for (i = 0; i < (int)octaves; i++) {
39                 value += safe_noise(p, "signed") * pwr;
40                 pwr *= pwHL;
41                 p *= lacunarity;
42         }
43
44         rmd = octaves - floor(octaves);
45         if (rmd != 0.0)
46                 value += rmd * safe_noise(p, "signed") * pwr;
47
48         return value;
49 }
50
51 /* Musgrave Multifractal
52  *
53  * H: highest fractal dimension
54  * lacunarity: gap between successive frequencies
55  * octaves: number of frequencies in the fBm
56  */
57
58 float noise_musgrave_multi_fractal(point ip, float H, float lacunarity, float octaves)
59 {
60         float rmd;
61         float value = 1.0;
62         float pwr = 1.0;
63         float pwHL = pow(lacunarity, -H);
64         int i;
65         point p = ip;
66
67         for (i = 0; i < (int)octaves; i++) {
68                 value *= (pwr * safe_noise(p, "signed") + 1.0);
69                 pwr *= pwHL;
70                 p *= lacunarity;
71         }
72
73         rmd = octaves - floor(octaves);
74         if (rmd != 0.0)
75                 value *= (rmd * pwr * safe_noise(p, "signed") + 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 ip, 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         point p = ip;
95
96         /* first unscaled octave of function; later octaves are scaled */
97         value = offset + safe_noise(p, "signed");
98         p *= lacunarity;
99
100         for (i = 1; i < (int)octaves; i++) {
101                 increment = (safe_noise(p, "signed") + offset) * pwr * value;
102                 value += increment;
103                 pwr *= pwHL;
104                 p *= lacunarity;
105         }
106
107         rmd = octaves - floor(octaves);
108         if (rmd != 0.0) {
109                 increment = (safe_noise(p, "signed") + offset) * pwr * value;
110                 value += rmd * increment;
111         }
112
113         return value;
114 }
115
116 /* Hybrid Additive/Multiplicative Multifractal Terrain
117  *
118  * H: fractal dimension of the roughest area
119  * lacunarity: gap between successive frequencies
120  * octaves: number of frequencies in the fBm
121  * offset: raises the terrain from `sea level'
122  */
123
124 float noise_musgrave_hybrid_multi_fractal(point ip, float H, float lacunarity,
125                                           float octaves, float offset, float gain)
126 {
127         float result, signal, weight, rmd;
128         float pwHL = pow(lacunarity, -H);
129         float pwr = pwHL;
130         int i;
131         point p = ip;
132
133         result = safe_noise(p, "signed") + offset;
134         weight = gain * result;
135         p *= lacunarity;
136
137         for (i = 1; (weight > 0.001) && (i < (int)octaves); i++) {
138                 if (weight > 1.0)
139                         weight = 1.0;
140
141                 signal = (safe_noise(p, "signed") + offset) * pwr;
142                 pwr *= pwHL;
143                 result += weight * signal;
144                 weight *= gain * signal;
145                 p *= lacunarity;
146         }
147
148         rmd = octaves - floor(octaves);
149         if (rmd != 0.0)
150                 result += rmd * ((safe_noise(p, "signed") + offset) * pwr);
151
152         return result;
153 }
154
155 /* Ridged Multifractal Terrain
156  *
157  * H: fractal dimension of the roughest area
158  * lacunarity: gap between successive frequencies
159  * octaves: number of frequencies in the fBm
160  * offset: raises the terrain from `sea level'
161  */
162
163 float noise_musgrave_ridged_multi_fractal(point ip, float H, float lacunarity,
164                                           float octaves, float offset, float gain)
165 {
166         float result, signal, weight;
167         float pwHL = pow(lacunarity, -H);
168         float pwr = pwHL;
169         int i;
170         point p = ip;
171
172         signal = offset - fabs(safe_noise(p, "signed"));
173         signal *= signal;
174         result = signal;
175         weight = 1.0;
176
177         for (i = 1; i < (int)octaves; i++) {
178                 p *= lacunarity;
179                 weight = clamp(signal * gain, 0.0, 1.0);
180                 signal = offset - fabs(safe_noise(p, "signed"));
181                 signal *= signal;
182                 signal *= weight;
183                 result += signal * pwr;
184                 pwr *= pwHL;
185         }
186
187         return result;
188 }
189
190 /* Shader */
191
192 shader node_musgrave_texture(
193         int use_mapping = 0,
194         matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
195         string type = "fBM",
196         float Dimension = 2.0,
197         float Lacunarity = 1.0,
198         float Detail = 2.0,
199         float Offset = 0.0,
200         float Gain = 1.0,
201         float Scale = 5.0,
202         point Vector = P,
203         output float Fac = 0.0,
204         output color Color = 0.0)
205 {
206         float dimension = max(Dimension, 1e-5);
207         float octaves = clamp(Detail, 0.0, 16.0);
208         float lacunarity = max(Lacunarity, 1e-5);
209         float intensity = 1.0;
210
211         point p = Vector;
212
213         if (use_mapping)
214                 p = transform(mapping, p);
215
216         p = p * Scale;
217
218         if (type == "multifractal")
219                 Fac = intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves);
220         else if (type == "fBM")
221                 Fac = intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves);
222         else if (type == "hybrid_multifractal")
223                 Fac = intensity * noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, Offset, Gain);
224         else if (type == "ridged_multifractal")
225                 Fac = intensity * noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, Offset, Gain);
226         else if (type == "hetero_terrain")
227                 Fac = intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, Offset);
228         
229         Color = color(Fac, Fac, Fac);
230 }
231