Cycles: Remove few function arguments needed only for the split kernel
[blender.git] / intern / cycles / kernel / kernel_shadow.h
1 /*
2  * Copyright 2011-2013 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 CCL_NAMESPACE_BEGIN
18
19 #ifdef __SHADOW_RECORD_ALL__
20
21 /* Shadow function to compute how much light is blocked, CPU variation.
22  *
23  * We trace a single ray. If it hits any opaque surface, or more than a given
24  * number of transparent surfaces is hit, then we consider the geometry to be
25  * entirely blocked. If not, all transparent surfaces will be recorded and we
26  * will shade them one by one to determine how much light is blocked. This all
27  * happens in one scene intersection function.
28  *
29  * Recording all hits works well in some cases but may be slower in others. If
30  * we have many semi-transparent hairs, one intersection may be faster because
31  * you'd be reinteresecting the same hairs a lot with each step otherwise. If
32  * however there is mostly binary transparency then we may be recording many
33  * unnecessary intersections when one of the first surfaces blocks all light.
34  *
35  * From tests in real scenes it seems the performance loss is either minimal,
36  * or there is a performance increase anyway due to avoiding the need to send
37  * two rays with transparent shadows.
38  *
39  * This is CPU only because of qsort, and malloc or high stack space usage to
40  * record all these intersections. */
41
42 #define STACK_MAX_HITS 64
43
44 ccl_device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ray, float3 *shadow)
45 {
46         *shadow = make_float3(1.0f, 1.0f, 1.0f);
47
48         if(ray->t == 0.0f)
49                 return false;
50         
51         bool blocked;
52
53         if(kernel_data.integrator.transparent_shadows) {
54                 /* check transparent bounces here, for volume scatter which can do
55                  * lighting before surface path termination is checked */
56                 if(state->transparent_bounce >= kernel_data.integrator.transparent_max_bounce)
57                         return true;
58
59                 /* intersect to find an opaque surface, or record all transparent surface hits */
60                 Intersection hits_stack[STACK_MAX_HITS];
61                 Intersection *hits = hits_stack;
62                 uint max_hits = kernel_data.integrator.transparent_max_bounce - state->transparent_bounce - 1;
63
64                 /* prefer to use stack but use dynamic allocation if too deep max hits
65                  * we need max_hits + 1 storage space due to the logic in
66                  * scene_intersect_shadow_all which will first store and then check if
67                  * the limit is exceeded */
68                 if(max_hits + 1 > STACK_MAX_HITS)
69                         hits = (Intersection*)malloc(sizeof(Intersection)*(max_hits + 1));
70
71                 uint num_hits;
72                 blocked = scene_intersect_shadow_all(kg, ray, hits, max_hits, &num_hits);
73
74                 /* if no opaque surface found but we did find transparent hits, shade them */
75                 if(!blocked && num_hits > 0) {
76                         float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
77                         float3 Pend = ray->P + ray->D*ray->t;
78                         float last_t = 0.0f;
79                         int bounce = state->transparent_bounce;
80                         Intersection *isect = hits;
81 #ifdef __VOLUME__
82                         PathState ps = *state;
83 #endif
84
85                         qsort(hits, num_hits, sizeof(Intersection), intersections_compare);
86
87                         for(int hit = 0; hit < num_hits; hit++, isect++) {
88                                 /* adjust intersection distance for moving ray forward */
89                                 float new_t = isect->t;
90                                 isect->t -= last_t;
91
92                                 /* skip hit if we did not move forward, step by step raytracing
93                                  * would have skipped it as well then */
94                                 if(last_t == new_t)
95                                         continue;
96
97                                 last_t = new_t;
98
99 #ifdef __VOLUME__
100                                 /* attenuation between last surface and next surface */
101                                 if(ps.volume_stack[0].shader != SHADER_NONE) {
102                                         Ray segment_ray = *ray;
103                                         segment_ray.t = isect->t;
104                                         kernel_volume_shadow(kg, &ps, &segment_ray, &throughput);
105                                 }
106 #endif
107
108                                 /* setup shader data at surface */
109                                 ShaderData sd;
110                                 shader_setup_from_ray(kg, &sd, isect, ray);
111
112                                 /* attenuation from transparent surface */
113                                 if(!(sd.flag & SD_HAS_ONLY_VOLUME)) {
114                                         path_state_modify_bounce(state, true);
115                                         shader_eval_surface(kg, &sd, state, 0.0f, PATH_RAY_SHADOW, SHADER_CONTEXT_SHADOW);
116                                         path_state_modify_bounce(state, false);
117
118                                         throughput *= shader_bsdf_transparency(kg, &sd);
119                                 }
120
121                                 /* stop if all light is blocked */
122                                 if(is_zero(throughput)) {
123                                         /* free dynamic storage */
124                                         if(hits != hits_stack)
125                                                 free(hits);
126                                         return true;
127                                 }
128
129                                 /* move ray forward */
130                                 ray->P = sd.P;
131                                 if(ray->t != FLT_MAX)
132                                         ray->D = normalize_len(Pend - ray->P, &ray->t);
133
134 #ifdef __VOLUME__
135                                 /* exit/enter volume */
136                                 kernel_volume_stack_enter_exit(kg, &sd, ps.volume_stack);
137 #endif
138
139                                 bounce++;
140                         }
141
142 #ifdef __VOLUME__
143                         /* attenuation for last line segment towards light */
144                         if(ps.volume_stack[0].shader != SHADER_NONE)
145                                 kernel_volume_shadow(kg, &ps, ray, &throughput);
146 #endif
147
148                         *shadow = throughput;
149
150                         if(hits != hits_stack)
151                                 free(hits);
152                         return is_zero(throughput);
153                 }
154
155                 /* free dynamic storage */
156                 if(hits != hits_stack)
157                         free(hits);
158         }
159         else {
160                 Intersection isect;
161                 blocked = scene_intersect(kg, ray, PATH_RAY_SHADOW_OPAQUE, &isect, NULL, 0.0f, 0.0f);
162         }
163
164 #ifdef __VOLUME__
165         if(!blocked && state->volume_stack[0].shader != SHADER_NONE) {
166                 /* apply attenuation from current volume shader */
167                 kernel_volume_shadow(kg, state, ray, shadow);
168         }
169 #endif
170
171         return blocked;
172 }
173
174 #undef STACK_MAX_HITS
175
176 #else
177
178 /* Shadow function to compute how much light is blocked, GPU variation.
179  *
180  * Here we raytrace from one transparent surface to the next step by step.
181  * To minimize overhead in cases where we don't need transparent shadows, we
182  * first trace a regular shadow ray. We check if the hit primitive was
183  * potentially transparent, and only in that case start marching. this gives
184  * one extra ray cast for the cases were we do want transparency. */
185
186 ccl_device_noinline bool shadow_blocked(KernelGlobals *kg,
187                                         ccl_addr_space PathState *state,
188                                         ccl_addr_space Ray *ray_input,
189                                         float3 *shadow)
190 {
191         *shadow = make_float3(1.0f, 1.0f, 1.0f);
192
193         if(ray_input->t == 0.0f)
194                 return false;
195
196 #ifdef __SPLIT_KERNEL__
197         Ray private_ray = *ray_input;
198         Ray *ray = &private_ray;
199 #else
200         Ray *ray = ray_input;
201 #endif
202
203 #ifdef __SPLIT_KERNEL__
204         Intersection *isect = &kg->isect_shadow[TIDX];
205 #else
206         Intersection isect_object;
207         Intersection *isect = &isect_object;
208 #endif
209
210         bool blocked = scene_intersect(kg, ray, PATH_RAY_SHADOW_OPAQUE, isect, NULL, 0.0f, 0.0f);
211
212 #ifdef __TRANSPARENT_SHADOWS__
213         if(blocked && kernel_data.integrator.transparent_shadows) {
214                 if(shader_transparent_shadow(kg, isect)) {
215                         float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
216                         float3 Pend = ray->P + ray->D*ray->t;
217                         int bounce = state->transparent_bounce;
218 #ifdef __VOLUME__
219                         PathState ps = *state;
220 #endif
221
222                         for(;;) {
223                                 if(bounce >= kernel_data.integrator.transparent_max_bounce)
224                                         return true;
225
226                                 if(!scene_intersect(kg, ray, PATH_RAY_SHADOW_TRANSPARENT, isect, NULL, 0.0f, 0.0f))
227                                 {
228 #ifdef __VOLUME__
229                                         /* attenuation for last line segment towards light */
230                                         if(ps.volume_stack[0].shader != SHADER_NONE)
231                                                 kernel_volume_shadow(kg, &ps, ray, &throughput);
232 #endif
233
234                                         *shadow *= throughput;
235
236                                         return false;
237                                 }
238
239                                 if(!shader_transparent_shadow(kg, isect))
240                                         return true;
241
242 #ifdef __VOLUME__
243                                 /* attenuation between last surface and next surface */
244                                 if(ps.volume_stack[0].shader != SHADER_NONE) {
245                                         Ray segment_ray = *ray;
246                                         segment_ray.t = isect->t;
247                                         kernel_volume_shadow(kg, &ps, &segment_ray, &throughput);
248                                 }
249 #endif
250
251                                 /* setup shader data at surface */
252 #ifdef __SPLIT_KERNEL__
253                                 ShaderData *sd = kg->sd_input;
254 #else
255                                 ShaderData sd_object;
256                                 ShaderData *sd = &sd_object;
257 #endif
258                                 shader_setup_from_ray(kg, sd, isect, ray);
259
260                                 /* attenuation from transparent surface */
261                                 if(!(ccl_fetch(sd, flag) & SD_HAS_ONLY_VOLUME)) {
262                                         path_state_modify_bounce(state, true);
263                                         shader_eval_surface(kg, sd, state, 0.0f, PATH_RAY_SHADOW, SHADER_CONTEXT_SHADOW);
264                                         path_state_modify_bounce(state, false);
265
266                                         throughput *= shader_bsdf_transparency(kg, sd);
267                                 }
268
269                                 if(is_zero(throughput))
270                                         return true;
271
272                                 /* move ray forward */
273                                 ray->P = ray_offset(ccl_fetch(sd, P), -ccl_fetch(sd, Ng));
274                                 if(ray->t != FLT_MAX)
275                                         ray->D = normalize_len(Pend - ray->P, &ray->t);
276
277 #ifdef __VOLUME__
278                                 /* exit/enter volume */
279                                 kernel_volume_stack_enter_exit(kg, sd, ps.volume_stack);
280 #endif
281
282                                 bounce++;
283                         }
284                 }
285         }
286 #ifdef __VOLUME__
287         else if(!blocked && state->volume_stack[0].shader != SHADER_NONE) {
288                 /* apply attenuation from current volume shader */
289                 kernel_volume_shadow(kg, state, ray, shadow);
290         }
291 #endif
292 #endif
293
294         return blocked;
295 }
296
297 #endif
298
299 CCL_NAMESPACE_END
300