Cycles Volume Render: support for rendering of homogeneous volume with absorption.
[blender.git] / intern / cycles / kernel / kernel_path_state.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 typedef struct PathState {
20         int flag;
21         int bounce;
22
23         int diffuse_bounce;
24         int glossy_bounce;
25         int transmission_bounce;
26         int transparent_bounce;
27
28 #ifdef __VOLUME__
29         int volume_shader;
30 #endif
31 } PathState;
32
33 ccl_device_inline void path_state_init(KernelGlobals *kg, PathState *state)
34 {
35         state->flag = PATH_RAY_CAMERA|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP;
36         state->bounce = 0;
37         state->diffuse_bounce = 0;
38         state->glossy_bounce = 0;
39         state->transmission_bounce = 0;
40         state->transparent_bounce = 0;
41
42 #ifdef __VOLUME__
43         /* todo: this assumes camera is always in air, need to detect when it isn't */
44         state->volume_shader = kernel_data.background.volume_shader;
45 #endif
46 }
47
48 ccl_device_inline void path_state_next(KernelGlobals *kg, PathState *state, int label)
49 {
50         /* ray through transparent keeps same flags from previous ray and is
51          * not counted as a regular bounce, transparent has separate max */
52         if(label & LABEL_TRANSPARENT) {
53                 state->flag |= PATH_RAY_TRANSPARENT;
54                 state->transparent_bounce++;
55
56                 if(!kernel_data.integrator.transparent_shadows)
57                         state->flag |= PATH_RAY_MIS_SKIP;
58
59                 return;
60         }
61
62         state->bounce++;
63
64         /* reflection/transmission */
65         if(label & LABEL_REFLECT) {
66                 state->flag |= PATH_RAY_REFLECT;
67                 state->flag &= ~(PATH_RAY_TRANSMIT|PATH_RAY_CAMERA|PATH_RAY_TRANSPARENT);
68
69                 if(label & LABEL_DIFFUSE)
70                         state->diffuse_bounce++;
71                 else
72                         state->glossy_bounce++;
73         }
74         else {
75                 kernel_assert(label & LABEL_TRANSMIT);
76
77                 state->flag |= PATH_RAY_TRANSMIT;
78                 state->flag &= ~(PATH_RAY_REFLECT|PATH_RAY_CAMERA|PATH_RAY_TRANSPARENT);
79
80                 state->transmission_bounce++;
81         }
82
83         /* diffuse/glossy/singular */
84         if(label & LABEL_DIFFUSE) {
85                 state->flag |= PATH_RAY_DIFFUSE|PATH_RAY_DIFFUSE_ANCESTOR;
86                 state->flag &= ~(PATH_RAY_GLOSSY|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP);
87         }
88         else if(label & LABEL_GLOSSY) {
89                 state->flag |= PATH_RAY_GLOSSY|PATH_RAY_GLOSSY_ANCESTOR;
90                 state->flag &= ~(PATH_RAY_DIFFUSE|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP);
91         }
92         else {
93                 kernel_assert(label & LABEL_SINGULAR);
94
95                 state->flag |= PATH_RAY_GLOSSY|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP;
96                 state->flag &= ~PATH_RAY_DIFFUSE;
97         }
98 }
99
100 ccl_device_inline uint path_state_ray_visibility(KernelGlobals *kg, PathState *state)
101 {
102         uint flag = state->flag & PATH_RAY_ALL_VISIBILITY;
103
104         /* for visibility, diffuse/glossy are for reflection only */
105         if(flag & PATH_RAY_TRANSMIT)
106                 flag &= ~(PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY);
107         /* for camera visibility, use render layer flags */
108         if(flag & PATH_RAY_CAMERA)
109                 flag |= kernel_data.integrator.layer_flag;
110
111         return flag;
112 }
113
114 ccl_device_inline float path_state_terminate_probability(KernelGlobals *kg, PathState *state, const float3 throughput)
115 {
116         if(state->flag & PATH_RAY_TRANSPARENT) {
117                 /* transparent rays treated separately */
118                 if(state->transparent_bounce >= kernel_data.integrator.transparent_max_bounce)
119                         return 0.0f;
120                 else if(state->transparent_bounce <= kernel_data.integrator.transparent_min_bounce)
121                         return 1.0f;
122         }
123         else {
124                 /* other rays */
125                 if((state->bounce >= kernel_data.integrator.max_bounce) ||
126                    (state->diffuse_bounce >= kernel_data.integrator.max_diffuse_bounce) ||
127                    (state->glossy_bounce >= kernel_data.integrator.max_glossy_bounce) ||
128                    (state->transmission_bounce >= kernel_data.integrator.max_transmission_bounce))
129                 {
130                         return 0.0f;
131                 }
132                 else if(state->bounce <= kernel_data.integrator.min_bounce) {
133                         return 1.0f;
134                 }
135         }
136
137         /* probalistic termination */
138         return average(throughput); /* todo: try using max here */
139 }
140
141 CCL_NAMESPACE_END
142