112 const Scene *scene_eval = inst_.scene;
115 const float camera_clip_start = inst_.camera.data_get().clip_near;
116 const float camera_clip_end = inst_.camera.data_get().clip_far;
120 if (!inst_.camera.is_camera_object() && inst_.camera.is_orthographic()) {
121 integration_start = -integration_end;
124 std::optional<Bounds<float>> volume_bounds = inst_.pipelines.volume.object_integration_range();
125 if (volume_bounds && !inst_.world.has_volume()) {
127 integration_start =
math::max(integration_start, -volume_bounds.value().max);
128 integration_end =
math::min(integration_end, -volume_bounds.value().min);
132 float near = -
math::max(integration_start, camera_clip_start - 1e-4f);
133 float far = -
math::min(integration_end, camera_clip_end + 1e-4f);
139 valid_history_ =
false;
142 if (valid_history_) {
144 if (current_objects_ != previous_objects_) {
145 valid_history_ =
false;
149 if (inst_.camera.is_perspective()) {
151 sample_distribution = 4.0f *
math::max(1.0f - sample_distribution, 1e-2f);
153 data_.depth_near = (far - near *
exp2(1.0f / sample_distribution)) / (far - near);
154 data_.depth_far = (1.0f - data_.depth_near) / near;
155 data_.depth_distribution = sample_distribution;
158 data_.depth_near = near;
159 data_.depth_far = far;
160 data_.depth_distribution = 0.0f;
164 occupancy_tx_.free();
165 prop_scattering_tx_.free();
166 prop_extinction_tx_.free();
167 prop_emission_tx_.free();
168 prop_phase_tx_.free();
169 prop_phase_weight_tx_.free();
170 scatter_tx_.current().free();
171 scatter_tx_.previous().free();
172 extinction_tx_.current().free();
173 extinction_tx_.previous().free();
174 integrated_scatter_tx_.free();
175 integrated_transmit_tx_.free();
178 result.scattering_tx_ = dummy_scatter_tx_;
179 result.transmittance_tx_ = dummy_transmit_tx_;
192 valid_history_ =
false;
196 bool has_scatter = inst_.world.has_volume_scatter() || inst_.pipelines.volume.has_scatter();
197 bool has_absorption = inst_.world.has_volume_absorption() ||
198 inst_.pipelines.volume.has_absorption();
199 use_lights_ = has_scatter;
206 prop_scattering_tx_.ensure_3d(gpu::TextureFormat::UFLOAT_11_11_10, data_.tex_size, usage);
207 prop_extinction_tx_.ensure_3d(gpu::TextureFormat::UFLOAT_11_11_10, data_.tex_size, usage);
208 prop_emission_tx_.ensure_3d(gpu::TextureFormat::UFLOAT_11_11_10, data_.tex_size, usage);
210 prop_phase_tx_.ensure_3d(gpu::TextureFormat::SFLOAT_16, data_.tex_size, usage);
211 prop_phase_weight_tx_.ensure_3d(gpu::TextureFormat::SFLOAT_16, data_.tex_size, usage);
216 occupancy_tx_.ensure_3d(
217 gpu::TextureFormat::UINT_32,
int3(data_.tex_size.xy(), occupancy_layers), occupancy_usage);
225 int hit_list_layer = 1;
226 if (inst_.pipelines.volume.use_hit_list()) {
227 hit_list_layer =
clamp_i(inst_.scene->eevee.volumetric_ray_depth, 1, 16);
228 hit_list_size = data_.tex_size.
xy();
230 hit_depth_tx_.ensure_3d(
231 gpu::TextureFormat::SFLOAT_32,
int3(hit_list_size, hit_list_layer), hit_depth_usage);
232 if (hit_count_tx_.ensure_2d(gpu::TextureFormat::UINT_32, hit_list_size, hit_count_usage)) {
233 hit_count_tx_.clear(
uint4(0u));
239 front_depth_tx_.ensure_2d(
240 gpu::TextureFormat::SFLOAT_32_DEPTH_UINT_8, data_.tex_size.xy(), front_depth_usage);
243 bool created =
false;
244 created |= scatter_tx_.current().ensure_3d(
245 gpu::TextureFormat::UFLOAT_11_11_10, data_.tex_size, usage);
246 created |= extinction_tx_.current().ensure_3d(
247 gpu::TextureFormat::UFLOAT_11_11_10, data_.tex_size, usage);
248 created |= scatter_tx_.previous().ensure_3d(
249 gpu::TextureFormat::UFLOAT_11_11_10, data_.tex_size, usage);
250 created |= extinction_tx_.previous().ensure_3d(
251 gpu::TextureFormat::UFLOAT_11_11_10, data_.tex_size, usage);
254 valid_history_ =
false;
257 integrated_scatter_tx_.ensure_3d(gpu::TextureFormat::UFLOAT_11_11_10, data_.tex_size, usage);
258 integrated_transmit_tx_.ensure_3d(gpu::TextureFormat::UFLOAT_11_11_10, data_.tex_size, usage);
261 result.scattering_tx_ = integrated_scatter_tx_;
262 result.transmittance_tx_ = integrated_transmit_tx_;
263 properties.scattering_tx_ = prop_scattering_tx_;
264 properties.extinction_tx_ = prop_extinction_tx_;
267 properties.phase_weight_tx_ = prop_phase_weight_tx_;
280 scatter_ps_.shader_set(
282 scatter_ps_.bind_resources(inst_.lights);
283 scatter_ps_.bind_resources(inst_.sphere_probes);
284 scatter_ps_.bind_resources(inst_.volume_probes);
285 scatter_ps_.bind_resources(inst_.shadows);
286 scatter_ps_.bind_resources(inst_.uniform_data);
287 scatter_ps_.bind_resources(inst_.sampling);
288 scatter_ps_.bind_image(
"in_scattering_img", &prop_scattering_tx_);
289 scatter_ps_.bind_image(
"in_extinction_img", &prop_extinction_tx_);
290 scatter_ps_.bind_texture(
"extinction_tx", &prop_extinction_tx_);
291 scatter_ps_.bind_image(
"in_emission_img", &prop_emission_tx_);
292 scatter_ps_.bind_image(
"in_phase_img", &prop_phase_tx_);
293 scatter_ps_.bind_image(
"in_phase_weight_img", &prop_phase_weight_tx_);
294 scatter_ps_.bind_texture(
"scattering_history_tx", &scatter_tx_.previous(), history_sampler);
295 scatter_ps_.bind_texture(
"extinction_history_tx", &extinction_tx_.previous(), history_sampler);
296 scatter_ps_.bind_image(
"out_scattering_img", &scatter_tx_.current());
297 scatter_ps_.bind_image(
"out_extinction_img", &extinction_tx_.current());
303 integration_ps_.init();
305 integration_ps_.bind_resources(inst_.uniform_data);
306 integration_ps_.bind_resources(inst_.sampling);
307 integration_ps_.bind_texture(
"in_scattering_tx", &scatter_tx_.current());
308 integration_ps_.bind_texture(
"in_extinction_tx", &extinction_tx_.current());
309 integration_ps_.bind_image(
"out_scattering_img", &integrated_scatter_tx_);
310 integration_ps_.bind_image(
"out_transmittance_img", &integrated_transmit_tx_);
313 integration_ps_.dispatch(
318 resolve_ps_.shader_set(inst_.shaders.static_shader_get(
VOLUME_RESOLVE));
319 resolve_ps_.bind_resources(inst_.uniform_data);
320 resolve_ps_.bind_resources(this->
result);
321 resolve_ps_.bind_resources(inst_.hiz_buffer.front);
322 resolve_ps_.bind_image(
RBUFS_COLOR_SLOT, &inst_.render_buffers.rp_color_tx);
323 resolve_ps_.bind_image(
RBUFS_VALUE_SLOT, &inst_.render_buffers.rp_value_tx);
336 int exponential_frame_count = 16;
337 if (inst_.is_image_render) {
339 exponential_frame_count = 0;
341 else if (!use_reprojection_) {
343 exponential_frame_count = 0;
345 else if (inst_.is_playback) {
350 exponential_frame_count = 3;
352 else if (inst_.is_transforming) {
356 exponential_frame_count = 3;
358 else if (inst_.is_navigating) {
361 exponential_frame_count = 8;
363 else if (inst_.is_viewport() && inst_.sampling.is_reset()) {
366 exponential_frame_count = 0;
369 if (!valid_history_) {
370 history_frame_count_ = 0;
376 history_frame_count_ =
math::min(history_frame_count_, exponential_frame_count);
380 float history_opacity = history_frame_count_ / (history_frame_count_ + 1.0f);
384 data_.history_opacity = (valid_history_) ? history_opacity : 0.0f;
386 float left, right, bottom,
top, near, far;
392 float2 volume_size = render_size *
float2(data_.tex_size.xy() * data_.tile_size) /
393 float2(inst_.film.render_extent_get());
395 right =
left + volume_size.x;
396 top = bottom + volume_size.y;
398 float4x4 winmat_infinite, winmat_finite;
401 winmat_infinite = main_view.
is_persp() ?
405 winmat_finite = main_view.
is_persp() ?
409 data_.winmat_stable = winmat_finite;
417 jitter *= data_.inv_tex_size.
xy();
422 data_.winmat_finite = winmat_finite;
426 data_.curr_view_to_past_view = history_viewmat_ * main_view.
viewinv();
428 inst_.uniform_data.push_update();
431 occupancy_fb_.bind();
432 inst_.pipelines.world_volume.render(main_view);
434 volume_view.sync(main_view.
viewmat(), winmat_infinite);
437 volume_view.visibility_test(
false);
439 if (!current_objects_.is_empty()) {
440 inst_.pipelines.volume.render(volume_view, occupancy_tx_);