Blender V5.0
shade_background.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#pragma once
6
9
13
14#include "kernel/light/light.h"
15#include "kernel/light/sample.h"
16
18
20
24{
25 const int shader = kernel_data.background.surface_shader;
26 const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
27
28 /* Use visibility flag to skip lights. */
29 if (!is_light_shader_visible_to_path(shader, path_flag)) {
30 return zero_spectrum();
31 }
32
33 /* Use fast constant background color if available. */
35 if (surface_shader_constant_emission(kg, shader, &L)) {
36 return L;
37 }
38
39 /* Evaluate background shader. */
40
41 /* TODO: does aliasing like this break automatic SoA in CUDA?
42 * Should we instead store closures separate from ShaderData? */
43 ShaderDataTinyStorage emission_sd_storage;
44 ccl_private ShaderData *emission_sd = AS_SHADER_DATA(&emission_sd_storage);
45
48 emission_sd,
51 INTEGRATOR_STATE(state, ray, time));
52
53 PROFILING_SHADER(emission_sd->object, emission_sd->shader);
56 kg, state, emission_sd, render_buffer, path_flag | PATH_RAY_EMISSION);
57
58 return surface_shader_background(emission_sd);
59}
60
64{
65 /* Accumulate transparency for transparent background. We can skip background
66 * shader evaluation unless a background pass is used. */
67 bool eval_background = true;
68 float transparent = 0.0f;
69
70 const int path_flag = INTEGRATOR_STATE(state, path, flag);
71 const bool is_transparent_background_ray = kernel_data.background.transparent &&
73
74 if (is_transparent_background_ray) {
75 transparent = average(INTEGRATOR_STATE(state, path, throughput));
76
77#ifdef __PASSES__
78 eval_background = (kernel_data.film.light_pass_flag & PASSMASK(BACKGROUND));
79#else
80 eval_background = false;
81#endif
82 }
83
84#ifdef __MNEE__
86 if (kernel_data.background.use_mis) {
87 for (int lamp = 0; lamp < kernel_data.integrator.num_lights; lamp++) {
88 /* This path should have been resolved with mnee, it will
89 * generate a firefly for small lights since it is improbable. */
90 const ccl_global KernelLight *klight = &kernel_data_fetch(lights, lamp);
91 if (klight->type == LIGHT_BACKGROUND && klight->use_caustics) {
92 eval_background = false;
93 break;
94 }
95 }
96 }
97 }
98#endif /* __MNEE__ */
99
100 /* Evaluate background shader. */
102
103 if (eval_background) {
105
106 /* When using the ao bounces approximation, adjust background
107 * shader intensity with ao factor. */
108 if (path_state_ao_bounce(kg, state)) {
109 L *= kernel_data.integrator.ao_bounces_factor;
110 }
111
112 /* Background MIS weights. */
113 const float mis_weight = light_sample_mis_weight_forward_background(kg, state, path_flag);
114
115 guiding_record_background(kg, state, L, mis_weight);
116 L *= mis_weight;
117 }
118
119 /* Write to render buffer. */
120 film_write_background(kg, state, L, transparent, is_transparent_background_ray, render_buffer);
122}
123
127{
128 const float3 ray_D = INTEGRATOR_STATE(state, ray, D);
129 const float ray_time = INTEGRATOR_STATE(state, ray, time);
131 for (int lamp = 0; lamp < kernel_data.integrator.num_lights; lamp++) {
132 if (distant_light_sample_from_intersection(kg, ray_D, lamp, &ls)) {
133 /* Use visibility flag to skip lights. */
134#ifdef __PASSES__
135 const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
136 if (!is_light_shader_visible_to_path(ls.shader, path_flag)) {
137 continue;
138 }
139#endif
140
141 const ccl_global KernelLight *klight = &kernel_data_fetch(lights, lamp);
142#ifdef __LIGHT_LINKING__
143 if (!light_link_light_match(kg, light_link_receiver_forward(kg, state), klight->object_id) &&
144 !(path_flag & PATH_RAY_CAMERA))
145 {
146 continue;
147 }
148#endif
149#ifdef __SHADOW_LINKING__
150 if (kernel_data_fetch(objects, klight->object_id).shadow_set_membership !=
152 {
153 continue;
154 }
155#endif
156
157#ifdef __MNEE__
159 /* This path should have been resolved with mnee, it will
160 * generate a firefly for small lights since it is improbable. */
161 if (klight->use_caustics) {
162 continue;
163 }
164 }
165#endif /* __MNEE__ */
166
167 /* Evaluate light shader. */
168 /* TODO: does aliasing like this break automatic SoA in CUDA? */
169 ShaderDataTinyStorage emission_sd_storage;
170 ccl_private ShaderData *emission_sd = AS_SHADER_DATA(&emission_sd_storage);
171 const Spectrum light_eval = light_sample_shader_eval(kg, state, emission_sd, &ls, ray_time);
172 if (is_zero(light_eval)) {
173 continue;
174 }
175
176 /* MIS weighting. */
177 const float mis_weight = light_sample_mis_weight_forward_distant(kg, state, path_flag, &ls);
178
179 /* Write to render buffer. */
180 guiding_record_background(kg, state, light_eval, mis_weight);
181 film_write_surface_emission(kg, state, light_eval, mis_weight, render_buffer, ls.group);
182 }
183 }
184}
185
189{
191
192 /* TODO: unify these in a single loop to only have a single shader evaluation call. */
195
196#ifdef __SHADOW_CATCHER__
198 /* Special case for shadow catcher where we want to fill the background pass
199 * behind the shadow catcher but also continue tracing the path. */
201 integrator_intersect_next_kernel_after_shadow_catcher_background<
203 return;
204 }
205#endif
206
208}
209
#define D
CCL_NAMESPACE_BEGIN ccl_device_noinline_cpu Spectrum light_sample_shader_eval(KernelGlobals kg, IntegratorState state, ccl_private ShaderData *ccl_restrict emission_sd, ccl_private LightSample *ccl_restrict ls, const float time)
ccl_device_inline float light_sample_mis_weight_forward_background(KernelGlobals kg, IntegratorState state, const uint32_t path_flag)
ccl_device_inline float light_sample_mis_weight_forward_distant(KernelGlobals kg, IntegratorState state, const uint32_t path_flag, const ccl_private LightSample *ls)
ccl_device_inline void film_write_data_passes_background(KernelGlobals kg, IntegratorState state, ccl_global float *ccl_restrict render_buffer)
#define kernel_data
#define ccl_restrict
#define ccl_optional_struct_init
#define kernel_data_fetch(name, index)
#define AS_SHADER_DATA(shader_data_tiny_storage)
#define zero_spectrum
#define ccl_private
const ThreadKernelGlobalsCPU * KernelGlobals
#define ccl_device_inline
#define PASSMASK(pass)
#define LIGHT_LINK_MASK_ALL
#define ccl_global
#define CCL_NAMESPACE_END
ccl_device bool distant_light_sample_from_intersection(KernelGlobals kg, const float3 ray_D, const int lamp, ccl_private LightSample *ccl_restrict ls)
Definition distant.h:86
ccl_gpu_kernel_postfix ccl_global KernelWorkTile const int ccl_global float * render_buffer
ccl_device_forceinline void guiding_record_background(KernelGlobals kg, IntegratorState state, const Spectrum L, const float mis_weight)
ccl_device_inline bool light_link_light_match(KernelGlobals kg, const int object_receiver, const int object_emitter)
ccl_device_inline int light_link_receiver_forward(KernelGlobals kg, IntegratorState state)
@ PATH_MNEE_CULL_LIGHT_CONNECTION
ShaderData ShaderDataTinyStorage
@ PATH_RAY_EMISSION
@ PATH_RAY_TRANSPARENT_BACKGROUND
@ PATH_RAY_SHADOW_CATCHER_BACKGROUND
@ PATH_RAY_CAMERA
@ LIGHT_BACKGROUND
@ DEVICE_KERNEL_INTEGRATOR_SHADE_BACKGROUND
ccl_device_inline bool is_light_shader_visible_to_path(const int shader, const uint32_t path_flag)
ccl_device_inline void film_write_background(KernelGlobals kg, ConstIntegratorState state, const Spectrum L, const float transparent, const bool is_transparent_background_ray, ccl_global float *ccl_restrict render_buffer)
ccl_device_inline void film_write_surface_emission(KernelGlobals kg, ConstIntegratorState state, const Spectrum L, const float mis_weight, ccl_global float *ccl_restrict render_buffer, const int lightgroup=LIGHTGROUP_NONE)
ccl_device_inline bool is_zero(const float2 a)
static ulong state[N]
#define L
#define PROFILING_INIT_FOR_SHADER(kg, event)
#define PROFILING_EVENT(event)
#define PROFILING_SHADER(object, shader)
#define PROFILING_INIT(kg, event)
float average(point a)
Definition node_math.h:144
ccl_device_inline bool path_state_ao_bounce(KernelGlobals kg, ConstIntegratorState state)
Definition path_state.h:301
@ PROFILING_SHADE_LIGHT_SETUP
Definition profiling.h:42
@ PROFILING_SHADE_LIGHT_EVAL
Definition profiling.h:43
#define ccl_device
CCL_NAMESPACE_BEGIN ccl_device Spectrum integrator_eval_background_shader(KernelGlobals kg, IntegratorState state, ccl_global float *ccl_restrict render_buffer)
ccl_device_inline void integrate_background(KernelGlobals kg, IntegratorState state, ccl_global float *ccl_restrict render_buffer)
ccl_device void integrator_shade_background(KernelGlobals kg, IntegratorState state, ccl_global float *ccl_restrict render_buffer)
ccl_device_inline void integrate_distant_lights(KernelGlobals kg, IntegratorState state, ccl_global float *ccl_restrict render_buffer)
ccl_device_inline void shader_setup_from_background(KernelGlobals kg, ccl_private ShaderData *ccl_restrict sd, const float3 ray_P, const float3 ray_D, const float ray_time)
#define INTEGRATOR_STATE_WRITE(state, nested_struct, member)
Definition state.h:236
#define INTEGRATOR_STATE(state, nested_struct, member)
Definition state.h:235
IntegratorStateCPU * IntegratorState
Definition state.h:228
ccl_device_forceinline void integrator_path_terminate(KernelGlobals kg, IntegratorState state, ccl_global float *ccl_restrict render_buffer, const DeviceKernel current_kernel)
Definition state_flow.h:203
ccl_device void surface_shader_eval(KernelGlobals kg, ConstIntegratorGenericState state, ccl_private ShaderData *ccl_restrict sd, ccl_global float *ccl_restrict buffer, const uint32_t path_flag, bool use_caustics_storage=false)
ccl_device Spectrum surface_shader_background(const ccl_private ShaderData *sd)
ccl_device bool surface_shader_constant_emission(KernelGlobals kg, const int shader, ccl_private Spectrum *eval)
float3 Spectrum
uint8_t flag
Definition wm_window.cc:145