Blender V4.3
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
18
19#ifdef __TRANSPARENT_SHADOWS__
20ccl_device_inline Spectrum integrate_transparent_surface_shadow(KernelGlobals kg,
22 const int hit)
23{
25
26 /* TODO: does aliasing like this break automatic SoA in CUDA?
27 * Should we instead store closures separate from ShaderData?
28 *
29 * TODO: is it better to declare this outside the loop or keep it local
30 * so the compiler can see there is no dependency between iterations? */
31 ShaderDataTinyStorage shadow_sd_storage;
32 ccl_private ShaderData *shadow_sd = AS_SHADER_DATA(&shadow_sd_storage);
33
34 /* Setup shader data at surface. */
37
40
41 shader_setup_from_ray(kg, shadow_sd, &ray, &isect);
42
43 /* Evaluate shader. */
44 if (!(shadow_sd->flag & SD_HAS_ONLY_VOLUME)) {
46 kg, state, shadow_sd, NULL, PATH_RAY_SHADOW);
47 }
48
49# ifdef __VOLUME__
50 /* Exit/enter volume. */
51 shadow_volume_stack_enter_exit(kg, state, shadow_sd);
52# endif
53
54 /* Disable transparent shadows for ray portals */
55 if (shadow_sd->flag & SD_RAY_PORTAL) {
56 return zero_spectrum();
57 }
58
59 /* Compute transparency from closures. */
60 return surface_shader_transparency(kg, shadow_sd);
61}
62
63# ifdef __VOLUME__
64ccl_device_inline void integrate_transparent_volume_shadow(KernelGlobals kg,
66 const int hit,
67 const int num_recorded_hits,
69 throughput)
70{
72
73 /* TODO: deduplicate with surface, or does it not matter for memory usage? */
74 ShaderDataTinyStorage shadow_sd_storage;
75 ccl_private ShaderData *shadow_sd = AS_SHADER_DATA(&shadow_sd_storage);
76
77 /* Setup shader data. */
80 ray.self.object = OBJECT_NONE;
81 ray.self.prim = PRIM_NONE;
82 ray.self.light_object = OBJECT_NONE;
83 ray.self.light_prim = PRIM_NONE;
84 ray.self.light = LAMP_NONE;
85 /* Modify ray position and length to match current segment. */
86 ray.tmin = (hit == 0) ? ray.tmin : INTEGRATOR_STATE_ARRAY(state, shadow_isect, hit - 1, t);
87 ray.tmax = (hit < num_recorded_hits) ? INTEGRATOR_STATE_ARRAY(state, shadow_isect, hit, t) :
88 ray.tmax;
89
90 /* `object` is only needed for light tree with light linking, it is irrelevant for shadow. */
91 shader_setup_from_volume(kg, shadow_sd, &ray, OBJECT_NONE);
92
93 VOLUME_READ_LAMBDA(integrator_state_read_shadow_volume_stack(state, i));
94 const float step_size = volume_stack_step_size(kg, volume_read_lambda_pass);
95
96 volume_shadow_heterogeneous(kg, state, &ray, shadow_sd, throughput, step_size);
97}
98# endif
99
100ccl_device_inline bool integrate_transparent_shadow(KernelGlobals kg,
102 const uint num_hits)
103{
104 /* Accumulate shadow for transparent surfaces. */
105 const uint num_recorded_hits = min(num_hits, INTEGRATOR_SHADOW_ISECT_SIZE);
106
107 /* Plus one to account for world volume, which has no boundary to hit but casts shadows. */
108 for (uint hit = 0; hit < num_recorded_hits + 1; hit++) {
109 /* Volume shaders. */
110 if (hit < num_recorded_hits || !shadow_intersections_has_remaining(num_hits)) {
111# ifdef __VOLUME__
112 if (!integrator_state_shadow_volume_stack_is_empty(kg, state)) {
113 Spectrum throughput = INTEGRATOR_STATE(state, shadow_path, throughput);
114 integrate_transparent_volume_shadow(kg, state, hit, num_recorded_hits, &throughput);
115 if (is_zero(throughput)) {
116 return true;
117 }
118
119 INTEGRATOR_STATE_WRITE(state, shadow_path, throughput) = throughput;
120 }
121# endif
122 }
123
124 /* Surface shaders. */
125 if (hit < num_recorded_hits) {
126 const Spectrum shadow = integrate_transparent_surface_shadow(kg, state, hit);
127 const Spectrum throughput = INTEGRATOR_STATE(state, shadow_path, throughput) * shadow;
128 if (is_zero(throughput)) {
129 return true;
130 }
131
132 INTEGRATOR_STATE_WRITE(state, shadow_path, throughput) = throughput;
133 INTEGRATOR_STATE_WRITE(state, shadow_path, transparent_bounce) += 1;
134 INTEGRATOR_STATE_WRITE(state, shadow_path, rng_offset) += PRNG_BOUNCE_NUM;
135 }
136
137 /* Note we do not need to check max_transparent_bounce here, the number
138 * of intersections is already limited and made opaque in the
139 * INTERSECT_SHADOW kernel. */
140 }
141
143 /* There are more hits that we could not recorded due to memory usage,
144 * adjust ray to intersect again from the last hit. */
145 const float last_hit_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, num_recorded_hits - 1, t);
146 INTEGRATOR_STATE_WRITE(state, shadow_ray, tmin) = intersection_t_offset(last_hit_t);
147 }
148
149 return false;
150}
151#endif /* __TRANSPARENT_SHADOWS__ */
152
156{
158 const uint num_hits = INTEGRATOR_STATE(state, shadow_path, num_hits);
159
160#ifdef __TRANSPARENT_SHADOWS__
161 /* Evaluate transparent shadows. */
162 const bool opaque = integrate_transparent_shadow(kg, state, num_hits);
163 if (opaque) {
165 return;
166 }
167#endif
168
170 /* More intersections to find, continue shadow ray. */
172 state,
175 return;
176 }
177 else {
181 return;
182 }
183}
184
unsigned int uint
ccl_device_forceinline float intersection_t_offset(const float t)
const KernelGlobalsCPU *ccl_restrict KernelGlobals
#define ccl_restrict
#define ccl_optional_struct_init
#define ccl_device
#define ccl_private
#define ccl_device_inline
#define ccl_global
#define CCL_NAMESPACE_END
#define NULL
#define VOLUME_READ_LAMBDA(function_call)
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
#define AS_SHADER_DATA(shader_data_tiny_storage)
@ PRNG_BOUNCE_NUM
#define PRIM_NONE
@ PATH_RAY_SHADOW
#define INTEGRATOR_SHADOW_ISECT_SIZE
#define OBJECT_NONE
ShaderDataTinyStorage
ShaderData
#define LAMP_NONE
@ DEVICE_KERNEL_INTEGRATOR_SHADE_SHADOW
@ DEVICE_KERNEL_INTEGRATOR_INTERSECT_SHADOW
#define PROFILING_INIT(kg, event)
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]
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, ccl_private const Ray *ccl_restrict ray, ccl_private const Intersection *ccl_restrict isect)
Definition shader_data.h:31
#define min(a, b)
Definition sort.c:32
#define INTEGRATOR_STATE_WRITE(state, nested_struct, member)
Definition state.h:236
#define INTEGRATOR_STATE(state, nested_struct, member)
Definition state.h:235
IntegratorShadowStateCPU *ccl_restrict IntegratorShadowState
Definition state.h:230
#define INTEGRATOR_STATE_ARRAY(state, nested_struct, array_index, member)
Definition state.h:238
ccl_device_forceinline void integrator_shadow_path_terminate(KernelGlobals kg, IntegratorShadowState state, const DeviceKernel current_kernel)
Definition state_flow.h:217
ccl_device_forceinline void integrator_shadow_path_next(KernelGlobals kg, IntegratorShadowState state, const DeviceKernel current_kernel, const DeviceKernel next_kernel)
Definition state_flow.h:208
ccl_device_forceinline void integrator_state_read_shadow_ray(ConstIntegratorShadowState state, ccl_private Ray *ccl_restrict ray)
Definition state_util.h:84
ccl_device_forceinline void integrator_state_read_shadow_isect(ConstIntegratorShadowState state, ccl_private Intersection *ccl_restrict isect, const int index)
Definition state_util.h:276
ccl_device void surface_shader_eval(KernelGlobals kg, ConstIntegratorGenericState state, ccl_private ShaderData *ccl_restrict sd, ccl_global float *ccl_restrict buffer, uint32_t path_flag, bool use_caustics_storage=false)
ccl_device Spectrum surface_shader_transparency(KernelGlobals kg, ccl_private const ShaderData *sd)
#define zero_spectrum
SPECTRUM_DATA_TYPE Spectrum
@ PROFILING_SHADE_SHADOW_SURFACE
@ PROFILING_SHADE_SHADOW_VOLUME
@ PROFILING_SHADE_SHADOW_SETUP