Blender V4.3
eevee_volume.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
13#include "DNA_volume_types.h"
14#include "GPU_capabilities.hh"
15
16#include "draw_common.hh"
17
18#include "eevee_instance.hh"
19#include "eevee_pipeline.hh"
20
21#include "eevee_volume.hh"
22
23namespace blender::eevee {
24
26{
27 enabled_ = false;
28
29 const Scene *scene_eval = inst_.scene;
30
31 const int2 extent = inst_.film.render_extent_get();
32 int tile_size = clamp_i(scene_eval->eevee.volumetric_tile_size, 1, 16);
33
34 int3 tex_size;
35 /* Try to match resolution setting but fallback to lower resolution
36 * if it doesn't fit the hardware limits. */
37 for (; tile_size <= 16; tile_size *= 2) {
38 /* Find Froxel Texture resolution. */
39 tex_size = int3(math::divide_ceil(extent, int2(tile_size)), 0);
40 tex_size.z = std::max(1, scene_eval->eevee.volumetric_samples);
41
42 if (math::reduce_max(tex_size) < GPU_max_texture_3d_size()) {
43 /* Fits hardware limits. */
44 break;
45 }
46 }
47
48 if (tile_size != scene_eval->eevee.volumetric_tile_size) {
49 inst_.info_append_i18n(
50 "Warning: Volume rendering data could not be allocated. Now using a resolution of 1:{} "
51 "instead of 1:{}.",
52 tile_size,
53 scene_eval->eevee.volumetric_tile_size);
54 }
55
56 data_.tile_size = tile_size;
57 data_.tile_size_lod = int(log2(tile_size));
58 data_.coord_scale = float2(extent) / float2(tile_size * tex_size);
59 data_.main_view_extent = float2(extent);
60 data_.main_view_extent_inv = 1.0f / float2(extent);
61 data_.tex_size = tex_size;
62 data_.inv_tex_size = 1.0f / float3(tex_size);
63
64 const bool shadow_enabled = (scene_eval->eevee.flag & SCE_EEVEE_VOLUMETRIC_SHADOWS) != 0;
65 data_.shadow_steps = (shadow_enabled) ? scene_eval->eevee.volumetric_shadow_samples : 0;
66
67 data_.light_clamp = scene_eval->eevee.volumetric_light_clamp;
68 data_.light_clamp = (data_.light_clamp > 0.0) ? data_.light_clamp : 1e20;
69
70 use_reprojection_ = (scene_eval->eevee.flag & SCE_EEVEE_TAA_REPROJECTION) != 0;
71}
72
74{
75 previous_objects_ = current_objects_;
76 current_objects_.clear();
77}
78
79void VolumeModule::world_sync(const WorldHandle &world_handle)
80{
81 if (!use_reprojection_) {
82 return;
83 }
84
85 if (world_handle.recalc && !inst_.is_playback()) {
86 valid_history_ = false;
87 }
88}
89
91{
92 current_objects_.add(ob_handle.object_key);
93
94 if (!use_reprojection_) {
95 return;
96 }
97
98 if (ob_handle.recalc && !inst_.is_playback()) {
99 valid_history_ = false;
100 }
101}
102
104{
105 enabled_ = inst_.world.has_volume() || !current_objects_.is_empty();
106
107 const Scene *scene_eval = inst_.scene;
108
109 const bool custom_range = scene_eval->eevee.flag & SCE_EEVEE_VOLUME_CUSTOM_RANGE;
110 const float camera_clip_start = inst_.camera.data_get().clip_near;
111 const float camera_clip_end = inst_.camera.data_get().clip_far;
112 float integration_start = custom_range ? scene_eval->eevee.volumetric_start : camera_clip_start;
113 float integration_end = custom_range ? scene_eval->eevee.volumetric_end : camera_clip_end;
114
115 if (!inst_.camera.is_camera_object() && inst_.camera.is_orthographic()) {
116 integration_start = -integration_end;
117 }
118
119 std::optional<Bounds<float>> volume_bounds = inst_.pipelines.volume.object_integration_range();
120 if (volume_bounds && !inst_.world.has_volume()) {
121 /* Restrict integration range to the object volume range. This increases precision. */
122 integration_start = math::max(integration_start, -volume_bounds.value().max);
123 integration_end = math::min(integration_end, -volume_bounds.value().min);
124 }
125
126 /* Negate clip values (View matrix forward vector is -Z). */
127 float near = -math::max(integration_start, camera_clip_start - 1e-4f);
128 float far = -math::min(integration_end, camera_clip_end + 1e-4f);
129
130 if (assign_if_different(history_camera_is_perspective_, inst_.camera.is_perspective())) {
131 /* Currently, the re-projection uses the same path for volume_z_to_view_z conversion for both
132 * the current view and the history view. Moreover, re-projecting in this huge change is more
133 * detrimental than anything. */
134 valid_history_ = false;
135 }
136
137 if (valid_history_) {
138 /* Avoid the (potentially expensive) check if valid_history_ is already false. */
139 if (current_objects_ != previous_objects_) {
140 valid_history_ = false;
141 }
142 }
143
144 if (inst_.camera.is_perspective()) {
145 float sample_distribution = scene_eval->eevee.volumetric_sample_distribution;
146 sample_distribution = 4.0f * math::max(1.0f - sample_distribution, 1e-2f);
147
148 data_.depth_near = (far - near * exp2(1.0f / sample_distribution)) / (far - near);
149 data_.depth_far = (1.0f - data_.depth_near) / near;
150 data_.depth_distribution = sample_distribution;
151 }
152 else {
153 data_.depth_near = near;
154 data_.depth_far = far;
155 data_.depth_distribution = 0.0f; /* Unused. */
156 }
157
158 if (!enabled_) {
159 occupancy_tx_.free();
160 prop_scattering_tx_.free();
161 prop_extinction_tx_.free();
162 prop_emission_tx_.free();
163 prop_phase_tx_.free();
164 prop_phase_weight_tx_.free();
165 scatter_tx_.current().free();
166 scatter_tx_.previous().free();
167 extinction_tx_.current().free();
168 extinction_tx_.previous().free();
169 integrated_scatter_tx_.free();
170 integrated_transmit_tx_.free();
171
172 /* Update references for bindings. */
173 result.scattering_tx_ = dummy_scatter_tx_;
174 result.transmittance_tx_ = dummy_transmit_tx_;
175 /* These shouldn't be used. */
176 properties.scattering_tx_ = nullptr;
177 properties.extinction_tx_ = nullptr;
178 properties.emission_tx_ = nullptr;
179 properties.phase_tx_ = nullptr;
180 properties.phase_weight_tx_ = nullptr;
181 properties.occupancy_tx_ = nullptr;
182 occupancy.occupancy_tx_ = nullptr;
183 occupancy.hit_depth_tx_ = nullptr;
184 occupancy.hit_count_tx_ = nullptr;
185
186 /* Avoid undefined re-projection behavior. */
187 valid_history_ = false;
188 return;
189 }
190
191 bool has_scatter = inst_.world.has_volume_scatter() || inst_.pipelines.volume.has_scatter();
192 bool has_absorption = inst_.world.has_volume_absorption() ||
194 use_lights_ = has_scatter;
195 /* TODO(fclem): Allocate extinction texture as dummy (1px^3) if has_absorption are false. */
196 UNUSED_VARS(has_absorption);
197
200
201 prop_scattering_tx_.ensure_3d(GPU_R11F_G11F_B10F, data_.tex_size, usage);
202 prop_extinction_tx_.ensure_3d(GPU_R11F_G11F_B10F, data_.tex_size, usage);
203 prop_emission_tx_.ensure_3d(GPU_R11F_G11F_B10F, data_.tex_size, usage);
204 /* We need 2 separate images to prevent bugs in Nvidia drivers (See #122454). */
205 prop_phase_tx_.ensure_3d(GPU_R16F, data_.tex_size, usage);
206 prop_phase_weight_tx_.ensure_3d(GPU_R16F, data_.tex_size, usage);
207
208 int occupancy_layers = divide_ceil_u(data_.tex_size.z, 32u);
211 occupancy_tx_.ensure_3d(GPU_R32UI, int3(data_.tex_size.xy(), occupancy_layers), occupancy_usage);
212
213 {
218 int2 hit_list_size = int2(1);
219 int hit_list_layer = 1;
220 if (inst_.pipelines.volume.use_hit_list()) {
221 hit_list_layer = clamp_i(inst_.scene->eevee.volumetric_ray_depth, 1, 16);
222 hit_list_size = data_.tex_size.xy();
223 }
224 hit_depth_tx_.ensure_3d(GPU_R32F, int3(hit_list_size, hit_list_layer), hit_depth_usage);
225 if (hit_count_tx_.ensure_2d(GPU_R32UI, hit_list_size, hit_count_usage)) {
226 hit_count_tx_.clear(uint4(0u));
227 }
228 }
229
232 front_depth_tx_.ensure_2d(GPU_DEPTH24_STENCIL8, data_.tex_size.xy(), front_depth_usage);
233 occupancy_fb_.ensure(GPU_ATTACHMENT_TEXTURE(front_depth_tx_));
234
235 bool created = false;
236 created |= scatter_tx_.current().ensure_3d(GPU_R11F_G11F_B10F, data_.tex_size, usage);
237 created |= extinction_tx_.current().ensure_3d(GPU_R11F_G11F_B10F, data_.tex_size, usage);
238 created |= scatter_tx_.previous().ensure_3d(GPU_R11F_G11F_B10F, data_.tex_size, usage);
239 created |= extinction_tx_.previous().ensure_3d(GPU_R11F_G11F_B10F, data_.tex_size, usage);
240
241 if (created) {
242 valid_history_ = false;
243 }
244
245 integrated_scatter_tx_.ensure_3d(GPU_R11F_G11F_B10F, data_.tex_size, usage);
246 integrated_transmit_tx_.ensure_3d(GPU_R11F_G11F_B10F, data_.tex_size, usage);
247
248 /* Update references for bindings. */
249 result.scattering_tx_ = integrated_scatter_tx_;
250 result.transmittance_tx_ = integrated_transmit_tx_;
251 properties.scattering_tx_ = prop_scattering_tx_;
252 properties.extinction_tx_ = prop_extinction_tx_;
253 properties.emission_tx_ = prop_emission_tx_;
254 properties.phase_tx_ = prop_phase_tx_;
255 properties.phase_weight_tx_ = prop_phase_weight_tx_;
256 properties.occupancy_tx_ = occupancy_tx_;
257 occupancy.occupancy_tx_ = occupancy_tx_;
258 occupancy.hit_depth_tx_ = hit_depth_tx_;
259 occupancy.hit_count_tx_ = hit_count_tx_;
260
261 /* Set extend mode to extend and reject invalid samples in the shader.
262 * This avoids some black rim artifacts near the edge of the re-projected volume.
263 * Filter linear to avoid sharp artifacts during re-projection. */
264 const GPUSamplerState history_sampler = {GPU_SAMPLER_FILTERING_LINEAR,
267 scatter_ps_.init();
268 scatter_ps_.shader_set(
270 scatter_ps_.bind_resources(inst_.lights);
271 scatter_ps_.bind_resources(inst_.sphere_probes);
272 scatter_ps_.bind_resources(inst_.volume_probes);
273 scatter_ps_.bind_resources(inst_.shadows);
274 scatter_ps_.bind_resources(inst_.uniform_data);
275 scatter_ps_.bind_resources(inst_.sampling);
276 scatter_ps_.bind_image("in_scattering_img", &prop_scattering_tx_);
277 scatter_ps_.bind_image("in_extinction_img", &prop_extinction_tx_);
278 scatter_ps_.bind_texture("extinction_tx", &prop_extinction_tx_);
279 scatter_ps_.bind_image("in_emission_img", &prop_emission_tx_);
280 scatter_ps_.bind_image("in_phase_img", &prop_phase_tx_);
281 scatter_ps_.bind_image("in_phase_weight_img", &prop_phase_weight_tx_);
282 scatter_ps_.bind_texture("scattering_history_tx", &scatter_tx_.previous(), history_sampler);
283 scatter_ps_.bind_texture("extinction_history_tx", &extinction_tx_.previous(), history_sampler);
284 scatter_ps_.bind_image("out_scattering_img", &scatter_tx_.current());
285 scatter_ps_.bind_image("out_extinction_img", &extinction_tx_.current());
287 /* Sync with the property pass. */
290
291 integration_ps_.init();
293 integration_ps_.bind_resources(inst_.uniform_data);
294 integration_ps_.bind_resources(inst_.sampling);
295 integration_ps_.bind_texture("in_scattering_tx", &scatter_tx_.current());
296 integration_ps_.bind_texture("in_extinction_tx", &extinction_tx_.current());
297 integration_ps_.bind_image("out_scattering_img", &integrated_scatter_tx_);
298 integration_ps_.bind_image("out_transmittance_img", &integrated_transmit_tx_);
299 /* Sync with the scatter pass. */
300 integration_ps_.barrier(GPU_BARRIER_TEXTURE_FETCH);
301 integration_ps_.dispatch(
303
304 resolve_ps_.init();
307 resolve_ps_.bind_resources(inst_.uniform_data);
308 resolve_ps_.bind_resources(this->result);
309 resolve_ps_.bind_resources(inst_.hiz_buffer.front);
312 /* Sync with the integration pass. */
314 resolve_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
315}
316
318{
319 if (!enabled_) {
320 return;
321 }
322
323 /* Number of frame to consider for blending with exponential (infinite) average. */
324 int exponential_frame_count = 16;
325 if (inst_.is_image_render()) {
326 /* Disable reprojection for rendering. */
327 exponential_frame_count = 0;
328 }
329 else if (!use_reprojection_) {
330 /* No re-projection if TAA is disabled. */
331 exponential_frame_count = 0;
332 }
333 else if (inst_.is_playback()) {
334 /* For now, we assume we want responsiveness for volume animation.
335 * But this makes general animation inside uniform volumes less stable.
336 * When we introduce updated volume tagging, we will be able to increase this for general
337 * playback. */
338 exponential_frame_count = 3;
339 }
340 else if (inst_.is_transforming()) {
341 /* Improve responsiveness of volume if we are transforming objects. */
342 /* TODO(fclem): This is too general as it will be triggered even for non volume object.
343 * Instead, we should tag which areas of the volume that need increased responsiveness. */
344 exponential_frame_count = 3;
345 }
346 else if (inst_.is_navigating()) {
347 /* Navigation is usually smooth because of the re-projection but we can get ghosting
348 * artifacts on lights because of voxels stretched in Z or anisotropy. */
349 exponential_frame_count = 8;
350 }
351 else if (inst_.sampling.is_reset()) {
352 /* If we are not falling in any cases above, this usually means there is a scene or object
353 * parameter update. Reset accumulation completely. */
354 exponential_frame_count = 0;
355 }
356
357 if (!valid_history_) {
358 history_frame_count_ = 0;
359 }
360 /* Interactive mode accumulate samples using exponential average.
361 * We still reuse the history when we go into static mode.
362 * However, using re-projection for static mode will show the precision limit of RG11B10 format.
363 * So we clamp it to the exponential frame count in any case. */
364 history_frame_count_ = math::min(history_frame_count_, exponential_frame_count);
365
366 /* In interactive mode, use exponential average (fixed ratio).
367 * For static / render mode use simple average (moving ratio). */
368 float history_opacity = history_frame_count_ / (history_frame_count_ + 1.0f);
369
370 /* Setting opacity to 0.0 will bypass any sampling of history buffer.
371 * Allowing us to skip the 3D texture clear. */
372 data_.history_opacity = (valid_history_) ? history_opacity : 0.0f;
373
374 float left, right, bottom, top, near, far;
375 projmat_dimensions(main_view.winmat().ptr(), &left, &right, &bottom, &top, &near, &far);
376
377 /* Just like up-sampling matrix computation, we have to be careful to where to put the bounds of
378 * our froxel volume so that a 2D pixel covers exactly the number of pixel in a tile. */
379 float2 render_size = float2(right - left, top - bottom);
380 float2 volume_size = render_size * float2(data_.tex_size.xy() * data_.tile_size) /
382 /* Change to the padded extends. */
383 right = left + volume_size.x;
384 top = bottom + volume_size.y;
385
386 float4x4 winmat_infinite, winmat_finite;
387 /* Create an infinite projection matrix to avoid far clipping plane clipping the object. This
388 * way, surfaces that are further away than the far clip plane will still be voxelized.*/
389 winmat_infinite = main_view.is_persp() ?
390 math::projection::perspective_infinite(left, right, bottom, top, near) :
391 math::projection::orthographic_infinite(left, right, bottom, top, near);
392 /* We still need a bounded projection matrix to get correct froxel location. */
393 winmat_finite = main_view.is_persp() ?
394 math::projection::perspective(left, right, bottom, top, near, far) :
395 math::projection::orthographic(left, right, bottom, top, near, far);
396 /* Save non-jittered finite matrix for re-projection. */
397 data_.winmat_stable = winmat_finite;
398 data_.wininv_stable = math::invert(winmat_finite);
399
400 /* Anti-Aliasing / Super-Sampling jitter. */
402 /* Wrap to keep first sample centered (0,0) and scale to convert to NDC. */
403 jitter = math::fract(jitter + 0.5f) * 2.0f - 1.0f;
404 /* Convert to pixel size. */
405 jitter *= data_.inv_tex_size.xy();
406 /* Apply jitter to both matrices. */
407 winmat_infinite = math::projection::translate(winmat_infinite, jitter);
408 winmat_finite = math::projection::translate(winmat_finite, jitter);
409
410 data_.winmat_finite = winmat_finite;
411 data_.wininv_finite = math::invert(winmat_finite);
412
413 /* Compute re-projection matrix. */
414 data_.curr_view_to_past_view = history_viewmat_ * main_view.viewinv();
415
417
418 DRW_stats_group_start("Volumes");
419 occupancy_fb_.bind();
420 inst_.pipelines.world_volume.render(main_view);
421
422 volume_view.sync(main_view.viewmat(), winmat_infinite);
423 /* TODO(fclem): The infinite projection matrix makes the culling test unreliable (see #115595).
424 * We need custom culling for these but that's not implemented yet. */
425 volume_view.visibility_test(false);
426
427 if (!current_objects_.is_empty()) {
428 inst_.pipelines.volume.render(volume_view, occupancy_tx_);
429 }
431}
432
433void VolumeModule::draw_compute(View &main_view, int2 extent)
434{
435 if (!enabled_) {
436 return;
437 }
438
439 if (inst_.pipelines.deferred.is_empty()) {
440 /* This assume the volume are computed after deferred passes. This is needed to avoid broken
441 * lighting and shadowing as the lights are not setup otherwise (see #121971). */
442 inst_.hiz_buffer.swap_layer();
443 inst_.hiz_buffer.update();
444 inst_.volume_probes.set_view(main_view);
445 inst_.sphere_probes.set_view(main_view);
446 inst_.shadows.set_view(main_view, extent);
447 }
448
449 scatter_tx_.swap();
450 extinction_tx_.swap();
451
452 inst_.manager->submit(scatter_ps_, main_view);
453 inst_.manager->submit(integration_ps_, main_view);
454
455 /* Copy history data. */
456 history_viewmat_ = main_view.viewmat();
457 data_.history_depth_near = data_.depth_near;
458 data_.history_depth_far = data_.depth_far;
461 valid_history_ = true;
462 history_frame_count_ += 1;
463}
464
466{
467 if (!enabled_) {
468 return;
469 }
470
471 inst_.hiz_buffer.update();
472
473 resolve_fb_.ensure(GPU_ATTACHMENT_NONE,
475 resolve_fb_.bind();
476 inst_.manager->submit(resolve_ps_, view);
477}
478
479} // namespace blender::eevee
MINLINE uint divide_ceil_u(uint a, uint b)
MINLINE int clamp_i(int value, int min, int max)
void projmat_dimensions(const float winmat[4][4], float *r_left, float *r_right, float *r_bottom, float *r_top, float *r_near, float *r_far)
#define UNUSED_VARS(...)
@ SCE_EEVEE_VOLUME_CUSTOM_RANGE
@ SCE_EEVEE_VOLUMETRIC_SHADOWS
@ SCE_EEVEE_TAA_REPROJECTION
int GPU_max_texture_3d_size()
#define GPU_ATTACHMENT_TEXTURE(_texture)
#define GPU_ATTACHMENT_NONE
@ GPU_PRIM_TRIS
@ GPU_BARRIER_TEXTURE_FETCH
Definition GPU_state.hh:37
@ GPU_BARRIER_SHADER_IMAGE_ACCESS
Definition GPU_state.hh:35
eGPUTextureUsage
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_SHADER_WRITE
@ GPU_TEXTURE_USAGE_ATTACHMENT
@ GPU_TEXTURE_USAGE_ATOMIC
@ GPU_SAMPLER_EXTEND_MODE_EXTEND
@ GPU_DEPTH24_STENCIL8
@ GPU_SAMPLER_FILTERING_LINEAR
void ensure(GPUAttachment depth=GPU_ATTACHMENT_NONE, GPUAttachment color1=GPU_ATTACHMENT_NONE, GPUAttachment color2=GPU_ATTACHMENT_NONE, GPUAttachment color3=GPU_ATTACHMENT_NONE, GPUAttachment color4=GPU_ATTACHMENT_NONE, GPUAttachment color5=GPU_ATTACHMENT_NONE, GPUAttachment color6=GPU_ATTACHMENT_NONE, GPUAttachment color7=GPU_ATTACHMENT_NONE, GPUAttachment color8=GPU_ATTACHMENT_NONE)
void submit(PassSimple &pass, View &view)
void clear(float4 values)
bool ensure_2d(eGPUTextureFormat format, int2 extent, eGPUTextureUsage usage=GPU_TEXTURE_USAGE_GENERAL, const float *data=nullptr, int mip_len=1)
bool ensure_3d(eGPUTextureFormat format, int3 extent, eGPUTextureUsage usage=GPU_TEXTURE_USAGE_GENERAL, const float *data=nullptr, int mip_len=1)
void visibility_test(bool enable)
Definition draw_view.hh:78
bool is_persp(int view_id=0) const
Definition draw_view.hh:90
const float4x4 & winmat(int view_id=0) const
Definition draw_view.hh:145
const float4x4 & viewmat(int view_id=0) const
Definition draw_view.hh:133
const float4x4 & viewinv(int view_id=0) const
Definition draw_view.hh:139
void sync(const float4x4 &view_mat, const float4x4 &win_mat, int view_id=0)
Definition draw_view.cc:20
void bind_texture(const char *name, GPUTexture *texture, GPUSamplerState state=sampler_auto)
void bind_resources(U &resources)
Definition draw_pass.hh:426
void bind_image(const char *name, GPUTexture *image)
void draw_procedural(GPUPrimType primitive, uint instance_len, uint vertex_len, uint vertex_first=-1, ResourceHandle handle={0}, uint custom_id=0)
Definition draw_pass.hh:833
void dispatch(int group_len)
Definition draw_pass.hh:874
void barrier(eGPUBarrier type)
Definition draw_pass.hh:943
void state_set(DRWState state, int clip_plane_count=0)
Definition draw_pass.hh:954
void shader_set(GPUShader *shader)
Definition draw_pass.hh:971
bool is_orthographic() const
const CameraData & data_get() const
bool is_perspective() const
bool is_camera_object() const
int2 render_extent_get() const
struct blender::eevee::HiZBuffer::@195 front
VolumeProbeModule volume_probes
SphereProbeModule sphere_probes
void info_append_i18n(const char *msg, Args &&...args)
UniformDataModule uniform_data
float2 rng_2d_get(eSamplingDimension starting_dimension) const
GPUShader * static_shader_get(eShaderType shader_type)
void set_view(View &view, int2 extent)
struct blender::eevee::VolumeModule::@197 properties
void object_sync(const ObjectHandle &ob_handle)
struct blender::eevee::VolumeModule::@198 occupancy
void world_sync(const WorldHandle &world_handle)
void draw_compute(View &main_view, int2 extent)
void draw_prepass(View &main_view)
std::optional< Bounds< float > > object_integration_range() const
void render(View &view, Texture &occupancy_tx)
bool has_volume() const
bool has_volume_absorption() const
bool has_volume_scatter() const
void DRW_stats_group_start(const char *name)
void DRW_stats_group_end()
@ DRW_STATE_WRITE_COLOR
Definition draw_state.hh:30
@ DRW_STATE_BLEND_CUSTOM
Definition draw_state.hh:63
#define RBUFS_UTILITY_TEX_SLOT
#define VOLUME_GROUP_SIZE
#define RBUFS_VALUE_SLOT
#define RBUFS_COLOR_SLOT
#define VOLUME_INTEGRATION_GROUP_SIZE
DOF_TILES_FLATTEN_GROUP_SIZE coc_tx GPU_R11F_G11F_B10F
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
SHADOW_TILEMAP_RES tiles_buf[] statistics_buf render_view_buf[SHADOW_VIEW_MAX] GPU_R32UI
uint top
static int left
MatBase< T, 4, 4 > orthographic(T left, T right, T bottom, T top, T near_clip, T far_clip)
Create an orthographic projection matrix using OpenGL coordinate convention: Maps each axis range to ...
MatBase< T, 4, 4 > orthographic_infinite(T left, T right, T bottom, T top)
Create an orthographic projection matrix using OpenGL coordinate convention: Maps each axis range to ...
MatBase< T, 4, 4 > translate(const MatBase< T, 4, 4 > &mat, const VecBase< T, 2 > &offset)
Translate a projection matrix after creation in the screen plane. Usually used for anti-aliasing jitt...
MatBase< T, 4, 4 > perspective_infinite(T left, T right, T bottom, T top, T near_clip)
Create a perspective projection matrix using OpenGL coordinate convention: Maps each axis range to [-...
MatBase< T, 4, 4 > perspective(T left, T right, T bottom, T top, T near_clip, T far_clip)
Create a perspective projection matrix using OpenGL coordinate convention: Maps each axis range to [-...
T reduce_max(const VecBase< T, Size > &a)
VecBase< T, Size > divide_ceil(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
T min(const T &a, const T &b)
CartesianBasis invert(const CartesianBasis &basis)
T fract(const T &a)
T max(const T &a, const T &b)
VecBase< uint32_t, 4 > uint4
bool assign_if_different(T &old_value, T new_value)
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
VecBase< int32_t, 3 > int3
VecBase< float, 3 > float3
float volumetric_light_clamp
float volumetric_sample_distribution
int volumetric_shadow_samples
struct SceneEEVEE eevee
const c_style_mat & ptr() const