* OSL can't overwrite input parameters, use a local variable instead.
[blender.git] / intern / cycles / kernel / osl / nodes / node_texture.h
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16
17 /* Voronoi Distances */
18
19 float voronoi_distance(string distance_metric, vector d, float e)
20 {
21         float result = 0.0;
22
23         if (distance_metric == "Distance Squared")
24                 result = dot(d, d);
25         if (distance_metric == "Actual Distance")
26                 result = length(d);
27         if (distance_metric == "Manhattan")
28                 result = fabs(d[0]) + fabs(d[1]) + fabs(d[2]);
29         if (distance_metric == "Chebychev")
30                 result = max(fabs(d[0]), max(fabs(d[1]), fabs(d[2])));
31         if (distance_metric == "Minkovsky 1/2")
32                 result = sqrt(fabs(d[0])) + sqrt(fabs(d[1])) + sqrt(fabs(d[1]));
33         if (distance_metric == "Minkovsky 4")
34                 result = sqrt(sqrt(dot(d * d, d * d)));
35         if (distance_metric == "Minkovsky")
36                 result = pow(pow(fabs(d[0]), e) + pow(fabs(d[1]), e) + pow(fabs(d[2]), e), 1.0 / e);
37         
38         return result;
39 }
40
41 /* Voronoi / Worley like */
42
43 color cellnoise_color(point p)
44 {
45         float r = cellnoise(p);
46         float g = cellnoise(point(p[1], p[0], p[2]));
47         float b = cellnoise(point(p[1], p[2], p[0]));
48
49         return color(r, g, b);
50 }
51
52 void voronoi(point p, string distance_metric, float e, float da[4], point pa[4])
53 {
54         /* returns distances in da and point coords in pa */
55         int xx, yy, zz, xi, yi, zi;
56
57         xi = (int)floor(p[0]);
58         yi = (int)floor(p[1]);
59         zi = (int)floor(p[2]);
60
61         da[0] = 1e10;
62         da[1] = 1e10;
63         da[2] = 1e10;
64         da[3] = 1e10;
65
66         for (xx = xi - 1; xx <= xi + 1; xx++) {
67                 for (yy = yi - 1; yy <= yi + 1; yy++) {
68                         for (zz = zi - 1; zz <= zi + 1; zz++) {
69                                 point ip = point(xx, yy, zz);
70                                 point vp = (point)cellnoise_color(ip);
71                                 point pd = p - (vp + ip);
72                                 float d = voronoi_distance(distance_metric, pd, e);
73
74                                 vp += point(xx, yy, zz);
75
76                                 if (d < da[0]) {
77                                         da[3] = da[2];
78                                         da[2] = da[1];
79                                         da[1] = da[0];
80                                         da[0] = d;
81
82                                         pa[3] = pa[2];
83                                         pa[2] = pa[1];
84                                         pa[1] = pa[0];
85                                         pa[0] = vp;
86                                 }
87                                 else if (d < da[1]) {
88                                         da[3] = da[2];
89                                         da[2] = da[1];
90                                         da[1] = d;
91
92                                         pa[3] = pa[2];
93                                         pa[2] = pa[1];
94                                         pa[1] = vp;
95                                 }
96                                 else if (d < da[2]) {
97                                         da[3] = da[2];
98                                         da[2] = d;
99
100                                         pa[3] = pa[2];
101                                         pa[2] = vp;
102                                 }
103                                 else if (d < da[3]) {
104                                         da[3] = d;
105                                         pa[3] = vp;
106                                 }
107                         }
108                 }
109         }
110 }
111
112 float voronoi_Fn(point p, int n)
113 {
114         float da[4];
115         point pa[4];
116
117         voronoi(p, "Distance Squared", 0, da, pa);
118
119         return da[n];
120 }
121
122 float voronoi_FnFn(point p, int n1, int n2)
123 {
124         float da[4];
125         point pa[4];
126
127         voronoi(p, "Distance Squared", 0, da, pa);
128
129         return da[n2] - da[n1];
130 }
131
132 float voronoi_F1(point p) { return voronoi_Fn(p, 0); }
133 float voronoi_F2(point p) { return voronoi_Fn(p, 1); }
134 float voronoi_F3(point p) { return voronoi_Fn(p, 2); }
135 float voronoi_F4(point p) { return voronoi_Fn(p, 3); }
136 float voronoi_F1F2(point p) { return voronoi_FnFn(p, 0, 1); }
137
138 float voronoi_Cr(point p)
139 {
140         /* crackle type pattern, just a scale/clamp of F2-F1 */
141         float t = 10.0 * voronoi_F1F2(p);
142         return (t > 1.0) ? 1.0 : t;
143 }
144
145 float voronoi_F1S(point p) { return 2.0 * voronoi_F1(p) - 1.0; }
146 float voronoi_F2S(point p) { return 2.0 * voronoi_F2(p) - 1.0; }
147 float voronoi_F3S(point p) { return 2.0 * voronoi_F3(p) - 1.0; }
148 float voronoi_F4S(point p) { return 2.0 * voronoi_F4(p) - 1.0; }
149 float voronoi_F1F2S(point p) { return 2.0 * voronoi_F1F2(p) - 1.0; }
150 float voronoi_CrS(point p) { return 2.0 * voronoi_Cr(p) - 1.0; }
151
152 /* Noise Bases */
153
154 float noise_basis(point p, string basis)
155 {
156         float result = 0.0;
157
158         if (basis == "Perlin")
159                 result = noise(p);
160         if (basis == "Voronoi F1")
161                 result = voronoi_F1S(p);
162         if (basis == "Voronoi F2")
163                 result = voronoi_F2S(p);
164         if (basis == "Voronoi F3")
165                 result = voronoi_F3S(p);
166         if (basis == "Voronoi F4")
167                 result = voronoi_F4S(p);
168         if (basis == "Voronoi F2-F1")
169                 result = voronoi_F1F2S(p);
170         if (basis == "Voronoi Crackle")
171                 result = voronoi_CrS(p);
172         if (basis == "Cell Noise")
173                 result = cellnoise(p);
174         
175         return result;
176 }
177
178 /* Soft/Hard Noise */
179
180 float noise_basis_hard(point p, string basis, int hard)
181 {
182         float t = noise_basis(p, basis);
183         return (hard) ? fabs(2.0 * t - 1.0) : t;
184 }
185
186 /* Waves */
187
188 float noise_wave(string wave, float a)
189 {
190         float result = 0.0;
191
192         if (wave == "Sine") {
193                 result = 0.5 + 0.5 * sin(a);
194         }
195         else if (wave == "Saw") {
196                 float b = 2 * M_PI;
197                 int n = (int)(a / b);
198                 a -= n * b;
199                 if (a < 0) a += b;
200
201                 result = a / b;
202         }
203         else if (wave == "Tri") {
204                 float b = 2 * M_PI;
205                 float rmax = 1.0;
206
207                 result = rmax - 2.0 * fabs(floor((a * (1.0 / b)) + 0.5) - (a * (1.0 / b)));
208         }
209
210         return result;
211 }
212
213 /* Turbulence */
214
215 float noise_turbulence(point p, string basis, float details, int hard)
216 {
217         float fscale = 1.0;
218         float amp = 1.0;
219         float sum = 0.0;
220         int i, n;
221         
222         float octaves = clamp(details, 0.0, 16.0);
223         n = (int)octaves;
224
225         for (i = 0; i <= n; i++) {
226                 float t = noise_basis(fscale * p, basis);
227
228                 if (hard)
229                         t = fabs(2.0 * t - 1.0);
230
231                 sum += t * amp;
232                 amp *= 0.5;
233                 fscale *= 2.0;
234         }
235         
236         float rmd = octaves - floor(octaves);
237
238         if(rmd != 0.0) {
239                 float t = noise_basis(fscale*p, basis);
240
241                 if(hard)
242                         t = fabs(2.0*t - 1.0);
243
244                 float sum2 = sum + t*amp;
245
246                 sum *= ((float)(1 << n)/(float)((1 << (n+1)) - 1));
247                 sum2 *= ((float)(1 << (n+1))/(float)((1 << (n+2)) - 1));
248
249                 return (1.0 - rmd)*sum + rmd*sum2;
250         }
251         else {
252                 sum *= ((float)(1 << n)/(float)((1 << (n+1)) - 1));
253                 return sum;
254         }
255 }
256
257 /* Utility */
258
259 float nonzero(float f, float eps)
260 {
261         float r;
262
263         if (abs(f) < eps)
264                 r = sign(f) * eps;
265         else
266                 r = f;
267         
268         return r;
269 }
270