Cycles: don't count volume boundaries as transparent bounces.
[blender-staging.git] / intern / cycles / kernel / geom / geom_motion_curve.h
1 /*
2  * Licensed under the Apache License, Version 2.0 (the "License");
3  * you may not use this file except in compliance with the License.
4  * You may obtain a copy of the License at
5  *
6  * http://www.apache.org/licenses/LICENSE-2.0
7  *
8  * Unless required by applicable law or agreed to in writing, software
9  * distributed under the License is distributed on an "AS IS" BASIS,
10  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11  * See the License for the specific language governing permissions and
12  * limitations under the License.
13  */
14
15 CCL_NAMESPACE_BEGIN
16
17 /* Motion Curve Primitive
18  *
19  * These are stored as regular curves, plus extra positions and radii at times
20  * other than the frame center. Computing the curve keys at a given ray time is
21  * a matter of interpolation of the two steps between which the ray time lies.
22  *
23  * The extra curve keys are stored as ATTR_STD_MOTION_VERTEX_POSITION.
24  */
25
26 #ifdef __HAIR__
27
28 ccl_device_inline int find_attribute_curve_motion(KernelGlobals *kg, int object, uint id, AttributeElement *elem)
29 {
30         /* todo: find a better (faster) solution for this, maybe store offset per object.
31          *
32          * NOTE: currently it's not a bottleneck because in test scenes the loop below runs
33          * zero iterations and rendering is really slow with motion curves. For until other
34          * areas are speed up it's probably not so crucial to optimize this out.
35          */
36         uint attr_offset = object_attribute_map_offset(kg, object) + ATTR_PRIM_CURVE;
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_curve_keys_for_step(KernelGlobals *kg, int offset, int numkeys, int numsteps, int step, int k0, int k1, float4 keys[2])
51 {
52         if(step == numsteps) {
53                 /* center step: regular key location */
54                 keys[0] = kernel_tex_fetch(__curve_keys, k0);
55                 keys[1] = kernel_tex_fetch(__curve_keys, k1);
56         }
57         else {
58                 /* center step is not stored in this array */
59                 if(step > numsteps)
60                         step--;
61
62                 offset += step*numkeys;
63
64                 keys[0] = kernel_tex_fetch(__attributes_float3, offset + k0);
65                 keys[1] = kernel_tex_fetch(__attributes_float3, offset + k1);
66         }
67 }
68
69 /* return 2 curve key locations */
70 ccl_device_inline void motion_curve_keys(KernelGlobals *kg, int object, int prim, float time, int k0, int k1, float4 keys[2])
71 {
72         /* get motion info */
73         int numsteps, numkeys;
74         object_motion_info(kg, object, &numsteps, NULL, &numkeys);
75
76         /* figure out which steps we need to fetch and their interpolation factor */
77         int maxstep = numsteps*2;
78         int step = min((int)(time*maxstep), maxstep-1);
79         float t = time*maxstep - step;
80
81         /* find attribute */
82         AttributeElement elem;
83         int offset = find_attribute_curve_motion(kg, object, ATTR_STD_MOTION_VERTEX_POSITION, &elem);
84         kernel_assert(offset != ATTR_STD_NOT_FOUND);
85
86         /* fetch key coordinates */
87         float4 next_keys[2];
88
89         motion_curve_keys_for_step(kg, offset, numkeys, numsteps, step, k0, k1, keys);
90         motion_curve_keys_for_step(kg, offset, numkeys, numsteps, step+1, k0, k1, next_keys);
91
92         /* interpolate between steps */
93         keys[0] = (1.0f - t)*keys[0] + t*next_keys[0];
94         keys[1] = (1.0f - t)*keys[1] + t*next_keys[1];
95 }
96
97 ccl_device_inline void motion_cardinal_curve_keys_for_step(KernelGlobals *kg, int offset, int numkeys, int numsteps, int step, int k0, int k1, int k2, int k3, float4 keys[4])
98 {
99         if(step == numsteps) {
100                 /* center step: regular key location */
101                 keys[0] = kernel_tex_fetch(__curve_keys, k0);
102                 keys[1] = kernel_tex_fetch(__curve_keys, k1);
103                 keys[2] = kernel_tex_fetch(__curve_keys, k2);
104                 keys[3] = kernel_tex_fetch(__curve_keys, k3);
105         }
106         else {
107                 /* center step is not stored in this array */
108                 if(step > numsteps)
109                         step--;
110
111                 offset += step*numkeys;
112
113                 keys[0] = kernel_tex_fetch(__attributes_float3, offset + k0);
114                 keys[1] = kernel_tex_fetch(__attributes_float3, offset + k1);
115                 keys[2] = kernel_tex_fetch(__attributes_float3, offset + k2);
116                 keys[3] = kernel_tex_fetch(__attributes_float3, offset + k3);
117         }
118 }
119
120 /* return 2 curve key locations */
121 ccl_device_inline void motion_cardinal_curve_keys(KernelGlobals *kg,
122                                                   int object,
123                                                   int prim,
124                                                   float time,
125                                                   int k0, int k1, int k2, int k3,
126                                                   float4 keys[4])
127 {
128         /* get motion info */
129         int numsteps, numkeys;
130         object_motion_info(kg, object, &numsteps, NULL, &numkeys);
131
132         /* figure out which steps we need to fetch and their interpolation factor */
133         int maxstep = numsteps*2;
134         int step = min((int)(time*maxstep), maxstep-1);
135         float t = time*maxstep - step;
136
137         /* find attribute */
138         AttributeElement elem;
139         int offset = find_attribute_curve_motion(kg, object, ATTR_STD_MOTION_VERTEX_POSITION, &elem);
140         kernel_assert(offset != ATTR_STD_NOT_FOUND);
141
142         /* fetch key coordinates */
143         float4 next_keys[4];
144
145         motion_cardinal_curve_keys_for_step(kg, offset, numkeys, numsteps, step, k0, k1, k2, k3, keys);
146         motion_cardinal_curve_keys_for_step(kg, offset, numkeys, numsteps, step+1, k0, k1, k2, k3, next_keys);
147
148         /* interpolate between steps */
149         keys[0] = (1.0f - t)*keys[0] + t*next_keys[0];
150         keys[1] = (1.0f - t)*keys[1] + t*next_keys[1];
151         keys[2] = (1.0f - t)*keys[2] + t*next_keys[2];
152         keys[3] = (1.0f - t)*keys[3] + t*next_keys[3];
153 }
154
155 #if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__)
156 /* Similar to above, but returns keys as pair of two AVX registers with each
157  * holding two float4.
158  */
159 ccl_device_inline void motion_cardinal_curve_keys_avx(KernelGlobals *kg,
160                                                       int object,
161                                                       int prim,
162                                                       float time,
163                                                       int k0, int k1,
164                                                       int k2, int k3,
165                                                       avxf *out_keys_0_1,
166                                                       avxf *out_keys_2_3)
167 {
168         /* Get motion info. */
169         int numsteps, numkeys;
170         object_motion_info(kg, object, &numsteps, NULL, &numkeys);
171
172         /* Figure out which steps we need to fetch and their interpolation factor. */
173         int maxstep = numsteps * 2;
174         int step = min((int)(time*maxstep), maxstep - 1);
175         float t = time*maxstep - step;
176
177         /* Find attribute. */
178         AttributeElement elem;
179         int offset = find_attribute_curve_motion(kg,
180                                                  object,
181                                                  ATTR_STD_MOTION_VERTEX_POSITION,
182                                                  &elem);
183         kernel_assert(offset != ATTR_STD_NOT_FOUND);
184
185         /* Fetch key coordinates. */
186         float4 next_keys[4];
187         float4 keys[4];
188         motion_cardinal_curve_keys_for_step(kg,
189                                             offset,
190                                             numkeys,
191                                             numsteps,
192                                             step,
193                                             k0, k1, k2, k3,
194                                             keys);
195         motion_cardinal_curve_keys_for_step(kg,
196                                             offset,
197                                             numkeys,
198                                             numsteps,
199                                             step + 1,
200                                             k0, k1, k2, k3,
201                                             next_keys);
202
203         const avxf keys_0_1 = avxf(keys[0].m128, keys[1].m128);
204         const avxf keys_2_3 = avxf(keys[2].m128, keys[3].m128);
205         const avxf next_keys_0_1 = avxf(next_keys[0].m128, next_keys[1].m128);
206         const avxf next_keys_2_3 = avxf(next_keys[2].m128, next_keys[3].m128);
207
208         /* Interpolate between steps. */
209         *out_keys_0_1 = (1.0f - t) * keys_0_1 + t*next_keys_0_1;
210         *out_keys_2_3 = (1.0f - t) * keys_2_3 + t*next_keys_2_3;
211 }
212 #endif
213
214 #endif
215
216 CCL_NAMESPACE_END
217