Blender V4.3
pass_accessor.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
6
7#include "session/buffers.h"
8#include "util/log.h"
9
10// clang-format off
12#include "kernel/types.h"
13// clang-format on
14
16
17/* --------------------------------------------------------------------
18 * Pass input information.
19 */
20
22 : type(pass.type),
23 mode(pass.mode),
24 include_albedo(pass.include_albedo),
25 is_lightgroup(!pass.lightgroup.empty()),
26 offset(pass.offset)
27{
28}
29
30/* --------------------------------------------------------------------
31 * Pass destination.
32 */
33
34PassAccessor::Destination::Destination(float *pixels, int num_components)
35 : pixels(pixels), num_components(num_components)
36{
37}
38
40 : Destination(pass_type)
41{
43}
44
46{
47 const PassInfo pass_info = Pass::get_info(pass_type);
48 num_components = pass_info.num_components;
49}
50
51/* --------------------------------------------------------------------
52 * Pass source.
53 */
54
55PassAccessor::Source::Source(const float *pixels, int num_components)
56 : pixels(pixels), num_components(num_components)
57{
58}
59
60/* --------------------------------------------------------------------
61 * Pass accessor.
62 */
63
64PassAccessor::PassAccessor(const PassAccessInfo &pass_access_info, float exposure, int num_samples)
65 : pass_access_info_(pass_access_info), exposure_(exposure), num_samples_(num_samples)
66{
67}
68
70 const Destination &destination) const
71{
72 if (render_buffers == nullptr || render_buffers->buffer.data() == nullptr) {
73 return false;
74 }
75
76 return get_render_tile_pixels(render_buffers, render_buffers->params, destination);
77}
78
79static void pad_pixels(const BufferParams &buffer_params,
80 const PassAccessor::Destination &destination,
81 const int src_num_components)
82{
83 /* When requesting a single channel pass as RGBA, or RGB pass as RGBA,
84 * fill in the additional components for convenience. */
85 const int dest_num_components = destination.num_components;
86
87 if (src_num_components >= dest_num_components) {
88 return;
89 }
90
91 const size_t size = static_cast<size_t>(buffer_params.width) * buffer_params.height;
92 if (destination.pixels) {
93 const size_t pixel_stride = destination.pixel_stride ? destination.pixel_stride :
94 destination.num_components;
95
96 float *pixel = destination.pixels + pixel_stride * destination.offset;
97
98 for (size_t i = 0; i < size; i++, pixel += dest_num_components) {
99 if (dest_num_components >= 3 && src_num_components == 1) {
100 pixel[1] = pixel[0];
101 pixel[2] = pixel[0];
103 if (dest_num_components >= 4) {
104 pixel[3] = 1.0f;
105 }
106 }
107 }
108
109 if (destination.pixels_half_rgba) {
110 const half one = float_to_half_display(1.0f);
111 half4 *pixel = destination.pixels_half_rgba + destination.offset;
112
113 for (size_t i = 0; i < size; i++, pixel++) {
114 if (dest_num_components >= 3 && src_num_components == 1) {
115 pixel[0].y = pixel[0].x;
116 pixel[0].z = pixel[0].x;
117 }
118 if (dest_num_components >= 4) {
119 pixel[0].w = one;
120 }
121 }
122 }
123}
124
126 const BufferParams &buffer_params,
127 const Destination &destination) const
128{
129 if (render_buffers == nullptr || render_buffers->buffer.data() == nullptr) {
130 return false;
131 }
132
133 const PassType type = pass_access_info_.type;
134 const PassMode mode = pass_access_info_.mode;
135 const PassInfo pass_info = Pass::get_info(
137 int num_written_components = pass_info.num_components;
138
139 if (pass_info.num_components == 1) {
140 /* Single channel passes. */
141 if (mode == PassMode::DENOISED) {
142 /* Denoised passes store their final pixels, no need in special calculation. */
143 get_pass_float(render_buffers, buffer_params, destination);
144 }
145 else if (type == PASS_DEPTH) {
146 get_pass_depth(render_buffers, buffer_params, destination);
147 }
148 else if (type == PASS_MIST) {
149 get_pass_mist(render_buffers, buffer_params, destination);
150 }
151 else if (type == PASS_SAMPLE_COUNT) {
152 get_pass_sample_count(render_buffers, buffer_params, destination);
153 }
154 else {
155 get_pass_float(render_buffers, buffer_params, destination);
156 }
157 }
158 else if (type == PASS_MOTION) {
159 /* Motion pass. */
160 DCHECK_EQ(destination.num_components, 4) << "Motion pass must have 4 components";
161 get_pass_motion(render_buffers, buffer_params, destination);
162 }
163 else if (type == PASS_CRYPTOMATTE) {
164 /* Cryptomatte pass. */
165 DCHECK_EQ(destination.num_components, 4) << "Cryptomatte pass must have 4 components";
166 get_pass_cryptomatte(render_buffers, buffer_params, destination);
167 }
168 else {
169 /* RGB, RGBA and vector passes. */
170 DCHECK(destination.num_components == 3 || destination.num_components == 4)
171 << pass_type_as_string(type) << " pass must have 3 or 4 components";
172
174 /* Denoised matte with shadow needs to do calculation (will use denoised shadow catcher pass
175 * to approximate shadow with). */
176 get_pass_shadow_catcher_matte_with_shadow(render_buffers, buffer_params, destination);
177 }
178 else if (type == PASS_SHADOW_CATCHER && mode != PassMode::DENOISED) {
179 /* Shadow catcher pass. */
180 get_pass_shadow_catcher(render_buffers, buffer_params, destination);
181 }
182 else if ((pass_info.divide_type != PASS_NONE || pass_info.direct_type != PASS_NONE ||
183 pass_info.indirect_type != PASS_NONE) &&
184 mode != PassMode::DENOISED)
185 {
186 /* RGB lighting passes that need to divide out color and/or sum direct and indirect.
187 * These can also optionally write alpha like the combined pass. */
188 get_pass_light_path(render_buffers, buffer_params, destination);
189 num_written_components = 4;
190 }
191 else {
192 /* Passes that need no special computation, or denoised passes that already
193 * had the computation done. */
194 if (pass_info.num_components == 3) {
195 get_pass_float3(render_buffers, buffer_params, destination);
196
197 /* Use alpha for colors passes. */
198 if (type == PASS_DIFFUSE_COLOR || type == PASS_GLOSSY_COLOR ||
200 {
201 num_written_components = destination.num_components;
202 }
203 }
204 else if (pass_info.num_components == 4) {
205 if (destination.num_components == 3) {
206 /* Special case for denoiser access of RGBA passes ignoring alpha channel. */
207 get_pass_float3(render_buffers, buffer_params, destination);
208 }
209 else if (type == PASS_COMBINED || type == PASS_SHADOW_CATCHER ||
211 {
212 /* Passes with transparency as 4th component. */
213 get_pass_combined(render_buffers, buffer_params, destination);
214 }
215 else {
216 /* Passes with alpha as 4th component. */
217 get_pass_float4(render_buffers, buffer_params, destination);
218 }
219 }
220 }
221 }
222
223 pad_pixels(buffer_params, destination, num_written_components);
224
225 return true;
226}
227
229 const BufferParams &buffer_params,
230 const Destination &destination) const
231{
232 const PassMode mode = pass_access_info_.mode;
233 const PassInfo &pass_info = Pass::get_info(
235
236 kfilm_convert->pass_offset = pass_access_info_.offset;
237 kfilm_convert->pass_stride = buffer_params.pass_stride;
238
239 kfilm_convert->pass_use_exposure = pass_info.use_exposure;
240 kfilm_convert->pass_use_filter = pass_info.use_filter;
241
242 /* TODO(sergey): Some of the passes needs to become denoised when denoised pass is accessed. */
243 if (pass_info.direct_type != PASS_NONE) {
244 kfilm_convert->pass_offset = buffer_params.get_pass_offset(pass_info.direct_type);
245 }
246 kfilm_convert->pass_indirect = buffer_params.get_pass_offset(pass_info.indirect_type);
247 kfilm_convert->pass_divide = buffer_params.get_pass_offset(pass_info.divide_type);
248
249 kfilm_convert->pass_combined = buffer_params.get_pass_offset(PASS_COMBINED);
250 kfilm_convert->pass_sample_count = buffer_params.get_pass_offset(PASS_SAMPLE_COUNT);
251 kfilm_convert->pass_adaptive_aux_buffer = buffer_params.get_pass_offset(
253 kfilm_convert->pass_motion_weight = buffer_params.get_pass_offset(PASS_MOTION_WEIGHT);
254 kfilm_convert->pass_shadow_catcher = buffer_params.get_pass_offset(PASS_SHADOW_CATCHER, mode);
255 kfilm_convert->pass_shadow_catcher_sample_count = buffer_params.get_pass_offset(
257 kfilm_convert->pass_shadow_catcher_matte = buffer_params.get_pass_offset(
259
260 /* Background is not denoised, so always use noisy pass. */
261 kfilm_convert->pass_background = buffer_params.get_pass_offset(PASS_BACKGROUND);
262
263 if (pass_info.use_filter) {
264 kfilm_convert->scale = num_samples_ != 0 ? 1.0f / num_samples_ : 0.0f;
265 }
266 else {
267 kfilm_convert->scale = 1.0f;
268 }
269
270 if (pass_info.use_exposure) {
271 kfilm_convert->exposure = exposure_;
272 }
273 else {
274 kfilm_convert->exposure = 1.0f;
275 }
276
277 kfilm_convert->scale_exposure = kfilm_convert->scale * kfilm_convert->exposure;
278
283
284 kfilm_convert->num_components = destination.num_components;
285 kfilm_convert->pixel_stride = destination.pixel_stride ? destination.pixel_stride :
286 destination.num_components;
287
288 kfilm_convert->is_denoised = (mode == PassMode::DENOISED);
289}
290
292{
293 if (render_buffers == nullptr || render_buffers->buffer.data() == nullptr) {
294 return false;
295 }
296
297 const PassInfo pass_info = Pass::get_info(
299
300 const BufferParams &buffer_params = render_buffers->params;
301
302 float *buffer_data = render_buffers->buffer.data();
303 const int size = buffer_params.width * buffer_params.height;
304
305 const int out_stride = buffer_params.pass_stride;
306 const int in_stride = source.num_components;
307 const int num_components_to_copy = min(source.num_components, pass_info.num_components);
308
309 float *out = buffer_data + pass_access_info_.offset;
310 const float *in = source.pixels + source.offset * in_stride;
311
312 for (int i = 0; i < size; i++, out += out_stride, in += in_stride) {
313 memcpy(out, in, sizeof(float) * num_components_to_copy);
314 }
315
316 return true;
317}
318
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
int pass_stride
Definition buffers.h:94
int get_pass_offset(PassType type, PassMode mode=PassMode::NOISY) const
Definition buffers.cpp:167
NODE_DECLARE int width
Definition buffers.h:72
const float * pixels
bool set_render_tile_pixels(RenderBuffers *render_buffers, const Source &source)
PassAccessor(const PassAccessInfo &pass_access_info, float exposure, int num_samples)
bool get_render_tile_pixels(const RenderBuffers *render_buffers, const Destination &destination) const
virtual void init_kernel_film_convert(KernelFilmConvert *kfilm_convert, const BufferParams &buffer_params, const Destination &destination) const
PassAccessInfo pass_access_info_
PassInfo get_info() const
Definition pass.cpp:141
device_vector< float > buffer
Definition buffers.h:160
BufferParams params
Definition buffers.h:157
Definition half.h:42
#define CCL_NAMESPACE_END
ccl_device_inline half float_to_half_display(const float f)
Definition half.h:136
PassType
@ PASS_SHADOW_CATCHER_SAMPLE_COUNT
@ PASS_BACKGROUND
@ PASS_TRANSMISSION_COLOR
@ PASS_SHADOW_CATCHER_MATTE
@ PASS_DEPTH
@ PASS_MIST
@ PASS_SHADOW_CATCHER
@ PASS_MOTION
@ PASS_COMBINED
@ PASS_ADAPTIVE_AUX_BUFFER
@ PASS_NONE
@ PASS_CRYPTOMATTE
@ PASS_DIFFUSE_COLOR
@ PASS_SAMPLE_COUNT
@ PASS_MOTION_WEIGHT
@ PASS_GLOSSY_COLOR
#define DCHECK(expression)
Definition log.h:51
#define DCHECK_EQ(a, b)
Definition log.h:59
CCL_NAMESPACE_BEGIN const char * pass_type_as_string(const PassType type)
Definition pass.cpp:12
PassMode
Definition pass.h:20
static void pad_pixels(const BufferParams &buffer_params, const PassAccessor::Destination &destination, const int src_num_components)
#define min(a, b)
Definition sort.c:32
int use_approximate_shadow_catcher_background
int pass_shadow_catcher_sample_count
PassType direct_type
Definition pass.h:33
int num_components
Definition pass.h:28
bool use_filter
Definition pass.h:29
PassType divide_type
Definition pass.h:32
bool use_exposure
Definition pass.h:30
PassType indirect_type
Definition pass.h:34
Definition half.h:61
half y
Definition half.h:62