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
path_state_init(KernelGlobals * kg,ShaderData * stack_sd,ccl_addr_space PathState * state,uint rng_hash,int sample,ccl_addr_space Ray * ray)19 ccl_device_inline void path_state_init(KernelGlobals *kg,
20 ShaderData *stack_sd,
21 ccl_addr_space PathState *state,
22 uint rng_hash,
23 int sample,
24 ccl_addr_space Ray *ray)
25 {
26 state->flag = PATH_RAY_CAMERA | PATH_RAY_MIS_SKIP | PATH_RAY_TRANSPARENT_BACKGROUND;
27
28 state->rng_hash = rng_hash;
29 state->rng_offset = PRNG_BASE_NUM;
30 state->sample = sample;
31 state->num_samples = kernel_data.integrator.aa_samples;
32 state->branch_factor = 1.0f;
33
34 state->bounce = 0;
35 state->diffuse_bounce = 0;
36 state->glossy_bounce = 0;
37 state->transmission_bounce = 0;
38 state->transparent_bounce = 0;
39
40 #ifdef __DENOISING_FEATURES__
41 if (kernel_data.film.pass_denoising_data) {
42 state->flag |= PATH_RAY_STORE_SHADOW_INFO;
43 state->denoising_feature_weight = 1.0f;
44 state->denoising_feature_throughput = make_float3(1.0f, 1.0f, 1.0f);
45 }
46 else {
47 state->denoising_feature_weight = 0.0f;
48 state->denoising_feature_throughput = make_float3(0.0f, 0.0f, 0.0f);
49 }
50 #endif /* __DENOISING_FEATURES__ */
51
52 state->min_ray_pdf = FLT_MAX;
53 state->ray_pdf = 0.0f;
54 #ifdef __LAMP_MIS__
55 state->ray_t = 0.0f;
56 #endif
57
58 #ifdef __VOLUME__
59 state->volume_bounce = 0;
60 state->volume_bounds_bounce = 0;
61
62 if (kernel_data.integrator.use_volumes) {
63 /* Initialize volume stack with volume we are inside of. */
64 kernel_volume_stack_init(kg, stack_sd, state, ray, state->volume_stack);
65 }
66 else {
67 state->volume_stack[0].shader = SHADER_NONE;
68 }
69 #endif
70 }
71
path_state_next(KernelGlobals * kg,ccl_addr_space PathState * state,int label)72 ccl_device_inline void path_state_next(KernelGlobals *kg,
73 ccl_addr_space PathState *state,
74 int label)
75 {
76 /* ray through transparent keeps same flags from previous ray and is
77 * not counted as a regular bounce, transparent has separate max */
78 if (label & LABEL_TRANSPARENT) {
79 state->flag |= PATH_RAY_TRANSPARENT;
80 state->transparent_bounce++;
81 if (state->transparent_bounce >= kernel_data.integrator.transparent_max_bounce) {
82 state->flag |= PATH_RAY_TERMINATE_IMMEDIATE;
83 }
84
85 if (!kernel_data.integrator.transparent_shadows)
86 state->flag |= PATH_RAY_MIS_SKIP;
87
88 /* random number generator next bounce */
89 state->rng_offset += PRNG_BOUNCE_NUM;
90
91 return;
92 }
93
94 state->bounce++;
95 if (state->bounce >= kernel_data.integrator.max_bounce) {
96 state->flag |= PATH_RAY_TERMINATE_AFTER_TRANSPARENT;
97 }
98
99 state->flag &= ~(PATH_RAY_ALL_VISIBILITY | PATH_RAY_MIS_SKIP);
100
101 #ifdef __VOLUME__
102 if (label & LABEL_VOLUME_SCATTER) {
103 /* volume scatter */
104 state->flag |= PATH_RAY_VOLUME_SCATTER;
105 state->flag &= ~PATH_RAY_TRANSPARENT_BACKGROUND;
106
107 state->volume_bounce++;
108 if (state->volume_bounce >= kernel_data.integrator.max_volume_bounce) {
109 state->flag |= PATH_RAY_TERMINATE_AFTER_TRANSPARENT;
110 }
111 }
112 else
113 #endif
114 {
115 /* surface reflection/transmission */
116 if (label & LABEL_REFLECT) {
117 state->flag |= PATH_RAY_REFLECT;
118 state->flag &= ~PATH_RAY_TRANSPARENT_BACKGROUND;
119
120 if (label & LABEL_DIFFUSE) {
121 state->diffuse_bounce++;
122 if (state->diffuse_bounce >= kernel_data.integrator.max_diffuse_bounce) {
123 state->flag |= PATH_RAY_TERMINATE_AFTER_TRANSPARENT;
124 }
125 }
126 else {
127 state->glossy_bounce++;
128 if (state->glossy_bounce >= kernel_data.integrator.max_glossy_bounce) {
129 state->flag |= PATH_RAY_TERMINATE_AFTER_TRANSPARENT;
130 }
131 }
132 }
133 else {
134 kernel_assert(label & LABEL_TRANSMIT);
135
136 state->flag |= PATH_RAY_TRANSMIT;
137
138 if (!(label & LABEL_TRANSMIT_TRANSPARENT)) {
139 state->flag &= ~PATH_RAY_TRANSPARENT_BACKGROUND;
140 }
141
142 state->transmission_bounce++;
143 if (state->transmission_bounce >= kernel_data.integrator.max_transmission_bounce) {
144 state->flag |= PATH_RAY_TERMINATE_AFTER_TRANSPARENT;
145 }
146 }
147
148 /* diffuse/glossy/singular */
149 if (label & LABEL_DIFFUSE) {
150 state->flag |= PATH_RAY_DIFFUSE | PATH_RAY_DIFFUSE_ANCESTOR;
151 }
152 else if (label & LABEL_GLOSSY) {
153 state->flag |= PATH_RAY_GLOSSY;
154 }
155 else {
156 kernel_assert(label & LABEL_SINGULAR);
157 state->flag |= PATH_RAY_GLOSSY | PATH_RAY_SINGULAR | PATH_RAY_MIS_SKIP;
158 }
159 }
160
161 /* random number generator next bounce */
162 state->rng_offset += PRNG_BOUNCE_NUM;
163
164 #ifdef __DENOISING_FEATURES__
165 if ((state->denoising_feature_weight == 0.0f) && !(state->flag & PATH_RAY_SHADOW_CATCHER)) {
166 state->flag &= ~PATH_RAY_STORE_SHADOW_INFO;
167 }
168 #endif
169 }
170
171 #ifdef __VOLUME__
path_state_volume_next(KernelGlobals * kg,ccl_addr_space PathState * state)172 ccl_device_inline bool path_state_volume_next(KernelGlobals *kg, ccl_addr_space PathState *state)
173 {
174 /* For volume bounding meshes we pass through without counting transparent
175 * bounces, only sanity check in case self intersection gets us stuck. */
176 state->volume_bounds_bounce++;
177 if (state->volume_bounds_bounce > VOLUME_BOUNDS_MAX) {
178 return false;
179 }
180
181 /* Random number generator next bounce. */
182 if (state->volume_bounds_bounce > 1) {
183 state->rng_offset += PRNG_BOUNCE_NUM;
184 }
185
186 return true;
187 }
188 #endif
189
path_state_ray_visibility(KernelGlobals * kg,ccl_addr_space PathState * state)190 ccl_device_inline uint path_state_ray_visibility(KernelGlobals *kg,
191 ccl_addr_space PathState *state)
192 {
193 uint flag = state->flag & PATH_RAY_ALL_VISIBILITY;
194
195 /* for visibility, diffuse/glossy are for reflection only */
196 if (flag & PATH_RAY_TRANSMIT)
197 flag &= ~(PATH_RAY_DIFFUSE | PATH_RAY_GLOSSY);
198 /* todo: this is not supported as its own ray visibility yet */
199 if (state->flag & PATH_RAY_VOLUME_SCATTER)
200 flag |= PATH_RAY_DIFFUSE;
201
202 return flag;
203 }
204
path_state_continuation_probability(KernelGlobals * kg,ccl_addr_space PathState * state,const float3 throughput)205 ccl_device_inline float path_state_continuation_probability(KernelGlobals *kg,
206 ccl_addr_space PathState *state,
207 const float3 throughput)
208 {
209 if (state->flag & PATH_RAY_TERMINATE_IMMEDIATE) {
210 /* Ray is to be terminated immediately. */
211 return 0.0f;
212 }
213 else if (state->flag & PATH_RAY_TRANSPARENT) {
214 /* Do at least specified number of bounces without RR. */
215 if (state->transparent_bounce <= kernel_data.integrator.transparent_min_bounce) {
216 return 1.0f;
217 }
218 #ifdef __SHADOW_TRICKS__
219 /* Exception for shadow catcher not working correctly with RR. */
220 else if ((state->flag & PATH_RAY_SHADOW_CATCHER) && (state->transparent_bounce <= 8)) {
221 return 1.0f;
222 }
223 #endif
224 }
225 else {
226 /* Do at least specified number of bounces without RR. */
227 if (state->bounce <= kernel_data.integrator.min_bounce) {
228 return 1.0f;
229 }
230 #ifdef __SHADOW_TRICKS__
231 /* Exception for shadow catcher not working correctly with RR. */
232 else if ((state->flag & PATH_RAY_SHADOW_CATCHER) && (state->bounce <= 3)) {
233 return 1.0f;
234 }
235 #endif
236 }
237
238 /* Probabilistic termination: use sqrt() to roughly match typical view
239 * transform and do path termination a bit later on average. */
240 return min(sqrtf(max3(fabs(throughput)) * state->branch_factor), 1.0f);
241 }
242
243 /* TODO(DingTo): Find more meaningful name for this */
path_state_modify_bounce(ccl_addr_space PathState * state,bool increase)244 ccl_device_inline void path_state_modify_bounce(ccl_addr_space PathState *state, bool increase)
245 {
246 /* Modify bounce temporarily for shader eval */
247 if (increase)
248 state->bounce += 1;
249 else
250 state->bounce -= 1;
251 }
252
path_state_ao_bounce(KernelGlobals * kg,ccl_addr_space PathState * state)253 ccl_device_inline bool path_state_ao_bounce(KernelGlobals *kg, ccl_addr_space PathState *state)
254 {
255 if (state->bounce <= kernel_data.integrator.ao_bounces) {
256 return false;
257 }
258
259 int bounce = state->bounce - state->transmission_bounce - (state->glossy_bounce > 0);
260 return (bounce > kernel_data.integrator.ao_bounces);
261 }
262
path_state_branch(ccl_addr_space PathState * state,int branch,int num_branches)263 ccl_device_inline void path_state_branch(ccl_addr_space PathState *state,
264 int branch,
265 int num_branches)
266 {
267 if (num_branches > 1) {
268 /* Path is splitting into a branch, adjust so that each branch
269 * still gets a unique sample from the same sequence. */
270 state->sample = state->sample * num_branches + branch;
271 state->num_samples = state->num_samples * num_branches;
272 state->branch_factor *= num_branches;
273 }
274 }
275
276 CCL_NAMESPACE_END
277