Cycles: constant folding for RGB/Vector Curves and Color Ramp.
[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 p, 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
37         for (i = 0; i < (int)octaves; i++) {
38                 value += safe_noise(p, "signed") * pwr;
39                 pwr *= pwHL;
40                 p *= lacunarity;
41         }
42
43         rmd = octaves - floor(octaves);
44         if (rmd != 0.0)
45                 value += rmd * safe_noise(p, "signed") * pwr;
46
47         return value;
48 }
49
50 /* Musgrave Multifractal
51  *
52  * H: highest fractal dimension
53  * lacunarity: gap between successive frequencies
54  * octaves: number of frequencies in the fBm
55  */
56
57 float noise_musgrave_multi_fractal(point p, float H, float lacunarity, float octaves)
58 {
59         float rmd;
60         float value = 1.0;
61         float pwr = 1.0;
62         float pwHL = pow(lacunarity, -H);
63         int i;
64
65         for (i = 0; i < (int)octaves; i++) {
66                 value *= (pwr * safe_noise(p, "signed") + 1.0);
67                 pwr *= pwHL;
68                 p *= lacunarity;
69         }
70
71         rmd = octaves - floor(octaves);
72         if (rmd != 0.0)
73                 value *= (rmd * pwr * safe_noise(p, "signed") + 1.0); /* correct? */
74
75         return value;
76 }
77
78 /* Musgrave Heterogeneous Terrain
79  *
80  * H: fractal dimension of the roughest area
81  * lacunarity: gap between successive frequencies
82  * octaves: number of frequencies in the fBm
83  * offset: raises the terrain from `sea level'
84  */
85
86 float noise_musgrave_hetero_terrain(point p, float H, float lacunarity, float octaves, float offset)
87 {
88         float value, increment, rmd;
89         float pwHL = pow(lacunarity, -H);
90         float pwr = pwHL;
91         int i;
92
93         /* first unscaled octave of function; later octaves are scaled */
94         value = offset + safe_noise(p, "signed");
95         p *= lacunarity;
96
97         for (i = 1; i < (int)octaves; i++) {
98                 increment = (safe_noise(p, "signed") + offset) * pwr * value;
99                 value += increment;
100                 pwr *= pwHL;
101                 p *= lacunarity;
102         }
103
104         rmd = octaves - floor(octaves);
105         if (rmd != 0.0) {
106                 increment = (safe_noise(p, "signed") + offset) * pwr * value;
107                 value += rmd * increment;
108         }
109
110         return value;
111 }
112
113 /* Hybrid Additive/Multiplicative Multifractal Terrain
114  *
115  * H: fractal dimension of the roughest area
116  * lacunarity: gap between successive frequencies
117  * octaves: number of frequencies in the fBm
118  * offset: raises the terrain from `sea level'
119  */
120
121 float noise_musgrave_hybrid_multi_fractal(point p, float H, float lacunarity,
122                                           float octaves, float offset, float gain)
123 {
124         float result, signal, weight, rmd;
125         float pwHL = pow(lacunarity, -H);
126         float pwr = pwHL;
127         int i;
128
129         result = safe_noise(p, "signed") + offset;
130         weight = gain * result;
131         p *= lacunarity;
132
133         for (i = 1; (weight > 0.001) && (i < (int)octaves); i++) {
134                 if (weight > 1.0)
135                         weight = 1.0;
136
137                 signal = (safe_noise(p, "signed") + offset) * pwr;
138                 pwr *= pwHL;
139                 result += weight * signal;
140                 weight *= gain * signal;
141                 p *= lacunarity;
142         }
143
144         rmd = octaves - floor(octaves);
145         if (rmd != 0.0)
146                 result += rmd * ((safe_noise(p, "signed") + offset) * pwr);
147
148         return result;
149 }
150
151 /* Ridged Multifractal Terrain
152  *
153  * H: fractal dimension of the roughest area
154  * lacunarity: gap between successive frequencies
155  * octaves: number of frequencies in the fBm
156  * offset: raises the terrain from `sea level'
157  */
158
159 float noise_musgrave_ridged_multi_fractal(point p, float H, float lacunarity,
160                                           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(safe_noise(p, "signed"));
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(safe_noise(p, "signed"));
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         int use_mapping = 0,
189         matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
190         string type = "fBM",
191         float Dimension = 2.0,
192         float Lacunarity = 1.0,
193         float Detail = 2.0,
194         float Offset = 0.0,
195         float Gain = 1.0,
196         float Scale = 5.0,
197         point Vector = P,
198         output float Fac = 0.0,
199         output color Color = 0.0)
200 {
201         float dimension = max(Dimension, 1e-5);
202         float octaves = clamp(Detail, 0.0, 16.0);
203         float lacunarity = max(Lacunarity, 1e-5);
204         float intensity = 1.0;
205
206         point p = Vector;
207
208         if (use_mapping)
209                 p = transform(mapping, p);
210
211         p = p * Scale;
212
213         if (type == "multifractal")
214                 Fac = intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves);
215         else if (type == "fBM")
216                 Fac = intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves);
217         else if (type == "hybrid_multifractal")
218                 Fac = intensity * noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, Offset, Gain);
219         else if (type == "ridged_multifractal")
220                 Fac = intensity * noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, Offset, Gain);
221         else if (type == "hetero_terrain")
222                 Fac = intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, Offset);
223         
224         Color = color(Fac, Fac, Fac);
225 }
226