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