Cycles: random walk subsurface scattering.
[blender.git] / intern / cycles / kernel / geom / geom_motion_triangle_intersect.h
1 /*
2  * Copyright 2011-2016 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 /* Motion Triangle Primitive
18  *
19  * These are stored as regular triangles, plus extra positions and normals at
20  * times other than the frame center. Computing the triangle vertex positions
21  * or normals at a given ray time is a matter of interpolation of the two steps
22  * between which the ray time lies.
23  *
24  * The extra positions and normals are stored as ATTR_STD_MOTION_VERTEX_POSITION
25  * and ATTR_STD_MOTION_VERTEX_NORMAL mesh attributes.
26  */
27
28 CCL_NAMESPACE_BEGIN
29
30 /* Refine triangle intersection to more precise hit point. For rays that travel
31  * far the precision is often not so good, this reintersects the primitive from
32  * a closer distance.
33  */
34
35 ccl_device_inline float3 motion_triangle_refine(KernelGlobals *kg,
36                                                 ShaderData *sd,
37                                                 const Intersection *isect,
38                                                 const Ray *ray,
39                                                 float3 verts[3])
40 {
41         float3 P = ray->P;
42         float3 D = ray->D;
43         float t = isect->t;
44
45 #ifdef __INTERSECTION_REFINE__
46         if(isect->object != OBJECT_NONE) {
47                 if(UNLIKELY(t == 0.0f)) {
48                         return P;
49                 }
50 #  ifdef __OBJECT_MOTION__
51                 Transform tfm = sd->ob_itfm;
52 #  else
53                 Transform tfm = object_fetch_transform(kg,
54                                                        isect->object,
55                                                        OBJECT_INVERSE_TRANSFORM);
56 #  endif
57
58                 P = transform_point(&tfm, P);
59                 D = transform_direction(&tfm, D*t);
60                 D = normalize_len(D, &t);
61         }
62
63         P = P + D*t;
64
65         /* Compute refined intersection distance. */
66         const float3 e1 = verts[0] - verts[2];
67         const float3 e2 = verts[1] - verts[2];
68         const float3 s1 = cross(D, e2);
69
70         const float invdivisor = 1.0f/dot(s1, e1);
71         const float3 d = P - verts[2];
72         const float3 s2 = cross(d, e1);
73         float rt = dot(e2, s2)*invdivisor;
74
75         /* Compute refined position. */
76         P = P + D*rt;
77
78         if(isect->object != OBJECT_NONE) {
79 #  ifdef __OBJECT_MOTION__
80                 Transform tfm = sd->ob_tfm;
81 #  else
82                 Transform tfm = object_fetch_transform(kg,
83                                                        isect->object,
84                                                        OBJECT_TRANSFORM);
85 #  endif
86
87                 P = transform_point(&tfm, P);
88         }
89
90         return P;
91 #else
92         return P + D*t;
93 #endif
94 }
95
96 /* Same as above, except that isect->t is assumed to be in object space
97  * for instancing.
98  */
99
100 #ifdef __BVH_LOCAL__
101 #  if defined(__KERNEL_CUDA__) && (defined(i386) || defined(_M_IX86))
102 ccl_device_noinline
103 #  else
104 ccl_device_inline
105 #  endif
106 float3 motion_triangle_refine_local(KernelGlobals *kg,
107                                     ShaderData *sd,
108                                     const Intersection *isect,
109                                     const Ray *ray,
110                                     float3 verts[3])
111 {
112         float3 P = ray->P;
113         float3 D = ray->D;
114         float t = isect->t;
115
116 #  ifdef __INTERSECTION_REFINE__
117         if(isect->object != OBJECT_NONE) {
118 #    ifdef __OBJECT_MOTION__
119                 Transform tfm = sd->ob_itfm;
120 #    else
121                 Transform tfm = object_fetch_transform(kg,
122                                                        isect->object,
123                                                        OBJECT_INVERSE_TRANSFORM);
124 #    endif
125
126                 P = transform_point(&tfm, P);
127                 D = transform_direction(&tfm, D);
128                 D = normalize(D);
129         }
130
131         P = P + D*t;
132
133         /* compute refined intersection distance */
134         const float3 e1 = verts[0] - verts[2];
135         const float3 e2 = verts[1] - verts[2];
136         const float3 s1 = cross(D, e2);
137
138         const float invdivisor = 1.0f/dot(s1, e1);
139         const float3 d = P - verts[2];
140         const float3 s2 = cross(d, e1);
141         float rt = dot(e2, s2)*invdivisor;
142
143         P = P + D*rt;
144
145         if(isect->object != OBJECT_NONE) {
146 #    ifdef __OBJECT_MOTION__
147                 Transform tfm = sd->ob_tfm;
148 #    else
149                 Transform tfm = object_fetch_transform(kg,
150                                                        isect->object,
151                                                        OBJECT_TRANSFORM);
152 #    endif
153
154                 P = transform_point(&tfm, P);
155         }
156
157         return P;
158 #  else  /* __INTERSECTION_REFINE__ */
159         return P + D*t;
160 #  endif  /* __INTERSECTION_REFINE__ */
161 }
162 #endif  /* __BVH_LOCAL__ */
163
164
165 /* Ray intersection. We simply compute the vertex positions at the given ray
166  * time and do a ray intersection with the resulting triangle.
167  */
168
169 ccl_device_inline bool motion_triangle_intersect(
170         KernelGlobals *kg,
171         Intersection *isect,
172         float3 P,
173         float3 dir,
174         float time,
175         uint visibility,
176         int object,
177         int prim_addr)
178 {
179         /* Primitive index for vertex location lookup. */
180         int prim = kernel_tex_fetch(__prim_index, prim_addr);
181         int fobject = (object == OBJECT_NONE)
182                           ? kernel_tex_fetch(__prim_object, prim_addr)
183                           : object;
184         /* Get vertex locations for intersection. */
185         float3 verts[3];
186         motion_triangle_vertices(kg, fobject, prim, time, verts);
187         /* Ray-triangle intersection, unoptimized. */
188         float t, u, v;
189         if(ray_triangle_intersect(P,
190                                   dir,
191                                   isect->t,
192 #if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
193                                   (ssef*)verts,
194 #else
195                                   verts[0], verts[1], verts[2],
196 #endif
197                                   &u, &v, &t))
198         {
199 #ifdef __VISIBILITY_FLAG__
200                 /* Visibility flag test. we do it here under the assumption
201                  * that most triangles are culled by node flags.
202                  */
203                 if(kernel_tex_fetch(__prim_visibility, prim_addr) & visibility)
204 #endif
205                 {
206                         isect->t = t;
207                         isect->u = u;
208                         isect->v = v;
209                         isect->prim = prim_addr;
210                         isect->object = object;
211                         isect->type = PRIMITIVE_MOTION_TRIANGLE;
212                         return true;
213                 }
214         }
215         return false;
216 }
217
218 /* Special ray intersection routines for local intersections. In that case we
219  * only want to intersect with primitives in the same object, and if case of
220  * multiple hits we pick a single random primitive as the intersection point.
221  */
222 #ifdef __BVH_LOCAL__
223 ccl_device_inline void motion_triangle_intersect_local(
224         KernelGlobals *kg,
225         LocalIntersection *local_isect,
226         float3 P,
227         float3 dir,
228         float time,
229         int object,
230         int local_object,
231         int prim_addr,
232         float tmax,
233         uint *lcg_state,
234         int max_hits)
235 {
236         /* Only intersect with matching object, for instanced objects we
237          * already know we are only intersecting the right object. */
238         if(object == OBJECT_NONE) {
239                 if(kernel_tex_fetch(__prim_object, prim_addr) != local_object) {
240                         return;
241                 }
242         }
243
244         /* Primitive index for vertex location lookup. */
245         int prim = kernel_tex_fetch(__prim_index, prim_addr);
246         /* Get vertex locations for intersection. */
247         float3 verts[3];
248         motion_triangle_vertices(kg, local_object, prim, time, verts);
249         /* Ray-triangle intersection, unoptimized. */
250         float t, u, v;
251         if(!ray_triangle_intersect(P,
252                                    dir,
253                                    tmax,
254 #if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
255                                    (ssef*)verts,
256 #else
257                                    verts[0], verts[1], verts[2],
258 #endif
259                                    &u, &v, &t))
260         {
261                 return;
262         }
263
264         int hit;
265         if(lcg_state) {
266                 /* Record up to max_hits intersections. */
267                 for(int i = min(max_hits, local_isect->num_hits) - 1; i >= 0; --i) {
268                         if(local_isect->hits[i].t == t) {
269                                 return;
270                         }
271                 }
272
273                 local_isect->num_hits++;
274
275                 if(local_isect->num_hits <= max_hits) {
276                         hit = local_isect->num_hits - 1;
277                 }
278                 else {
279                         /* Reservoir sampling: if we are at the maximum number of
280                          * hits, randomly replace element or skip it.
281                          */
282                         hit = lcg_step_uint(lcg_state) % local_isect->num_hits;
283
284                         if(hit >= max_hits)
285                                 return;
286                 }
287         }
288         else {
289                 /* Record closest intersection only. */
290                 if(local_isect->num_hits && t > local_isect->hits[0].t) {
291                         return;
292                 }
293
294                 hit = 0;
295                 local_isect->num_hits = 1;
296         }
297
298         /* Record intersection. */
299         Intersection *isect = &local_isect->hits[hit];
300         isect->t = t;
301         isect->u = u;
302         isect->v = v;
303         isect->prim = prim_addr;
304         isect->object = object;
305         isect->type = PRIMITIVE_MOTION_TRIANGLE;
306
307         /* Record geometric normal. */
308         local_isect->Ng[hit] = normalize(cross(verts[1] - verts[0],
309                                                verts[2] - verts[0]));
310 }
311 #endif  /* __BVH_LOCAL__ */
312
313 CCL_NAMESPACE_END