Cycles Volume Render: support for rendering of homogeneous volume with absorption.
[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 ccl_device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ray, float3 *shadow)
20 {
21         *shadow = make_float3(1.0f, 1.0f, 1.0f);
22
23         if(ray->t == 0.0f)
24                 return false;
25
26         Intersection isect;
27 #ifdef __HAIR__
28         bool result = scene_intersect(kg, ray, PATH_RAY_SHADOW_OPAQUE, &isect, NULL, 0.0f, 0.0f);
29 #else
30         bool result = scene_intersect(kg, ray, PATH_RAY_SHADOW_OPAQUE, &isect);
31 #endif
32
33 #ifdef __TRANSPARENT_SHADOWS__
34         if(result && kernel_data.integrator.transparent_shadows) {
35                 /* transparent shadows work in such a way to try to minimize overhead
36                  * in cases where we don't need them. after a regular shadow ray is
37                  * cast we check if the hit primitive was potentially transparent, and
38                  * only in that case start marching. this gives on extra ray cast for
39                  * the cases were we do want transparency.
40                  *
41                  * also note that for this to work correct, multi close sampling must
42                  * be used, since we don't pass a random number to shader_eval_surface */
43                 if(shader_transparent_shadow(kg, &isect)) {
44                         float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
45                         float3 Pend = ray->P + ray->D*ray->t;
46                         int bounce = state->transparent_bounce;
47
48 #ifdef __VOLUME__
49                         int volume_shader = state->volume_shader;
50 #endif
51
52                         for(;;) {
53                                 if(bounce >= kernel_data.integrator.transparent_max_bounce) {
54                                         return true;
55                                 }
56                                 else if(bounce >= kernel_data.integrator.transparent_min_bounce) {
57                                         /* todo: get random number somewhere for probabilistic terminate */
58 #if 0
59                                         float probability = average(throughput);
60                                         float terminate = 0.0f;
61
62                                         if(terminate >= probability)
63                                                 return true;
64
65                                         throughput /= probability;
66 #endif
67                                 }
68
69 #ifdef __HAIR__
70                                 if(!scene_intersect(kg, ray, PATH_RAY_SHADOW_TRANSPARENT, &isect, NULL, 0.0f, 0.0f)) {
71 #else
72                                 if(!scene_intersect(kg, ray, PATH_RAY_SHADOW_TRANSPARENT, &isect)) {
73 #endif
74
75 #ifdef __VOLUME__
76                                         /* attenuation for last line segment towards light */
77                                         if(volume_shader != SHADER_NO_ID)
78                                                 throughput *= kernel_volume_get_shadow_attenuation(kg, state, ray, volume_shader);
79 #endif
80
81                                         *shadow *= throughput;
82                                         return false;
83                                 }
84
85                                 if(!shader_transparent_shadow(kg, &isect))
86                                         return true;
87
88 #ifdef __VOLUME__
89                                 /* attenuation between last surface and next surface */
90                                 if(volume_shader != SHADER_NO_ID) {
91                                         Ray segment_ray = *ray;
92                                         segment_ray.t = isect.t;
93                                         throughput *= kernel_volume_get_shadow_attenuation(kg, state, &segment_ray, volume_shader);
94                                 }
95 #endif
96
97                                 /* setup shader data at surface */
98                                 ShaderData sd;
99                                 shader_setup_from_ray(kg, &sd, &isect, ray, state->bounce+1);
100
101                                 /* attenuation from transparent surface */
102                                 if(!(sd.flag & SD_HAS_ONLY_VOLUME)) {
103                                         shader_eval_surface(kg, &sd, 0.0f, PATH_RAY_SHADOW, SHADER_CONTEXT_SHADOW);
104                                         throughput *= shader_bsdf_transparency(kg, &sd);
105                                 }
106
107                                 /* move ray forward */
108                                 ray->P = ray_offset(sd.P, -sd.Ng);
109                                 if(ray->t != FLT_MAX)
110                                         ray->D = normalize_len(Pend - ray->P, &ray->t);
111
112 #ifdef __VOLUME__
113                                 /* exit/enter volume */
114                                 if(sd.flag & SD_BACKFACING)
115                                         volume_shader = kernel_data.background.volume_shader;
116                                 else
117                                         volume_shader = (sd.flag & SD_HAS_VOLUME)? sd.shader: SHADER_NO_ID;
118 #endif
119
120                                 bounce++;
121                         }
122                 }
123         }
124 #ifdef __VOLUME__
125         else if(!result && state->volume_shader != SHADER_NO_ID) {
126                 /* apply attenuation from current volume shader */
127                 *shadow *= kernel_volume_get_shadow_attenuation(kg, state, ray, state->volume_shader);
128         }
129 #endif
130 #endif
131
132         return result;
133 }
134
135 CCL_NAMESPACE_END
136