Blender V5.0
shade_shadow.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
11
13
15
20
21#ifdef __TRANSPARENT_SHADOWS__
22ccl_device_inline Spectrum integrate_transparent_surface_shadow(KernelGlobals kg,
24 const int hit)
25{
27
28 /* TODO: does aliasing like this break automatic SoA in CUDA?
29 * Should we instead store closures separate from ShaderData?
30 *
31 * TODO: is it better to declare this outside the loop or keep it local
32 * so the compiler can see there is no dependency between iterations? */
33 ShaderDataTinyStorage shadow_sd_storage;
34 ccl_private ShaderData *shadow_sd = AS_SHADER_DATA(&shadow_sd_storage);
35
36 /* Setup shader data at surface. */
39
42
43 shader_setup_from_ray(kg, shadow_sd, &ray, &isect);
44
45 /* Evaluate shader. */
46 if (!(shadow_sd->flag & SD_HAS_ONLY_VOLUME)) {
48 kg, state, shadow_sd, nullptr, PATH_RAY_SHADOW);
49 }
50 else {
51 INTEGRATOR_STATE_WRITE(state, shadow_path, volume_bounds_bounce) += 1;
52 }
53
54# ifdef __VOLUME__
55 /* Exit/enter volume. */
56 volume_stack_enter_exit<true>(kg, state, shadow_sd);
57# endif
58
59 /* Disable transparent shadows for ray portals */
60 if (shadow_sd->flag & SD_RAY_PORTAL) {
61 return zero_spectrum();
62 }
63
64 /* Compute transparency from closures. */
65 return surface_shader_transparency(shadow_sd);
66}
67
68# ifdef __VOLUME__
69ccl_device_inline void integrate_transparent_volume_shadow(KernelGlobals kg,
71 const int hit,
72 const int num_recorded_hits,
74 throughput)
75{
77
78 /* TODO: deduplicate with surface, or does it not matter for memory usage? */
79 ShaderDataTinyStorage shadow_sd_storage;
80 ccl_private ShaderData *shadow_sd = AS_SHADER_DATA(&shadow_sd_storage);
81
82 /* Setup shader data. */
85 ray.self.object = OBJECT_NONE;
86 ray.self.prim = PRIM_NONE;
87 ray.self.light_object = OBJECT_NONE;
88 ray.self.light_prim = PRIM_NONE;
89 /* Modify ray position and length to match current segment. */
90 ray.tmin = (hit == 0) ? ray.tmin : INTEGRATOR_STATE_ARRAY(state, shadow_isect, hit - 1, t);
91 ray.tmax = (hit < num_recorded_hits) ? INTEGRATOR_STATE_ARRAY(state, shadow_isect, hit, t) :
92 ray.tmax;
93
94 /* `object` is only needed for light tree with light linking, it is irrelevant for shadow. */
95 shader_setup_from_volume(shadow_sd, &ray, OBJECT_NONE);
96
97 if (kernel_data.integrator.volume_ray_marching) {
98 const float step_size = volume_stack_step_size<true>(kg, state);
99 volume_shadow_ray_marching(kg, state, &ray, shadow_sd, throughput, step_size);
100 }
101 else {
102 volume_shadow_null_scattering(kg, state, &ray, shadow_sd, throughput);
103 }
104}
105# endif
106
107ccl_device_inline bool integrate_transparent_shadow(KernelGlobals kg,
109 const uint num_hits)
110{
111 /* Accumulate shadow for transparent surfaces. */
112 const uint num_recorded_hits = min(num_hits, (uint)INTEGRATOR_SHADOW_ISECT_SIZE);
113
114 /* Plus one to account for world volume, which has no boundary to hit but casts shadows. */
115 for (uint hit = 0; hit < num_recorded_hits + 1; hit++) {
116 /* Volume shaders. */
117 if (hit < num_recorded_hits || !shadow_intersections_has_remaining(num_hits)) {
118# ifdef __VOLUME__
119 if (!integrator_state_shadow_volume_stack_is_empty(kg, state)) {
120 Spectrum throughput = INTEGRATOR_STATE(state, shadow_path, throughput);
121 integrate_transparent_volume_shadow(kg, state, hit, num_recorded_hits, &throughput);
122 if (is_zero(throughput)) {
123 return true;
124 }
125
126 INTEGRATOR_STATE_WRITE(state, shadow_path, throughput) = throughput;
127 }
128# endif
129 }
130
131 /* Surface shaders. */
132 if (hit < num_recorded_hits) {
133 const Spectrum shadow = integrate_transparent_surface_shadow(kg, state, hit);
134 const Spectrum throughput = INTEGRATOR_STATE(state, shadow_path, throughput) * shadow;
135 if (is_zero(throughput)) {
136 return true;
137 }
138
139 INTEGRATOR_STATE_WRITE(state, shadow_path, throughput) = throughput;
140 INTEGRATOR_STATE_WRITE(state, shadow_path, transparent_bounce) += 1;
141 INTEGRATOR_STATE_WRITE(state, shadow_path, rng_offset) += PRNG_BOUNCE_NUM;
142 }
143
144 if (INTEGRATOR_STATE(state, shadow_path, volume_bounds_bounce) > VOLUME_BOUNDS_MAX) {
145 return true;
146 }
147
148 /* Note we do not need to check max_transparent_bounce here, the number
149 * of intersections is already limited and made opaque in the
150 * INTERSECT_SHADOW kernel. */
151 }
152
154 /* There are more hits that we could not recorded due to memory usage,
155 * adjust ray to intersect again from the last hit. */
156 const float last_hit_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, num_recorded_hits - 1, t);
157 INTEGRATOR_STATE_WRITE(state, shadow_ray, tmin) = intersection_t_offset(last_hit_t);
158 }
159
160 return false;
161}
162#endif /* __TRANSPARENT_SHADOWS__ */
163
167{
169 const uint num_hits = INTEGRATOR_STATE(state, shadow_path, num_hits);
170
171#ifdef __TRANSPARENT_SHADOWS__
172 /* Evaluate transparent shadows. */
173 const bool opaque = integrate_transparent_shadow(kg, state, num_hits);
174 if (opaque) {
176 return;
177 }
178#endif
179
181 /* More intersections to find, continue shadow ray. */
184 return;
185 }
186
190}
191
unsigned int uint
ccl_device_forceinline float intersection_t_offset(const float t)
#define kernel_data
#define ccl_restrict
#define VOLUME_BOUNDS_MAX
#define ccl_optional_struct_init
#define AS_SHADER_DATA(shader_data_tiny_storage)
#define PRIM_NONE
#define INTEGRATOR_SHADOW_ISECT_SIZE
#define zero_spectrum
#define OBJECT_NONE
#define ccl_private
const ThreadKernelGlobalsCPU * KernelGlobals
#define ccl_device_inline
#define ccl_global
#define CCL_NAMESPACE_END
ccl_gpu_kernel_postfix ccl_global KernelWorkTile const int ccl_global float * render_buffer
ccl_device_forceinline void guiding_record_direct_light(KernelGlobals kg, IntegratorShadowState state)
@ SD_HAS_ONLY_VOLUME
@ SD_RAY_PORTAL
ShaderData ShaderDataTinyStorage
@ PRNG_BOUNCE_NUM
@ PATH_RAY_SHADOW
@ DEVICE_KERNEL_INTEGRATOR_SHADE_SHADOW
@ DEVICE_KERNEL_INTEGRATOR_INTERSECT_SHADOW
ccl_device_inline void film_write_direct_light(KernelGlobals kg, ConstIntegratorShadowState state, ccl_global float *ccl_restrict render_buffer)
ccl_device_inline bool is_zero(const float2 a)
static ulong state[N]
#define PROFILING_INIT(kg, event)
@ PROFILING_SHADE_SHADOW_SURFACE
Definition profiling.h:39
@ PROFILING_SHADE_SHADOW_VOLUME
Definition profiling.h:40
@ PROFILING_SHADE_SHADOW_SETUP
Definition profiling.h:38
#define ccl_device
ccl_device void integrator_shade_shadow(KernelGlobals kg, IntegratorShadowState state, ccl_global float *ccl_restrict render_buffer)
CCL_NAMESPACE_BEGIN ccl_device_inline bool shadow_intersections_has_remaining(const uint num_hits)
ccl_device_inline void shader_setup_from_ray(KernelGlobals kg, ccl_private ShaderData *ccl_restrict sd, const ccl_private Ray *ccl_restrict ray, const ccl_private Intersection *ccl_restrict isect)
Definition shader_data.h:39
#define min(a, b)
Definition sort.cc:36
IntegratorShadowStateCPU * IntegratorShadowState
Definition state.h:230
#define INTEGRATOR_STATE_WRITE(state, nested_struct, member)
Definition state.h:236
#define INTEGRATOR_STATE(state, nested_struct, member)
Definition state.h:235
#define INTEGRATOR_STATE_ARRAY(state, nested_struct, array_index, member)
Definition state.h:238
ccl_device_forceinline void integrator_shadow_path_terminate(IntegratorShadowState state, const DeviceKernel current_kernel)
Definition state_flow.h:246
ccl_device_forceinline void integrator_shadow_path_next(IntegratorShadowState state, const DeviceKernel current_kernel, const DeviceKernel next_kernel)
Definition state_flow.h:238
ccl_device_forceinline void integrator_state_read_shadow_ray(ConstIntegratorShadowState state, ccl_private Ray *ccl_restrict ray)
Definition state_util.h:86
ccl_device_forceinline void integrator_state_read_shadow_isect(ConstIntegratorShadowState state, ccl_private Intersection *ccl_restrict isect, const int index)
Definition state_util.h:297
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_transparency(const ccl_private ShaderData *sd)
float3 Spectrum