Blender V5.0
eevee_lightprobe_planar.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
6#include "eevee_instance.hh"
7
8namespace blender::eevee {
9
10using namespace blender::math;
11
12/* -------------------------------------------------------------------- */
15
17{
18 /* Invert the up axis to avoid changing handedness (see #137022). */
19 this->viewmat = from_scale<float4x4>(float3(1, -1, 1)) * view.viewmat() *
20 reflection_matrix_get();
21 this->winmat = view.winmat();
22 /* Invert Y offset in the projection matrix to compensate the flip above (see #141112). */
23 this->winmat[2][1] = -this->winmat[2][1];
24
25 this->wininv = invert(this->winmat);
26
28 this->normal = normalize(plane_to_world.z_axis());
29
30 float3 view_vec = view.is_persp() ? view.location() - plane_to_world.location() : view.forward();
31 bool view_is_below_plane = dot(view_vec, plane_to_world.z_axis()) < 0.0;
32 if (view_is_below_plane) {
33 this->normal = -this->normal;
34 }
35 this->layer_id = layer_id;
36}
37
39
40/* -------------------------------------------------------------------- */
43
45{
46 /* This triggers the compilation of clipped shader only if we can detect light-probe planes. */
47 if (inst_.is_viewport()) {
48 /* This check needs to happen upfront before sync, so we use the previous sync result. */
49 update_probes_ = !inst_.light_probes.planar_map_.is_empty();
50 }
51 else {
52 /* TODO(jbakker): should we check on the subtype as well? Now it also populates even when
53 * there are other light probes in the scene. */
54 update_probes_ = DEG_id_type_any_exists(inst_.depsgraph, ID_LP);
55 }
56
57 do_display_draw_ = false;
58}
59
61{
62 /* When first planar probes are enabled it can happen that the first sample is off. */
63 if (!update_probes_ && !inst_.light_probes.planar_map_.is_empty()) {
65 }
66}
67
68void PlanarProbeModule::set_view(const draw::View &main_view, int2 main_view_extent)
69{
70 GBuffer &gbuf = inst_.gbuffer;
71
72 const int64_t num_probes = inst_.light_probes.planar_map_.size();
73
74 /* TODO resolution percentage. */
75 int2 extent = main_view_extent;
76 int layer_count = num_probes;
77
78 if (num_probes == 0) {
79 /* Create valid dummy texture. */
80 extent = int2(1);
81 layer_count = 1;
82 }
83
85 radiance_tx_.ensure_2d_array(gpu::TextureFormat::UFLOAT_11_11_10, extent, layer_count, usage);
86 depth_tx_.ensure_2d_array(gpu::TextureFormat::SFLOAT_32_DEPTH, extent, layer_count, usage);
87 depth_tx_.ensure_layer_views();
88
89 do_display_draw_ = inst_.draw_overlays && num_probes > 0;
90
91 int resource_index = 0;
92 int display_index = 0;
93 for (PlanarProbe &probe : inst_.light_probes.planar_map_.values()) {
94 if (resource_index == PLANAR_PROBE_MAX) {
95 break;
96 }
97
98 PlanarResources &res = resources_[resource_index];
99
100 /* TODO Cull out of view planars. */
101
102 probe.set_view(main_view, resource_index);
103 probe_planar_buf_[resource_index] = probe;
104
105 res.view.sync(probe.viewmat, probe.winmat);
106
107 world_clip_buf_.plane = probe.reflection_clip_plane_get();
108 world_clip_buf_.push_update();
109
110 gbuf.acquire(extent,
111 inst_.pipelines.deferred.header_layer_count(),
112 inst_.pipelines.deferred.closure_layer_count(),
113 inst_.pipelines.deferred.normal_layer_count());
114
115 res.combined_fb.ensure(GPU_ATTACHMENT_TEXTURE_LAYER(depth_tx_, resource_index),
116 GPU_ATTACHMENT_TEXTURE_LAYER(radiance_tx_, resource_index));
117
118 res.gbuffer_fb.ensure(GPU_ATTACHMENT_TEXTURE_LAYER(depth_tx_, resource_index),
119 GPU_ATTACHMENT_TEXTURE_LAYER(radiance_tx_, resource_index),
124
125 inst_.pipelines.planar.render(
126 res.view, depth_tx_.layer_view(resource_index), res.gbuffer_fb, res.combined_fb, extent);
127
128 if (do_display_draw_ && probe.viewport_display) {
129 display_data_buf_.get_or_resize(display_index++) = {probe.plane_to_world, resource_index};
130 }
131
132 resource_index++;
133 }
134
135 gbuf.release();
136
137 if (resource_index < PLANAR_PROBE_MAX) {
138 /* Tag the end of the array. */
139 probe_planar_buf_[resource_index].layer_id = -1;
140 }
141 probe_planar_buf_.push_update();
142
143 do_display_draw_ = display_index > 0;
144 if (do_display_draw_) {
145 display_data_buf_.resize(display_index);
146 display_data_buf_.push_update();
147 }
148}
149
151{
152 if (!do_display_draw_) {
153 return;
154 }
155
156 viewport_display_ps_.init();
157 viewport_display_ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
158 DRW_STATE_CLIP_CONTROL_UNIT_RANGE | inst_.film.depth.test_state |
160 viewport_display_ps_.framebuffer_set(&view_fb);
161 viewport_display_ps_.shader_set(inst_.shaders.static_shader_get(DISPLAY_PROBE_PLANAR));
162 SphereProbeData &world_data = *static_cast<SphereProbeData *>(&inst_.light_probes.world_sphere_);
163 viewport_display_ps_.push_constant("world_coord_packed",
164 reinterpret_cast<int4 *>(&world_data.atlas_coord));
165 viewport_display_ps_.bind_resources(*this);
166 viewport_display_ps_.bind_resources(inst_.sphere_probes);
167 viewport_display_ps_.bind_ssbo("display_data_buf", display_data_buf_);
168 viewport_display_ps_.draw_procedural(GPU_PRIM_TRIS, 1, display_data_buf_.size() * 6);
169
170 inst_.manager->submit(viewport_display_ps_, view);
171}
172
174
175} // namespace blender::eevee
bool DEG_id_type_any_exists(const Depsgraph *depsgraph, short id_type)
@ ID_LP
static AppView * view
#define GPU_ATTACHMENT_TEXTURE_LAYER(_texture, _layer)
@ GPU_PRIM_TRIS
eGPUTextureUsage
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_ATTACHMENT
long long int int64_t
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)
gpu::Texture * layer_view(int layer)
void sync(const float4x4 &view_mat, const float4x4 &win_mat, int view_id=0)
Definition draw_view.cc:27
void set_view(const draw::View &main_view, int2 main_view_extent)
void viewport_draw(View &view, gpu::FrameBuffer *view_fb)
void DRW_viewport_request_redraw()
@ DRW_STATE_WRITE_DEPTH
Definition draw_state.hh:29
@ DRW_STATE_CLIP_CONTROL_UNIT_RANGE
Definition draw_state.hh:68
@ DRW_STATE_WRITE_COLOR
Definition draw_state.hh:30
@ DRW_STATE_CULL_BACK
Definition draw_state.hh:43
#define PLANAR_PROBE_MAX
VecBase< float, D > normalize(VecOp< float, D >) RET
MatBase< R, C > transpose(MatBase< C, R >) RET
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
CartesianBasis invert(const CartesianBasis &basis)
MatT from_scale(const VecBase< typename MatT::base_type, ScaleDim > &scale)
VecBase< int32_t, 4 > int4
MatBase< float, 3, 4 > float3x4
VecBase< int32_t, 2 > int2
VecBase< float, 3 > float3
void acquire(int2 extent, int header_count, int data_count, int normal_count)
void set_view(const draw::View &view, int layer_id)