Blender V5.0
overlay_lightprobe.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#pragma once
10
12
13#include "overlay_base.hh"
14
15namespace blender::draw::overlay {
16
21 using LightProbeInstanceBuf = ShapeInstanceBuf<ExtraInstanceData>;
22 using GroundLineInstanceBuf = ShapeInstanceBuf<float4>;
23 using DotsInstanceBuf = ShapeInstanceBuf<float4x4>;
24
25 private:
26 const SelectionType selection_type_;
27
28 PassSimple ps_ = {"LightProbes"};
29 PassMain ps_dots_ = {"LightProbesDots"};
30
31 struct CallBuffers {
32 const SelectionType selection_type_;
33
34 GroundLineInstanceBuf ground_line_buf = {selection_type_, "ground_line_buf"};
35 LightProbeInstanceBuf probe_cube_buf = {selection_type_, "probe_cube_buf"};
36 LightProbeInstanceBuf probe_planar_buf = {selection_type_, "probe_planar_buf"};
37 LightProbeInstanceBuf probe_grid_buf = {selection_type_, "probe_grid_buf"};
38 LightProbeInstanceBuf quad_solid_buf = {selection_type_, "quad_solid_buf"};
39 LightProbeInstanceBuf cube_buf = {selection_type_, "cube_buf"};
40 LightProbeInstanceBuf sphere_buf = {selection_type_, "sphere_buf"};
41 LightProbeInstanceBuf single_arrow_buf = {selection_type_, "single_arrow_buf"};
42
43 } call_buffers_{selection_type_};
44
45 public:
46 LightProbes(const SelectionType selection_type) : selection_type_(selection_type) {};
47
48 void begin_sync(Resources &res, const State &state) final
49 {
50 enabled_ = state.is_space_v3d() && state.show_extras();
51 if (!enabled_) {
52 return;
53 }
54
55 call_buffers_.ground_line_buf.clear();
56 call_buffers_.probe_cube_buf.clear();
57 call_buffers_.probe_planar_buf.clear();
58 call_buffers_.probe_grid_buf.clear();
59 call_buffers_.quad_solid_buf.clear();
60 call_buffers_.cube_buf.clear();
61 call_buffers_.sphere_buf.clear();
62 call_buffers_.single_arrow_buf.clear();
63
64 ps_dots_.init();
65 ps_dots_.state_set(DRW_STATE_WRITE_COLOR, state.clipping_plane_count);
66 ps_dots_.shader_set(res.shaders->extra_grid.get());
67 ps_dots_.bind_ubo(OVERLAY_GLOBALS_SLOT, &res.globals_buf);
68 ps_dots_.bind_ubo(DRW_CLIPPING_UBO_SLOT, &res.clip_planes_buf);
69 ps_dots_.bind_texture("depth_buffer", &res.depth_tx);
70 ps_dots_.push_constant("is_transform", (G.moving & G_TRANSFORM_OBJ) != 0);
71 res.select_bind(ps_dots_);
72 }
73
74 void object_sync(Manager & /*manager*/,
75 const ObjectRef &ob_ref,
76 Resources &res,
77 const State &state) final
78 {
79 if (!enabled_) {
80 return;
81 }
82
83 const Object *ob = ob_ref.object;
85 const bool show_clipping = (prb.flag & LIGHTPROBE_FLAG_SHOW_CLIP_DIST) != 0;
86 const bool show_parallax = (prb.flag & LIGHTPROBE_FLAG_SHOW_PARALLAX) != 0;
87 const bool show_influence = (prb.flag & LIGHTPROBE_FLAG_SHOW_INFLUENCE) != 0;
88 const bool show_data = (ob_ref.object->base_flag & BASE_SELECTED) || res.is_selection();
89
90 const select::ID select_id = res.select_id(ob_ref);
91 const float4 color = res.object_wire_color(ob_ref, state);
92 ExtraInstanceData data(ob->object_to_world(), color, 1.0f);
93 float4x4 &matrix = data.object_to_world;
94 float &clip_start = matrix[2].w;
95 float &clip_end = matrix[3].w;
96 float &draw_size = matrix[3].w;
97
98 switch (prb.type) {
100 clip_start = show_clipping ? prb.clipsta : -1.0;
101 clip_end = show_clipping ? prb.clipend : -1.0;
102 call_buffers_.probe_cube_buf.append(data, select_id);
103
104 call_buffers_.ground_line_buf.append(float4(matrix.location(), 0.0f), select_id);
105
106 if (show_influence) {
107 LightProbeInstanceBuf &attenuation = (prb.attenuation_type == LIGHTPROBE_SHAPE_BOX) ?
108 call_buffers_.cube_buf :
109 call_buffers_.sphere_buf;
110 const float f = 1.0f - prb.falloff;
111 ExtraInstanceData data(ob->object_to_world(), color, prb.distinf);
112 attenuation.append(data, select_id);
113 data.object_to_world[3].w = prb.distinf * f;
114 attenuation.append(data, select_id);
115 }
116
117 if (show_parallax) {
118 LightProbeInstanceBuf &parallax = (prb.parallax_type == LIGHTPROBE_SHAPE_BOX) ?
119 call_buffers_.cube_buf :
120 call_buffers_.sphere_buf;
121 const float dist = ((prb.flag & LIGHTPROBE_FLAG_CUSTOM_PARALLAX) != 0) ? prb.distpar :
122 prb.distinf;
123 parallax.append(ExtraInstanceData(ob->object_to_world(), color, dist), select_id);
124 }
125 break;
127 clip_start = show_clipping ? 0.0f : -1.0f;
128 clip_end = show_clipping ? prb.clipend : -1.0f;
129 call_buffers_.probe_grid_buf.append(data, select_id);
130 {
131 /* Display surfel density as a cube. */
132 float3 axes_len = math::to_scale(ob->object_to_world());
133 float max_axis_len = math::reduce_max(axes_len);
134 float3 local_surfel_size = (0.5f / prb.grid_surfel_density) * (max_axis_len / axes_len);
135
136 float4x4 surfel_density_mat = math::from_loc_rot_scale<float4x4>(
137 float3(-1.0f + local_surfel_size),
139 float3(local_surfel_size));
140 surfel_density_mat = ob->object_to_world() * surfel_density_mat;
141 call_buffers_.cube_buf.append(ExtraInstanceData(surfel_density_mat, color, 1.0f),
142 select_id);
143 }
144
145 if (show_influence) {
146 call_buffers_.cube_buf.append(ExtraInstanceData(ob->object_to_world(), color, 1.0f),
147 select_id);
148 }
149
150 /* Data dots */
151 if (show_data) {
152 matrix[0].w = prb.grid_resolution_x;
153 matrix[1].w = prb.grid_resolution_y;
154 matrix[2].w = prb.grid_resolution_z;
155 /* Put theme id in matrix. */
156 matrix[3].w = res.object_wire_theme_id(ob_ref, state) == TH_ACTIVE ? 1.0f : 2.0f;
157
158 const uint cell_count = prb.grid_resolution_x * prb.grid_resolution_y *
159 prb.grid_resolution_z;
160 ps_dots_.push_constant("grid_model_matrix", matrix);
161 ps_dots_.draw_procedural(GPU_PRIM_POINTS, 1, cell_count, 0, {0}, select_id.get());
162 }
163 break;
164 }
166 call_buffers_.probe_planar_buf.append(data, select_id);
167
168 if (res.is_selection() && (prb.flag & LIGHTPROBE_FLAG_SHOW_DATA)) {
169 call_buffers_.quad_solid_buf.append(data, select_id);
170 }
171
172 if (show_influence) {
173 matrix.z_axis() = math::normalize(matrix.z_axis()) * prb.distinf;
174 call_buffers_.cube_buf.append(data, select_id);
175 matrix.z_axis() *= 1.0f - prb.falloff;
176 call_buffers_.cube_buf.append(data, select_id);
177 }
178
179 matrix.z_axis() = float3(0);
180 call_buffers_.cube_buf.append(data, select_id);
181
182 matrix.view<3, 3>() = math::normalize(float3x3(ob->object_to_world().view<3, 3>()));
183 draw_size = ob->empty_drawsize;
184 call_buffers_.single_arrow_buf.append(data, select_id);
185 break;
186 }
187 }
188
189 void end_sync(Resources &res, const State &state) final
190 {
191 if (!enabled_) {
192 return;
193 }
194
195 ps_.init();
196 ps_.bind_ubo(OVERLAY_GLOBALS_SLOT, &res.globals_buf);
197 ps_.bind_ubo(DRW_CLIPPING_UBO_SLOT, &res.clip_planes_buf);
198 res.select_bind(ps_);
199
202 {
203 PassSimple::Sub &sub_pass = ps_.sub("empties");
204 sub_pass.state_set(pass_state, state.clipping_plane_count);
205 sub_pass.shader_set(res.shaders->extra_shape.get());
206 call_buffers_.probe_cube_buf.end_sync(sub_pass, res.shapes.lightprobe_cube.get());
207 call_buffers_.probe_planar_buf.end_sync(sub_pass, res.shapes.lightprobe_planar.get());
208 call_buffers_.probe_grid_buf.end_sync(sub_pass, res.shapes.lightprobe_grid.get());
209 call_buffers_.quad_solid_buf.end_sync(sub_pass, res.shapes.quad_solid.get());
210 call_buffers_.cube_buf.end_sync(sub_pass, res.shapes.cube.get());
211 call_buffers_.sphere_buf.end_sync(sub_pass, res.shapes.empty_sphere.get());
212 call_buffers_.single_arrow_buf.end_sync(sub_pass, res.shapes.single_arrow.get());
213 }
214 {
215 PassSimple::Sub &sub_pass = ps_.sub("ground_line");
216 sub_pass.state_set(pass_state | DRW_STATE_BLEND_ALPHA, state.clipping_plane_count);
217 sub_pass.shader_set(res.shaders->extra_ground_line.get());
218 call_buffers_.ground_line_buf.end_sync(sub_pass, res.shapes.ground_line.get());
219 }
220 }
221
222 void pre_draw(Manager &manager, View &view) final
223 {
224 if (!enabled_) {
225 return;
226 }
227
228 manager.generate_commands(ps_dots_, view);
229 }
230
231 void draw_line(Framebuffer &framebuffer, Manager &manager, View &view) final
232 {
233 if (!enabled_) {
234 return;
235 }
236
237 GPU_framebuffer_bind(framebuffer);
238 manager.submit(ps_, view);
239 }
240
241 void draw_color_only(Framebuffer &framebuffer, Manager &manager, View &view) final
242 {
243 if (!enabled_) {
244 return;
245 }
246
247 GPU_framebuffer_bind(framebuffer);
248 manager.submit_only(ps_dots_, view);
249 }
250};
251
252} // namespace blender::draw::overlay
@ G_TRANSFORM_OBJ
unsigned int uint
@ LIGHTPROBE_FLAG_SHOW_PARALLAX
@ LIGHTPROBE_FLAG_SHOW_CLIP_DIST
@ LIGHTPROBE_FLAG_SHOW_INFLUENCE
@ LIGHTPROBE_FLAG_SHOW_DATA
@ LIGHTPROBE_FLAG_CUSTOM_PARALLAX
@ LIGHTPROBE_SHAPE_BOX
@ LIGHTPROBE_TYPE_PLANE
@ LIGHTPROBE_TYPE_VOLUME
@ LIGHTPROBE_TYPE_SPHERE
#define BASE_SELECTED(v3d, base)
T & DRW_object_get_data_for_drawing(const Object &object)
static AppView * view
void GPU_framebuffer_bind(blender::gpu::FrameBuffer *fb)
@ GPU_PRIM_POINTS
@ TH_ACTIVE
BMesh const char void * data
void shader_set(gpu::Shader *shader)
void state_set(DRWState state, int clip_plane_count=0)
detail::PassBase< command::DrawCommandBuf > Sub
Definition draw_pass.hh:499
void pre_draw(Manager &manager, View &view) final
void draw_line(Framebuffer &framebuffer, Manager &manager, View &view) final
LightProbes(const SelectionType selection_type)
void begin_sync(Resources &res, const State &state) final
void end_sync(Resources &res, const State &state) final
void draw_color_only(Framebuffer &framebuffer, Manager &manager, View &view) final
void object_sync(Manager &, const ObjectRef &ob_ref, Resources &res, const State &state) final
#define DRW_CLIPPING_UBO_SLOT
#define OVERLAY_GLOBALS_SLOT
DRWState
Definition draw_state.hh:25
@ DRW_STATE_BLEND_ALPHA
Definition draw_state.hh:55
@ DRW_STATE_WRITE_DEPTH
Definition draw_state.hh:29
@ DRW_STATE_WRITE_COLOR
Definition draw_state.hh:30
@ DRW_STATE_DEPTH_LESS_EQUAL
Definition draw_state.hh:38
static ulong state[N]
#define G(x, y, z)
select::SelectionType SelectionType
detail::Pass< command::DrawCommandBuf > PassSimple
detail::Pass< command::DrawMultiBuf > PassMain
T reduce_max(const VecBase< T, Size > &a)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
VecBase< T, 3 > to_scale(const MatBase< T, NumCol, NumRow > &mat)
MatT from_loc_rot_scale(const typename MatT::loc_type &location, const RotationT &rotation, const VecBase< typename MatT::base_type, ScaleDim > &scale)
MatBase< float, 4, 4 > float4x4
VecBase< float, 4 > float4
MatBase< float, 3, 3 > float3x3
VecBase< float, 3 > float3
float empty_drawsize
const MatView< T, ViewNumCol, ViewNumRow, NumCol, NumRow, SrcStartCol, SrcStartRow, Alignment > view() const
void append(const InstanceDataT &data, select::ID select_id)