Cycles: change __device and similar qualifiers to ccl_device in kernel code.
[blender.git] / intern / cycles / kernel / svm / svm_noise.h
1 /*
2  * Adapted from Open Shading Language with this license:
3  *
4  * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
5  * All Rights Reserved.
6  *
7  * Modifications Copyright 2011, Blender Foundation.
8  * 
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are
11  * met:
12  * * Redistributions of source code must retain the above copyright
13  *   notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above copyright
15  *   notice, this list of conditions and the following disclaimer in the
16  *   documentation and/or other materials provided with the distribution.
17  * * Neither the name of Sony Pictures Imageworks nor the names of its
18  *   contributors may be used to endorse or promote products derived from
19  *   this software without specific prior written permission.
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 CCL_NAMESPACE_BEGIN
34
35 ccl_device int quick_floor(float x)
36 {
37         return float_to_int(x) - ((x < 0) ? 1 : 0);
38 }
39
40 ccl_device float bits_to_01(uint bits)
41 {
42         return bits * (1.0f/(float)0xFFFFFFFF);
43 }
44
45 ccl_device uint hash(uint kx, uint ky, uint kz)
46 {
47         // define some handy macros
48 #define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
49 #define final(a,b,c) \
50 { \
51         c ^= b; c -= rot(b,14); \
52         a ^= c; a -= rot(c,11); \
53         b ^= a; b -= rot(a,25); \
54         c ^= b; c -= rot(b,16); \
55         a ^= c; a -= rot(c,4);  \
56         b ^= a; b -= rot(a,14); \
57         c ^= b; c -= rot(b,24); \
58 }
59         // now hash the data!
60         uint a, b, c, len = 3;
61         a = b = c = 0xdeadbeef + (len << 2) + 13;
62
63         c += kz;
64         b += ky;
65         a += kx;
66         final(a, b, c);
67
68         return c;
69         // macros not needed anymore
70 #undef rot
71 #undef final
72 }
73
74 ccl_device int imod(int a, int b)
75 {
76         a %= b;
77         return a < 0 ? a + b : a;
78 }
79
80 ccl_device uint phash(int kx, int ky, int kz, int3 p) 
81 {
82         return hash(imod(kx, p.x), imod(ky, p.y), imod(kz, p.z));
83 }
84
85 ccl_device float floorfrac(float x, int* i)
86 {
87         *i = quick_floor(x);
88         return x - *i;
89 }
90
91 ccl_device float fade(float t)
92 {
93         return t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f);
94 }
95
96 ccl_device float nerp(float t, float a, float b)
97 {
98         return (1.0f - t) * a + t * b;
99 }
100
101 ccl_device float grad(int hash, float x, float y, float z)
102 {
103         // use vectors pointing to the edges of the cube
104         int h = hash & 15;
105         float u = h<8 ? x : y;
106         float v = h<4 ? y : h == 12 || h == 14 ? x : z;
107         return ((h&1) ? -u : u) + ((h&2) ? -v : v);
108 }
109
110 ccl_device float scale3(float result)
111 {
112         return 0.9820f * result;
113 }
114
115 ccl_device_noinline float perlin(float x, float y, float z)
116 {
117         int X; float fx = floorfrac(x, &X);
118         int Y; float fy = floorfrac(y, &Y);
119         int Z; float fz = floorfrac(z, &Z);
120
121         float u = fade(fx);
122         float v = fade(fy);
123         float w = fade(fz);
124
125         float result;
126
127         result = nerp (w, nerp (v, nerp (u, grad (hash (X  , Y  , Z  ), fx       , fy    , fz     ),
128                                                                                 grad (hash (X+1, Y  , Z  ), fx-1.0f, fy  , fz     )),
129                                                            nerp (u, grad (hash (X  , Y+1, Z  ), fx       , fy-1.0f, fz    ),
130                                                                                 grad (hash (X+1, Y+1, Z  ), fx-1.0f, fy-1.0f, fz          ))),
131                                           nerp (v, nerp (u, grad (hash (X  , Y  , Z+1), fx       , fy    , fz-1.0f ),
132                                                                                 grad (hash (X+1, Y  , Z+1), fx-1.0f, fy  , fz-1.0f )),
133                                                            nerp (u, grad (hash (X  , Y+1, Z+1), fx       , fy-1.0f, fz-1.0f ),
134                                                                                 grad (hash (X+1, Y+1, Z+1), fx-1.0f, fy-1.0f, fz-1.0f ))));
135         float r = scale3(result);
136
137         /* can happen for big coordinates, things even out to 0.0 then anyway */
138         return (isfinite(r))? r: 0.0f;
139 }
140
141 ccl_device_noinline float perlin_periodic(float x, float y, float z, float3 pperiod)
142 {
143         int X; float fx = floorfrac(x, &X);
144         int Y; float fy = floorfrac(y, &Y);
145         int Z; float fz = floorfrac(z, &Z);
146
147         int3 p;
148
149         p.x = max(quick_floor(pperiod.x), 1);
150         p.y = max(quick_floor(pperiod.y), 1);
151         p.z = max(quick_floor(pperiod.z), 1);
152
153         float u = fade(fx);
154         float v = fade(fy);
155         float w = fade(fz);
156
157         float result;
158
159         result = nerp (w, nerp (v, nerp (u, grad (phash (X  , Y  , Z  , p), fx   , fy    , fz     ),
160                                                                                 grad (phash (X+1, Y  , Z  , p), fx-1.0f, fy      , fz     )),
161                                                            nerp (u, grad (phash (X  , Y+1, Z  , p), fx   , fy-1.0f, fz    ),
162                                                                                 grad (phash (X+1, Y+1, Z  , p), fx-1.0f, fy-1.0f, fz      ))),
163                                           nerp (v, nerp (u, grad (phash (X  , Y  , Z+1, p), fx   , fy    , fz-1.0f ),
164                                                                                 grad (phash (X+1, Y  , Z+1, p), fx-1.0f, fy      , fz-1.0f )),
165                                                            nerp (u, grad (phash (X  , Y+1, Z+1, p), fx   , fy-1.0f, fz-1.0f ),
166                                                                                 grad (phash (X+1, Y+1, Z+1, p), fx-1.0f, fy-1.0f, fz-1.0f ))));
167         float r = scale3(result);
168
169         /* can happen for big coordinates, things even out to 0.0 then anyway */
170         return (isfinite(r))? r: 0.0f;
171 }
172
173 /* perlin noise in range 0..1 */
174 ccl_device float noise(float3 p)
175 {
176         float r = perlin(p.x, p.y, p.z);
177         return 0.5f*r + 0.5f;
178 }
179
180 /* perlin noise in range -1..1 */
181 ccl_device float snoise(float3 p)
182 {
183         return perlin(p.x, p.y, p.z);
184 }
185
186 /* cell noise */
187 ccl_device_noinline float cellnoise(float3 p)
188 {
189         uint ix = quick_floor(p.x);
190         uint iy = quick_floor(p.y);
191         uint iz = quick_floor(p.z);
192
193         return bits_to_01(hash(ix, iy, iz));
194 }
195
196 ccl_device float3 cellnoise_color(float3 p)
197 {
198         float r = cellnoise(p);
199         float g = cellnoise(make_float3(p.y, p.x, p.z));
200         float b = cellnoise(make_float3(p.y, p.z, p.x));
201
202         return make_float3(r, g, b);
203 }
204
205 /* periodic perlin noise in range 0..1 */
206 ccl_device float pnoise(float3 p, float3 pperiod)
207 {
208         float r = perlin_periodic(p.x, p.y, p.z, pperiod);
209         return 0.5f*r + 0.5f;
210 }
211
212 /* periodic perlin noise in range -1..1 */
213 ccl_device float psnoise(float3 p, float3 pperiod)
214 {
215         return perlin_periodic(p.x, p.y, p.z, pperiod);
216 }
217
218 CCL_NAMESPACE_END
219