Blender V4.3
overlay_next_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
9#pragma once
10
12
14
15namespace blender::draw::overlay {
16
21
22 private:
23 const SelectionType selection_type_;
24
25 PassSimple ps_ = {"LightProbes"};
26 PassMain ps_dots_ = {"LightProbesDots"};
27
28 struct CallBuffers {
29 const SelectionType selection_type_;
30
31 GroundLineInstanceBuf ground_line_buf = {selection_type_, "ground_line_buf"};
32 LightProbeInstanceBuf probe_cube_buf = {selection_type_, "probe_cube_buf"};
33 LightProbeInstanceBuf probe_planar_buf = {selection_type_, "probe_planar_buf"};
34 LightProbeInstanceBuf probe_grid_buf = {selection_type_, "probe_grid_buf"};
35 LightProbeInstanceBuf quad_solid_buf = {selection_type_, "quad_solid_buf"};
36 LightProbeInstanceBuf cube_buf = {selection_type_, "cube_buf"};
37 LightProbeInstanceBuf sphere_buf = {selection_type_, "sphere_buf"};
38 LightProbeInstanceBuf single_arrow_buf = {selection_type_, "single_arrow_buf"};
39
40 } call_buffers_{selection_type_};
41
42 public:
43 LightProbes(const SelectionType selection_type) : selection_type_(selection_type){};
44
45 void begin_sync(Resources &res, const State &state)
46 {
47 call_buffers_.ground_line_buf.clear();
48 call_buffers_.probe_cube_buf.clear();
49 call_buffers_.probe_planar_buf.clear();
50 call_buffers_.probe_grid_buf.clear();
51 call_buffers_.quad_solid_buf.clear();
52 call_buffers_.cube_buf.clear();
53 call_buffers_.sphere_buf.clear();
54 call_buffers_.single_arrow_buf.clear();
55
56 ps_dots_.init();
57 ps_dots_.state_set(DRW_STATE_WRITE_COLOR, state.clipping_plane_count);
58 ps_dots_.shader_set(res.shaders.extra_grid.get());
59 ps_dots_.bind_ubo("globalsBlock", &res.globals_buf);
60 ps_dots_.bind_texture("depthBuffer", &res.depth_tx);
61 ps_dots_.push_constant("isTransform", (G.moving & G_TRANSFORM_OBJ) != 0);
62 res.select_bind(ps_dots_);
63 }
64
65 void object_sync(const ObjectRef &ob_ref, Resources &res, const State &state)
66 {
67 const Object *ob = ob_ref.object;
68 const LightProbe *prb = static_cast<LightProbe *>(ob_ref.object->data);
69 const bool show_clipping = (prb->flag & LIGHTPROBE_FLAG_SHOW_CLIP_DIST) != 0;
70 const bool show_parallax = (prb->flag & LIGHTPROBE_FLAG_SHOW_PARALLAX) != 0;
71 const bool show_influence = (prb->flag & LIGHTPROBE_FLAG_SHOW_INFLUENCE) != 0;
72 const bool is_select = selection_type_ == SelectionType::ENABLED;
73 const bool show_data = (ob_ref.object->base_flag & BASE_SELECTED) || is_select;
74
75 const select::ID select_id = res.select_id(ob_ref);
76 const float4 color = res.object_wire_color(ob_ref, state);
77 ExtraInstanceData data(ob->object_to_world(), color, 1.0f);
78 float4x4 &matrix = data.object_to_world_;
79 float &clip_start = matrix[2].w;
80 float &clip_end = matrix[3].w;
81 float &draw_size = matrix[3].w;
82
83 switch (prb->type) {
85 clip_start = show_clipping ? prb->clipsta : -1.0;
86 clip_end = show_clipping ? prb->clipend : -1.0;
87 call_buffers_.probe_cube_buf.append(data, select_id);
88
89 call_buffers_.ground_line_buf.append(float4(matrix.location()), select_id);
90
91 if (show_influence) {
92 LightProbeInstanceBuf &attenuation = (prb->attenuation_type == LIGHTPROBE_SHAPE_BOX) ?
93 call_buffers_.cube_buf :
94 call_buffers_.sphere_buf;
95 const float f = 1.0f - prb->falloff;
96 ExtraInstanceData data(ob->object_to_world(), color, prb->distinf);
97 attenuation.append(data, select_id);
98 data.object_to_world_[3].w = prb->distinf * f;
99 attenuation.append(data, select_id);
100 }
101
102 if (show_parallax) {
103 LightProbeInstanceBuf &parallax = (prb->parallax_type == LIGHTPROBE_SHAPE_BOX) ?
104 call_buffers_.cube_buf :
105 call_buffers_.sphere_buf;
106 const float dist = ((prb->flag & LIGHTPROBE_FLAG_CUSTOM_PARALLAX) != 0) ? prb->distpar :
107 prb->distinf;
108 parallax.append(ExtraInstanceData(ob->object_to_world(), color, dist), select_id);
109 }
110 break;
112 clip_start = show_clipping ? 0.0f : -1.0f;
113 clip_end = show_clipping ? prb->clipend : -1.0f;
114 call_buffers_.probe_grid_buf.append(data, select_id);
115 {
116 /* Display surfel density as a cube. */
117 float3 axes_len = math::to_scale(ob->object_to_world());
118 float max_axis_len = math::reduce_max(axes_len);
119 float3 local_surfel_size = (0.5f / prb->grid_surfel_density) * (max_axis_len / axes_len);
120
121 float4x4 surfel_density_mat = math::from_loc_rot_scale<float4x4>(
122 float3(-1.0f + local_surfel_size),
124 float3(local_surfel_size));
125 surfel_density_mat = ob->object_to_world() * surfel_density_mat;
126 call_buffers_.cube_buf.append(ExtraInstanceData(surfel_density_mat, color, 1.0f),
127 select_id);
128 }
129
130 if (show_influence) {
131 call_buffers_.cube_buf.append(ExtraInstanceData(ob->object_to_world(), color, 1.0f),
132 select_id);
133 }
134
135 /* Data dots */
136 if (show_data) {
137 matrix[0].w = prb->grid_resolution_x;
138 matrix[1].w = prb->grid_resolution_y;
139 matrix[2].w = prb->grid_resolution_z;
140 /* Put theme id in matrix. */
141 matrix[3].w = res.object_wire_theme_id(ob_ref, state) == TH_ACTIVE ? 1.0f : 2.0f;
142
143 const uint cell_count = prb->grid_resolution_x * prb->grid_resolution_y *
144 prb->grid_resolution_z;
145 ps_dots_.push_constant("gridModelMatrix", matrix);
146 ps_dots_.draw_procedural(GPU_PRIM_POINTS, 1, cell_count, 0, {0}, select_id.get());
147 }
148 break;
149 }
151 call_buffers_.probe_planar_buf.append(data, select_id);
152
153 if (is_select && (prb->flag & LIGHTPROBE_FLAG_SHOW_DATA)) {
154 call_buffers_.quad_solid_buf.append(data, select_id);
155 }
156
157 if (show_influence) {
158 matrix.z_axis() = math::normalize(matrix.z_axis()) * prb->distinf;
159 call_buffers_.cube_buf.append(data, select_id);
160 matrix.z_axis() *= 1.0f - prb->falloff;
161 call_buffers_.cube_buf.append(data, select_id);
162 }
163
164 matrix.z_axis() = float3(0);
165 call_buffers_.cube_buf.append(data, select_id);
166
167 matrix.view<3, 3>() = math::normalize(float3x3(ob->object_to_world().view<3, 3>()));
168 draw_size = ob->empty_drawsize;
169 call_buffers_.single_arrow_buf.append(data, select_id);
170 break;
171 }
172 }
173
174 void end_sync(Resources &res, ShapeCache &shapes, const State &state)
175 {
176 ps_.init();
177 res.select_bind(ps_);
178
181 {
182 PassSimple::Sub &sub_pass = ps_.sub("empties");
183 sub_pass.state_set(pass_state, state.clipping_plane_count);
184 sub_pass.shader_set(res.shaders.extra_shape.get());
185 sub_pass.bind_ubo("globalsBlock", &res.globals_buf);
186 call_buffers_.probe_cube_buf.end_sync(sub_pass, shapes.lightprobe_cube.get());
187 call_buffers_.probe_planar_buf.end_sync(sub_pass, shapes.lightprobe_planar.get());
188 call_buffers_.probe_grid_buf.end_sync(sub_pass, shapes.lightprobe_grid.get());
189 call_buffers_.quad_solid_buf.end_sync(sub_pass, shapes.quad_solid.get());
190 call_buffers_.cube_buf.end_sync(sub_pass, shapes.cube.get());
191 call_buffers_.sphere_buf.end_sync(sub_pass, shapes.empty_sphere.get());
192 call_buffers_.single_arrow_buf.end_sync(sub_pass, shapes.single_arrow.get());
193 }
194 {
195 PassSimple::Sub &sub_pass = ps_.sub("ground_line");
196 sub_pass.state_set(pass_state | DRW_STATE_BLEND_ALPHA, state.clipping_plane_count);
197 sub_pass.shader_set(res.shaders.extra_ground_line.get());
198 sub_pass.bind_ubo("globalsBlock", &res.globals_buf);
199 call_buffers_.ground_line_buf.end_sync(sub_pass, shapes.ground_line.get());
200 }
201 }
202
203 void draw(Framebuffer &framebuffer, Manager &manager, View &view)
204 {
205 GPU_framebuffer_bind(framebuffer);
206 manager.submit(ps_, view);
207 }
208
209 void draw_color_only(Framebuffer &framebuffer, Manager &manager, View &view)
210 {
211 GPU_framebuffer_bind(framebuffer);
212 manager.submit(ps_dots_, view);
213 }
214};
215
216} // namespace blender::draw::overlay
@ G_TRANSFORM_OBJ
unsigned int uint
@ LIGHTPROBE_SHAPE_BOX
@ LIGHTPROBE_FLAG_SHOW_PARALLAX
@ LIGHTPROBE_FLAG_SHOW_CLIP_DIST
@ LIGHTPROBE_FLAG_SHOW_INFLUENCE
@ LIGHTPROBE_FLAG_SHOW_DATA
@ LIGHTPROBE_FLAG_CUSTOM_PARALLAX
@ LIGHTPROBE_TYPE_PLANE
@ LIGHTPROBE_TYPE_VOLUME
@ LIGHTPROBE_TYPE_SPHERE
#define BASE_SELECTED(v3d, base)
void GPU_framebuffer_bind(GPUFrameBuffer *framebuffer)
@ GPU_PRIM_POINTS
@ TH_ACTIVE
void submit(PassSimple &pass, View &view)
void bind_texture(const char *name, GPUTexture *texture, GPUSamplerState state=sampler_auto)
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
PassBase< DrawCommandBufType > & sub(const char *name)
Definition draw_pass.hh:616
void state_set(DRWState state, int clip_plane_count=0)
Definition draw_pass.hh:954
void bind_ubo(const char *name, GPUUniformBuf *buffer)
void push_constant(const char *name, const float &data)
void shader_set(GPUShader *shader)
Definition draw_pass.hh:971
void draw(Framebuffer &framebuffer, Manager &manager, View &view)
LightProbes(const SelectionType selection_type)
void begin_sync(Resources &res, const State &state)
void end_sync(Resources &res, ShapeCache &shapes, const State &state)
void object_sync(const ObjectRef &ob_ref, Resources &res, const State &state)
void draw_color_only(Framebuffer &framebuffer, Manager &manager, View &view)
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)
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)
VecBase< float, 4 > float4
MatBase< float, 3, 3 > float3x3
VecBase< float, 3 > float3
struct ExtraInstanceData ExtraInstanceData
short base_flag
float empty_drawsize
const float4 & object_wire_color(const ObjectRef &ob_ref, ThemeColorID theme_id) const
ThemeColorID object_wire_theme_id(const ObjectRef &ob_ref, const State &state) const
void append(const InstanceDataT &data, select::ID select_id)
void select_bind(PassSimple &pass)
const ID select_id(const ObjectRef &ob_ref, uint sub_object_id=0)