Cysles: Avoid having ShaderData on the stack
[blender.git] / intern / cycles / kernel / geom / geom_motion_triangle.h
1 /*
2  * Adapted from code Copyright 2009-2010 NVIDIA Corporation
3  * Modifications Copyright 2011, Blender Foundation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 /* Motion Triangle Primitive
19  *
20  * These are stored as regular triangles, plus extra positions and normals at
21  * times other than the frame center. Computing the triangle vertex positions
22  * or normals at a given ray time is a matter of interpolation of the two steps
23  * between which the ray time lies.
24  *
25  * The extra positions and normals are stored as ATTR_STD_MOTION_VERTEX_POSITION
26  * and ATTR_STD_MOTION_VERTEX_NORMAL mesh attributes.
27  */
28
29 CCL_NAMESPACE_BEGIN
30
31 /* Time interpolation of vertex positions and normals */
32
33 ccl_device_inline int find_attribute_motion(KernelGlobals *kg, int object, uint id, AttributeElement *elem)
34 {
35         /* todo: find a better (faster) solution for this, maybe store offset per object */
36         uint attr_offset = object*kernel_data.bvh.attributes_map_stride;
37         uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
38         
39         while(attr_map.x != id) {
40                 attr_offset += ATTR_PRIM_TYPES;
41                 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
42         }
43
44         *elem = (AttributeElement)attr_map.y;
45         
46         /* return result */
47         return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z;
48 }
49
50 ccl_device_inline void motion_triangle_verts_for_step(KernelGlobals *kg, float3 tri_vindex, int offset, int numverts, int numsteps, int step, float3 verts[3])
51 {
52         if(step == numsteps) {
53                 /* center step: regular vertex location */
54                 verts[0] = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x)));
55                 verts[1] = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y)));
56                 verts[2] = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z)));
57         }
58         else {
59                 /* center step not store in this array */
60                 if(step > numsteps)
61                         step--;
62
63                 offset += step*numverts;
64
65                 verts[0] = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.x)));
66                 verts[1] = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.y)));
67                 verts[2] = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.z)));
68         }
69 }
70
71 ccl_device_inline void motion_triangle_normals_for_step(KernelGlobals *kg, float3 tri_vindex, int offset, int numverts, int numsteps, int step, float3 normals[3])
72 {
73         if(step == numsteps) {
74                 /* center step: regular vertex location */
75                 normals[0] = float4_to_float3(kernel_tex_fetch(__tri_vnormal, __float_as_int(tri_vindex.x)));
76                 normals[1] = float4_to_float3(kernel_tex_fetch(__tri_vnormal, __float_as_int(tri_vindex.y)));
77                 normals[2] = float4_to_float3(kernel_tex_fetch(__tri_vnormal, __float_as_int(tri_vindex.z)));
78         }
79         else {
80                 /* center step not stored in this array */
81                 if(step > numsteps)
82                         step--;
83
84                 offset += step*numverts;
85
86                 normals[0] = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.x)));
87                 normals[1] = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.y)));
88                 normals[2] = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.z)));
89         }
90 }
91
92 ccl_device_inline void motion_triangle_vertices(KernelGlobals *kg, int object, int prim, float time, float3 verts[3])
93 {
94         /* get motion info */
95         int numsteps, numverts;
96         object_motion_info(kg, object, &numsteps, &numverts, NULL);
97
98         /* figure out which steps we need to fetch and their interpolation factor */
99         int maxstep = numsteps*2;
100         int step = min((int)(time*maxstep), maxstep-1);
101         float t = time*maxstep - step;
102
103         /* find attribute */
104         AttributeElement elem;
105         int offset = find_attribute_motion(kg, object, ATTR_STD_MOTION_VERTEX_POSITION, &elem);
106         kernel_assert(offset != ATTR_STD_NOT_FOUND);
107
108         /* fetch vertex coordinates */
109         float3 next_verts[3];
110         float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, prim));
111
112         motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step, verts);
113         motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step+1, next_verts);
114
115         /* interpolate between steps */
116         verts[0] = (1.0f - t)*verts[0] + t*next_verts[0];
117         verts[1] = (1.0f - t)*verts[1] + t*next_verts[1];
118         verts[2] = (1.0f - t)*verts[2] + t*next_verts[2];
119 }
120
121 /* Refine triangle intersection to more precise hit point. For rays that travel
122  * far the precision is often not so good, this reintersects the primitive from
123  * a closer distance. */
124
125 ccl_device_inline float3 motion_triangle_refine(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray, float3 verts[3])
126 {
127         float3 P = ray->P;
128         float3 D = ray->D;
129         float t = isect->t;
130
131 #ifdef __INTERSECTION_REFINE__
132         if(isect->object != OBJECT_NONE) {
133                 if(UNLIKELY(t == 0.0f)) {
134                         return P;
135                 }
136 #ifdef __OBJECT_MOTION__
137                 Transform tfm = ccl_fetch(sd, ob_itfm);
138 #else
139                 Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
140 #endif
141
142                 P = transform_point(&tfm, P);
143                 D = transform_direction(&tfm, D*t);
144                 D = normalize_len(D, &t);
145         }
146
147         P = P + D*t;
148
149         /* compute refined intersection distance */
150         const float3 e1 = verts[0] - verts[2];
151         const float3 e2 = verts[1] - verts[2];
152         const float3 s1 = cross(D, e2);
153
154         const float invdivisor = 1.0f/dot(s1, e1);
155         const float3 d = P - verts[2];
156         const float3 s2 = cross(d, e1);
157         float rt = dot(e2, s2)*invdivisor;
158
159         /* compute refined position */
160         P = P + D*rt;
161
162         if(isect->object != OBJECT_NONE) {
163 #ifdef __OBJECT_MOTION__
164                 Transform tfm = ccl_fetch(sd, ob_tfm);
165 #else
166                 Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
167 #endif
168
169                 P = transform_point(&tfm, P);
170         }
171
172         return P;
173 #else
174         return P + D*t;
175 #endif
176 }
177
178 /* Same as above, except that isect->t is assumed to be in object space for instancing */
179
180 #ifdef __SUBSURFACE__
181 ccl_device_inline float3 motion_triangle_refine_subsurface(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray, float3 verts[3])
182 {
183         float3 P = ray->P;
184         float3 D = ray->D;
185         float t = isect->t;
186
187 #ifdef __INTERSECTION_REFINE__
188         if(isect->object != OBJECT_NONE) {
189 #ifdef __OBJECT_MOTION__
190                 Transform tfm = ccl_fetch(sd, ob_itfm);
191 #else
192                 Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
193 #endif
194
195                 P = transform_point(&tfm, P);
196                 D = transform_direction(&tfm, D);
197                 D = normalize(D);
198         }
199
200         P = P + D*t;
201
202         /* compute refined intersection distance */
203         const float3 e1 = verts[0] - verts[2];
204         const float3 e2 = verts[1] - verts[2];
205         const float3 s1 = cross(D, e2);
206
207         const float invdivisor = 1.0f/dot(s1, e1);
208         const float3 d = P - verts[2];
209         const float3 s2 = cross(d, e1);
210         float rt = dot(e2, s2)*invdivisor;
211
212         P = P + D*rt;
213
214         if(isect->object != OBJECT_NONE) {
215 #ifdef __OBJECT_MOTION__
216                 Transform tfm = ccl_fetch(sd, ob_tfm);
217 #else
218                 Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
219 #endif
220
221                 P = transform_point(&tfm, P);
222         }
223
224         return P;
225 #else
226         return P + D*t;
227 #endif
228 }
229 #endif
230
231 /* Setup of motion triangle specific parts of ShaderData, moved into this one
232  * function to more easily share computation of interpolated positions and
233  * normals */
234
235 /* return 3 triangle vertex normals */
236 ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray, bool subsurface)
237 {
238         /* get shader */
239         ccl_fetch(sd, shader) = kernel_tex_fetch(__tri_shader, ccl_fetch(sd, prim));
240
241         /* get motion info */
242         int numsteps, numverts;
243         object_motion_info(kg, ccl_fetch(sd, object), &numsteps, &numverts, NULL);
244
245         /* figure out which steps we need to fetch and their interpolation factor */
246         int maxstep = numsteps*2;
247         int step = min((int)(ccl_fetch(sd, time)*maxstep), maxstep-1);
248         float t = ccl_fetch(sd, time)*maxstep - step;
249
250         /* find attribute */
251         AttributeElement elem;
252         int offset = find_attribute_motion(kg, ccl_fetch(sd, object), ATTR_STD_MOTION_VERTEX_POSITION, &elem);
253         kernel_assert(offset != ATTR_STD_NOT_FOUND);
254
255         /* fetch vertex coordinates */
256         float3 verts[3], next_verts[3];
257         float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, ccl_fetch(sd, prim)));
258
259         motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step, verts);
260         motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step+1, next_verts);
261
262         /* interpolate between steps */
263         verts[0] = (1.0f - t)*verts[0] + t*next_verts[0];
264         verts[1] = (1.0f - t)*verts[1] + t*next_verts[1];
265         verts[2] = (1.0f - t)*verts[2] + t*next_verts[2];
266
267         /* compute refined position */
268 #ifdef __SUBSURFACE__
269         if(!subsurface)
270 #endif
271                 ccl_fetch(sd, P) = motion_triangle_refine(kg, sd, isect, ray, verts);
272 #ifdef __SUBSURFACE__
273         else
274                 ccl_fetch(sd, P) = motion_triangle_refine_subsurface(kg, sd, isect, ray, verts);
275 #endif
276
277         /* compute face normal */
278         float3 Ng;
279         if(ccl_fetch(sd, flag) & SD_NEGATIVE_SCALE_APPLIED)
280                 Ng = normalize(cross(verts[2] - verts[0], verts[1] - verts[0]));
281         else
282                 Ng = normalize(cross(verts[1] - verts[0], verts[2] - verts[0]));
283
284         ccl_fetch(sd, Ng) = Ng;
285         ccl_fetch(sd, N) = Ng;
286
287         /* compute derivatives of P w.r.t. uv */
288 #ifdef __DPDU__
289         ccl_fetch(sd, dPdu) = (verts[0] - verts[2]);
290         ccl_fetch(sd, dPdv) = (verts[1] - verts[2]);
291 #endif
292
293         /* compute smooth normal */
294         if(ccl_fetch(sd, shader) & SHADER_SMOOTH_NORMAL) {
295                 /* find attribute */
296                 AttributeElement elem;
297                 int offset = find_attribute_motion(kg, ccl_fetch(sd, object), ATTR_STD_MOTION_VERTEX_NORMAL, &elem);
298                 kernel_assert(offset != ATTR_STD_NOT_FOUND);
299
300                 /* fetch vertex coordinates */
301                 float3 normals[3], next_normals[3];
302                 motion_triangle_normals_for_step(kg, tri_vindex, offset, numverts, numsteps, step, normals);
303                 motion_triangle_normals_for_step(kg, tri_vindex, offset, numverts, numsteps, step+1, next_normals);
304
305                 /* interpolate between steps */
306                 normals[0] = (1.0f - t)*normals[0] + t*next_normals[0];
307                 normals[1] = (1.0f - t)*normals[1] + t*next_normals[1];
308                 normals[2] = (1.0f - t)*normals[2] + t*next_normals[2];
309
310                 /* interpolate between vertices */
311                 float u = ccl_fetch(sd, u);
312                 float v = ccl_fetch(sd, v);
313                 float w = 1.0f - u - v;
314                 ccl_fetch(sd, N) = (u*normals[0] + v*normals[1] + w*normals[2]);
315         }
316 }
317
318 /* Ray intersection. We simply compute the vertex positions at the given ray
319  * time and do a ray intersection with the resulting triangle */
320
321 ccl_device_inline bool motion_triangle_intersect(KernelGlobals *kg, Intersection *isect,
322         float3 P, float3 dir, float time, uint visibility, int object, int triAddr)
323 {
324         /* primitive index for vertex location lookup */
325         int prim = kernel_tex_fetch(__prim_index, triAddr);
326         int fobject = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, triAddr): object;
327
328         /* get vertex locations for intersection */
329         float3 verts[3];
330         motion_triangle_vertices(kg, fobject, prim, time, verts);
331
332         /* ray-triangle intersection, unoptimized */
333         float t, u, v;
334
335         if(ray_triangle_intersect_uv(P, dir, isect->t, verts[2], verts[0], verts[1], &u, &v, &t)) {
336 #ifdef __VISIBILITY_FLAG__
337                 /* visibility flag test. we do it here under the assumption
338                  * that most triangles are culled by node flags */
339                 if(kernel_tex_fetch(__prim_visibility, triAddr) & visibility)
340 #endif
341                 {
342                         isect->t = t;
343                         isect->u = u;
344                         isect->v = v;
345                         isect->prim = triAddr;
346                         isect->object = object;
347                         isect->type = PRIMITIVE_MOTION_TRIANGLE;
348                 
349                         return true;
350                 }
351         }
352
353         return false;
354 }
355
356 /* Special ray intersection routines for subsurface scattering. In that case we
357  * only want to intersect with primitives in the same object, and if case of
358  * multiple hits we pick a single random primitive as the intersection point. */
359
360 #ifdef __SUBSURFACE__
361 ccl_device_inline void motion_triangle_intersect_subsurface(
362         KernelGlobals *kg,
363         SubsurfaceIntersection *ss_isect,
364         float3 P,
365         float3 dir,
366         float time,
367         int object,
368         int triAddr,
369         float tmax,
370         uint *lcg_state,
371         int max_hits)
372 {
373         /* primitive index for vertex location lookup */
374         int prim = kernel_tex_fetch(__prim_index, triAddr);
375         int fobject = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, triAddr): object;
376
377         /* get vertex locations for intersection */
378         float3 verts[3];
379         motion_triangle_vertices(kg, fobject, prim, time, verts);
380
381         /* ray-triangle intersection, unoptimized */
382         float t, u, v;
383
384         if(ray_triangle_intersect_uv(P, dir, tmax, verts[2], verts[0], verts[1], &u, &v, &t)) {
385                 ss_isect->num_hits++;
386
387                 int hit;
388
389                 if(ss_isect->num_hits <= max_hits) {
390                         hit = ss_isect->num_hits - 1;
391                 }
392                 else {
393                         /* reservoir sampling: if we are at the maximum number of
394                          * hits, randomly replace element or skip it */
395                         hit = lcg_step_uint(lcg_state) % ss_isect->num_hits;
396
397                         if(hit >= max_hits)
398                                 return;
399                 }
400
401                 /* record intersection */
402                 Intersection *isect = &ss_isect->hits[hit];
403                 isect->t = t;
404                 isect->u = u;
405                 isect->v = v;
406                 isect->prim = triAddr;
407                 isect->object = object;
408                 isect->type = PRIMITIVE_MOTION_TRIANGLE;
409
410                 /* Record geometric normal. */
411                 ss_isect->Ng[hit] = normalize(cross(verts[1] - verts[0],
412                                                     verts[2] - verts[0]));
413         }
414 }
415 #endif
416
417 CCL_NAMESPACE_END
418