Blender V4.5
overlay_attribute_viewer.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
11#include "BKE_curves.hh"
12#include "BKE_customdata.hh"
13#include "BKE_geometry_set.hh"
14#include "DNA_curve_types.h"
16
17#include "draw_cache.hh"
18#include "draw_cache_impl.hh"
19#include "overlay_base.hh"
20
21namespace blender::draw::overlay {
22
28 private:
29 PassMain ps_ = {"attribute_viewer_ps_"};
30
31 PassMain::Sub *mesh_sub_ = nullptr;
32 PassMain::Sub *pointcloud_sub_ = nullptr;
33 PassMain::Sub *curve_sub_ = nullptr;
34 PassMain::Sub *curves_sub_ = nullptr;
35 PassMain::Sub *instance_sub_ = nullptr;
36
37 public:
38 void begin_sync(Resources &res, const State &state) final
39 {
40 ps_.init();
41 enabled_ = state.is_space_v3d() && !res.is_selection() && state.show_attribute_viewer();
42 if (!enabled_) {
43 return;
44 };
45 ps_.bind_ubo(OVERLAY_GLOBALS_SLOT, &res.globals_buf);
46 ps_.bind_ubo(DRW_CLIPPING_UBO_SLOT, &res.clip_planes_buf);
48 state.clipping_plane_count);
49
50 auto create_sub = [&](const char *name, GPUShader *shader) {
51 auto &sub = ps_.sub(name);
52 sub.shader_set(shader);
53 return ⊂
54 };
55
56 mesh_sub_ = create_sub("mesh", res.shaders->attribute_viewer_mesh.get());
57 pointcloud_sub_ = create_sub("pointcloud", res.shaders->attribute_viewer_pointcloud.get());
58 curve_sub_ = create_sub("curve", res.shaders->attribute_viewer_curve.get());
59 curves_sub_ = create_sub("curves", res.shaders->attribute_viewer_curves.get());
60 instance_sub_ = create_sub("instance", res.shaders->uniform_color.get());
61 }
62
63 void object_sync(Manager &manager,
64 const ObjectRef &ob_ref,
65 Resources & /*res*/,
66 const State &state) final
67 {
68 const DupliObject *dupli_object = ob_ref.dupli_object;
69 const bool is_preview = dupli_object != nullptr &&
70 dupli_object->preview_base_geometry != nullptr;
71 if (!enabled_ || !is_preview) {
72 return;
73 }
74
75 if (dupli_object->preview_instance_index >= 0) {
76 const auto &instances =
78 if (const std::optional<blender::bke::AttributeMetaData> meta_data =
79 instances.attributes()->lookup_meta_data(".viewer"))
80 {
81 if (attribute_type_supports_viewer_overlay(meta_data->data_type)) {
82 populate_for_instance(ob_ref, *dupli_object, state, manager);
83 return;
84 }
85 }
86 }
87 populate_for_geometry(ob_ref, state, manager);
88 }
89
90 void pre_draw(Manager &manager, View &view) final
91 {
92 if (!enabled_) {
93 return;
94 }
95
96 manager.generate_commands(ps_, view);
97 }
98
99 void draw_line(Framebuffer &framebuffer, Manager &manager, View &view) final
100 {
101 if (!enabled_) {
102 return;
103 }
104
105 GPU_framebuffer_bind(framebuffer);
106 manager.submit_only(ps_, view);
107 }
108
109 private:
110 void populate_for_instance(const ObjectRef &ob_ref,
111 const DupliObject &dupli_object,
112 const State &state,
113 Manager &manager)
114 {
115 Object &object = *ob_ref.object;
116 const bke::GeometrySet &base_geometry = *dupli_object.preview_base_geometry;
117 const bke::InstancesComponent &instances =
118 *base_geometry.get_component<bke::InstancesComponent>();
119 const bke::AttributeAccessor instance_attributes = *instances.attributes();
120 const VArray attribute = *instance_attributes.lookup<ColorGeometry4f>(".viewer");
121 if (!attribute) {
122 return;
123 }
124 ColorGeometry4f color = attribute.get(dupli_object.preview_instance_index);
125 color.a *= state.overlay.viewer_attribute_opacity;
126 switch (object.type) {
127 case OB_MESH: {
128 ResourceHandle res_handle = manager.unique_handle(ob_ref);
129
130 {
131 gpu::Batch *batch = DRW_cache_mesh_surface_get(&object);
132 auto &sub = *instance_sub_;
133 sub.push_constant("ucolor", float4(color));
134 sub.draw(batch, res_handle);
135 }
136 if (gpu::Batch *batch = DRW_cache_mesh_loose_edges_get(&object)) {
137 auto &sub = *instance_sub_;
138 sub.push_constant("ucolor", float4(color));
139 sub.draw(batch, res_handle);
140 }
141
142 break;
143 }
144 case OB_POINTCLOUD: {
145 auto &sub = *pointcloud_sub_;
146 gpu::Batch *batch = pointcloud_sub_pass_setup(sub, &object, nullptr);
147 sub.push_constant("ucolor", float4(color));
148 sub.draw(batch, manager.unique_handle(ob_ref));
149 break;
150 }
151 case OB_CURVES_LEGACY: {
152 gpu::Batch *batch = DRW_cache_curve_edge_wire_get(&object);
153 auto &sub = *instance_sub_;
154 sub.push_constant("ucolor", float4(color));
155 ResourceHandle res_handle = manager.resource_handle(object.object_to_world());
156 sub.draw(batch, res_handle);
157 break;
158 }
159 case OB_CURVES: {
160 /* Not supported yet because instances of this type are currently drawn as legacy curves.
161 */
162 break;
163 }
164 }
165 }
166
167 static bool attribute_type_supports_viewer_overlay(const eCustomDataType data_type)
168 {
169 return CD_TYPE_AS_MASK(data_type) &
171 }
172
173 void populate_for_geometry(const ObjectRef &ob_ref, const State &state, Manager &manager)
174 {
175 const float opacity = state.overlay.viewer_attribute_opacity;
176 Object &object = *ob_ref.object;
177 switch (object.type) {
178 case OB_MESH: {
180 if (const std::optional<bke::AttributeMetaData> meta_data =
181 mesh.attributes().lookup_meta_data(".viewer"))
182 {
183 if (attribute_type_supports_viewer_overlay(meta_data->data_type)) {
185 auto &sub = *mesh_sub_;
186 sub.push_constant("opacity", opacity);
187 sub.draw(batch, manager.unique_handle(ob_ref));
188 }
189 }
190 break;
191 }
192 case OB_POINTCLOUD: {
194 if (const std::optional<bke::AttributeMetaData> meta_data =
195 pointcloud.attributes().lookup_meta_data(".viewer"))
196 {
197 if (attribute_type_supports_viewer_overlay(meta_data->data_type)) {
198 gpu::VertBuf **vertbuf = DRW_pointcloud_evaluated_attribute(&pointcloud, ".viewer");
199 /* Avoid trying to bind an empty `vertbuf` which causes assert / undefined behavior. */
200 if (pointcloud.totpoint > 0 && vertbuf != nullptr) {
201 auto &sub = *pointcloud_sub_;
202 gpu::Batch *batch = pointcloud_sub_pass_setup(sub, &object, nullptr);
203 sub.push_constant("opacity", opacity);
204 sub.bind_texture("attribute_tx", vertbuf);
205 sub.draw(batch, manager.unique_handle(ob_ref));
206 }
207 }
208 }
209 break;
210 }
211 case OB_CURVES_LEGACY: {
213 if (curve.curve_eval) {
214 const bke::CurvesGeometry &curves = curve.curve_eval->geometry.wrap();
215 if (const std::optional<bke::AttributeMetaData> meta_data =
216 curves.attributes().lookup_meta_data(".viewer"))
217 {
218 if (attribute_type_supports_viewer_overlay(meta_data->data_type)) {
220 auto &sub = *curve_sub_;
221 sub.push_constant("opacity", opacity);
222 ResourceHandle res_handle = manager.resource_handle(object.object_to_world());
223 sub.draw(batch, res_handle);
224 }
225 }
226 }
227 break;
228 }
229 case OB_CURVES: {
231 const bke::CurvesGeometry &curves = curves_id.geometry.wrap();
232 if (const std::optional<bke::AttributeMetaData> meta_data =
233 curves.attributes().lookup_meta_data(".viewer"))
234 {
235 if (attribute_type_supports_viewer_overlay(meta_data->data_type)) {
236 bool is_point_domain;
238 &curves_id, ".viewer", &is_point_domain);
239 auto &sub = *curves_sub_;
240 gpu::Batch *batch = curves_sub_pass_setup(sub, state.scene, ob_ref.object);
241 sub.push_constant("opacity", opacity);
242 sub.push_constant("is_point_domain", is_point_domain);
243 sub.bind_texture("color_tx", *texture);
244 sub.draw(batch, manager.unique_handle(ob_ref));
245 }
246 }
247 break;
248 }
249 }
250 }
251};
252} // namespace blender::draw::overlay
Low-level operations for curves.
CustomData interface, see also DNA_customdata_types.h.
#define CD_TYPE_AS_MASK(_type)
struct Curve Curve
struct Curves Curves
struct Mesh Mesh
@ OB_MESH
@ OB_POINTCLOUD
@ OB_CURVES_LEGACY
@ OB_CURVES
struct Object Object
struct PointCloud PointCloud
static AppView * view
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
AttributeSet attributes
T get(const int64_t index) const
std::optional< AttributeAccessor > attributes() const final
ResourceHandleRange unique_handle(const ObjectRef &ref)
ResourceHandleRange resource_handle(const ObjectRef &ref, float inflate_bounds=0.0f)
void push_constant(const char *name, const float &data)
detail::PassBase< command::DrawMultiBuf > Sub
Definition draw_pass.hh:490
void draw_line(Framebuffer &framebuffer, Manager &manager, View &view) final
void begin_sync(Resources &res, const State &state) final
void object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &, const State &state) final
void pre_draw(Manager &manager, View &view) final
Mesh & DRW_object_get_data_for_drawing(const Object &object)
#define DRW_CLIPPING_UBO_SLOT
#define OVERLAY_GLOBALS_SLOT
@ DRW_STATE_BLEND_ALPHA
Definition draw_state.hh:55
@ DRW_STATE_WRITE_COLOR
Definition draw_state.hh:30
@ DRW_STATE_DEPTH_LESS_EQUAL
Definition draw_state.hh:38
struct @064345207361167251075330302113175271221317160336::@113254110077376341056327177062323111323010325277 batch
TEX_TEMPLATE DataVec texture(T, FltCoord, float=0.0f) RET
#define CD_MASK_PROP_ALL
#define CD_MASK_PROP_QUATERNION
#define CD_MASK_PROP_FLOAT4X4
static ulong state[N]
gpu::Batch * curves_sub_pass_setup(PassMain::Sub &ps, const Scene *scene, Object *ob, GPUMaterial *gpu_material=nullptr)
gpu::Batch * DRW_cache_curve_edge_wire_viewer_attribute_get(Object *ob)
detail::Pass< command::DrawMultiBuf > PassMain
gpu::Batch * DRW_cache_mesh_loose_edges_get(Object *ob)
gpu::Batch * pointcloud_sub_pass_setup(PassMain::Sub &sub_ps, Object *object, GPUMaterial *gpu_material=nullptr)
gpu::Batch * DRW_cache_mesh_surface_viewer_attribute_get(Object *ob)
gpu::VertBuf ** DRW_pointcloud_evaluated_attribute(PointCloud *pointcloud, StringRef name)
gpu::VertBuf ** DRW_curves_texture_for_evaluated_attribute(Curves *curves, StringRef name, bool *r_is_point_domain)
gpu::Batch * DRW_cache_curve_edge_wire_get(Object *ob)
gpu::Batch * DRW_cache_mesh_surface_get(Object *ob)
VecBase< float, 4 > float4
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
Definition BLI_color.hh:342
const struct Curves * curve_eval
CurvesGeometry geometry
const blender::bke::GeometrySet * preview_base_geometry
int preview_instance_index
const GeometryComponent * get_component(GeometryComponent::Type component_type) const