Blender V4.3
overlay_next_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
9#pragma once
10
11#include "BKE_curves.hh"
12#include "BKE_geometry_set.hh"
13#include "DNA_curve_types.h"
15
16#include "draw_cache_impl.hh"
18
19namespace blender::draw::overlay {
21 private:
22 PassMain ps_ = {"attribute_viewer_ps_"};
23
24 PassMain::Sub *mesh_sub_ = nullptr;
25 PassMain::Sub *pointcloud_sub_ = nullptr;
26 PassMain::Sub *curve_sub_ = nullptr;
27 PassMain::Sub *curves_sub_ = nullptr;
28 PassMain::Sub *instance_sub_ = nullptr;
29
30 bool enabled_ = false;
31
32 public:
33 void begin_sync(Resources &res, const State &state)
34 {
35 ps_.init();
36 enabled_ = state.space_type == SPACE_VIEW3D && res.selection_type == SelectionType::DISABLED &&
37 (state.overlay.flag & V3D_OVERLAY_VIEWER_ATTRIBUTE);
38 if (!enabled_) {
39 return;
40 };
42 state.clipping_plane_count);
43
44 auto create_sub = [&](const char *name, GPUShader *shader) {
45 auto &sub = ps_.sub(name);
46 sub.shader_set(shader);
47 return ⊂
48 };
49
50 mesh_sub_ = create_sub("mesh", res.shaders.attribute_viewer_mesh.get());
51 pointcloud_sub_ = create_sub("pointcloud", res.shaders.attribute_viewer_pointcloud.get());
52 curve_sub_ = create_sub("curve", res.shaders.attribute_viewer_curve.get());
53 curves_sub_ = create_sub("curves", res.shaders.attribute_viewer_curves.get());
54 instance_sub_ = create_sub("instance", res.shaders.uniform_color.get());
55 }
56
57 void object_sync(const ObjectRef &ob_ref, const State &state, Manager &manager)
58 {
59 const DupliObject *dupli_object = DRW_object_get_dupli(ob_ref.object);
60 const bool is_preview = dupli_object != nullptr &&
61 dupli_object->preview_base_geometry != nullptr;
62 if (!enabled_ || !is_preview) {
63 return;
64 }
65
66 if (dupli_object->preview_instance_index >= 0) {
67 const auto &instances =
69 if (const std::optional<blender::bke::AttributeMetaData> meta_data =
70 instances.attributes()->lookup_meta_data(".viewer"))
71 {
72 if (attribute_type_supports_viewer_overlay(meta_data->data_type)) {
73 populate_for_instance(ob_ref, *dupli_object, state, manager);
74 return;
75 }
76 }
77 }
78 populate_for_geometry(ob_ref, state, manager);
79 }
80
81 void draw(Framebuffer &framebuffer, Manager &manager, View &view)
82 {
83 if (!enabled_) {
84 return;
85 }
86
87 GPU_framebuffer_bind(framebuffer);
88 manager.submit(ps_, view);
89 }
90
91 private:
92 void populate_for_instance(const ObjectRef &ob_ref,
93 const DupliObject &dupli_object,
94 const State &state,
95 Manager &manager)
96 {
97 Object &object = *ob_ref.object;
98 const bke::GeometrySet &base_geometry = *dupli_object.preview_base_geometry;
99 const bke::InstancesComponent &instances =
100 *base_geometry.get_component<bke::InstancesComponent>();
101 const bke::AttributeAccessor instance_attributes = *instances.attributes();
102 const VArray attribute = *instance_attributes.lookup<ColorGeometry4f>(".viewer");
103 if (!attribute) {
104 return;
105 }
106 ColorGeometry4f color = attribute.get(dupli_object.preview_instance_index);
107 color.a *= state.overlay.viewer_attribute_opacity;
108 switch (object.type) {
109 case OB_MESH: {
110 ResourceHandle res_handle = manager.unique_handle(ob_ref);
111
112 {
113 gpu::Batch *batch = DRW_cache_mesh_surface_get(&object);
114 auto &sub = *instance_sub_;
115 sub.push_constant("ucolor", color);
116 sub.draw(batch, res_handle);
117 }
118 if (gpu::Batch *batch = DRW_cache_mesh_loose_edges_get(&object)) {
119 auto &sub = *instance_sub_;
120 sub.push_constant("ucolor", color);
121 sub.draw(batch, res_handle);
122 }
123
124 break;
125 }
126 case OB_POINTCLOUD: {
127 auto &sub = *pointcloud_sub_;
128 gpu::Batch *batch = point_cloud_sub_pass_setup(sub, &object, nullptr);
129 sub.push_constant("ucolor", color);
130 sub.draw(batch, manager.unique_handle(ob_ref));
131 break;
132 }
133 case OB_CURVES_LEGACY: {
134 gpu::Batch *batch = DRW_cache_curve_edge_wire_get(&object);
135 auto &sub = *instance_sub_;
136 sub.push_constant("ucolor", color);
137 ResourceHandle res_handle = manager.resource_handle(object.object_to_world());
138 sub.draw(batch, res_handle);
139 break;
140 }
141 case OB_CURVES: {
142 /* Not supported yet because instances of this type are currently drawn as legacy curves.
143 */
144 break;
145 }
146 }
147 }
148
149 static bool attribute_type_supports_viewer_overlay(const eCustomDataType data_type)
150 {
151 return CD_TYPE_AS_MASK(data_type) &
153 }
154
155 void populate_for_geometry(const ObjectRef &ob_ref, const State &state, Manager &manager)
156 {
157 const float opacity = state.overlay.viewer_attribute_opacity;
158 Object &object = *ob_ref.object;
159 switch (object.type) {
160 case OB_MESH: {
161 Mesh *mesh = static_cast<Mesh *>(object.data);
162 if (const std::optional<bke::AttributeMetaData> meta_data =
163 mesh->attributes().lookup_meta_data(".viewer"))
164 {
165 if (attribute_type_supports_viewer_overlay(meta_data->data_type)) {
167 auto &sub = *mesh_sub_;
168 sub.push_constant("opacity", opacity);
169 sub.draw(batch, manager.unique_handle(ob_ref));
170 }
171 }
172 break;
173 }
174 case OB_POINTCLOUD: {
175 PointCloud *pointcloud = static_cast<PointCloud *>(object.data);
176 if (const std::optional<bke::AttributeMetaData> meta_data =
177 pointcloud->attributes().lookup_meta_data(".viewer"))
178 {
179 if (attribute_type_supports_viewer_overlay(meta_data->data_type)) {
180 gpu::VertBuf **vertbuf = DRW_pointcloud_evaluated_attribute(pointcloud, ".viewer");
181 auto &sub = *pointcloud_sub_;
182 gpu::Batch *batch = point_cloud_sub_pass_setup(sub, &object, nullptr);
183 sub.push_constant("opacity", opacity);
184 sub.bind_texture("attribute_tx", vertbuf);
185 sub.draw(batch, manager.unique_handle(ob_ref));
186 }
187 }
188 break;
189 }
190 case OB_CURVES_LEGACY: {
191 Curve *curve = static_cast<Curve *>(object.data);
192 if (curve->curve_eval) {
193 const bke::CurvesGeometry &curves = curve->curve_eval->geometry.wrap();
194 if (const std::optional<bke::AttributeMetaData> meta_data =
195 curves.attributes().lookup_meta_data(".viewer"))
196 {
197 if (attribute_type_supports_viewer_overlay(meta_data->data_type)) {
199 auto &sub = *curve_sub_;
200 sub.push_constant("opacity", opacity);
201 ResourceHandle res_handle = manager.resource_handle(object.object_to_world());
202 sub.draw(batch, res_handle);
203 }
204 }
205 }
206 break;
207 }
208 case OB_CURVES: {
209 ::Curves *curves_id = static_cast<::Curves *>(object.data);
210 const bke::CurvesGeometry &curves = curves_id->geometry.wrap();
211 if (const std::optional<bke::AttributeMetaData> meta_data =
212 curves.attributes().lookup_meta_data(".viewer"))
213 {
214 if (attribute_type_supports_viewer_overlay(meta_data->data_type)) {
215 bool is_point_domain;
216 gpu::VertBuf **texture = DRW_curves_texture_for_evaluated_attribute(
217 curves_id, ".viewer", &is_point_domain);
218 auto &sub = *curves_sub_;
219 gpu::Batch *batch = curves_sub_pass_setup(sub, state.scene, ob_ref.object);
220 sub.push_constant("opacity", opacity);
221 sub.push_constant("is_point_domain", is_point_domain);
222 sub.bind_texture("color_tx", *texture);
223 sub.draw(batch, manager.unique_handle(ob_ref));
224 }
225 }
226 break;
227 }
228 }
229 }
230};
231} // namespace blender::draw::overlay
Low-level operations for curves.
#define CD_TYPE_AS_MASK(_type)
#define CD_MASK_PROP_ALL
#define CD_MASK_PROP_QUATERNION
#define CD_MASK_PROP_FLOAT4X4
@ OB_MESH
@ OB_POINTCLOUD
@ OB_CURVES_LEGACY
@ OB_CURVES
@ SPACE_VIEW3D
@ V3D_OVERLAY_VIEWER_ATTRIBUTE
void GPU_framebuffer_bind(GPUFrameBuffer *framebuffer)
struct GPUShader GPUShader
AttributeSet attributes
ChannelStorageType a
Definition BLI_color.hh:88
ResourceHandle unique_handle(const ObjectRef &ref)
void submit(PassSimple &pass, View &view)
ResourceHandle resource_handle(const ObjectRef &ref, float inflate_bounds=0.0f)
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 push_constant(const char *name, const float &data)
void shader_set(GPUShader *shader)
Definition draw_pass.hh:971
void begin_sync(Resources &res, const State &state)
void object_sync(const ObjectRef &ob_ref, const State &state, Manager &manager)
void draw(Framebuffer &framebuffer, Manager &manager, View &view)
blender::gpu::Batch * DRW_cache_curve_edge_wire_viewer_attribute_get(Object *ob)
blender::gpu::Batch * DRW_cache_curve_edge_wire_get(Object *ob)
blender::gpu::Batch * DRW_cache_mesh_surface_get(Object *ob)
blender::gpu::Batch * DRW_cache_mesh_loose_edges_get(Object *ob)
blender::gpu::Batch * DRW_cache_mesh_surface_viewer_attribute_get(Object *ob)
DupliObject * DRW_object_get_dupli(const Object *)
@ 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 @620::@622 batch
static ulong state[N]
gpu::Batch * point_cloud_sub_pass_setup(PassMain::Sub &sub_ps, Object *object, GPUMaterial *gpu_material=nullptr)
gpu::Batch * curves_sub_pass_setup(PassMain::Sub &ps, const Scene *scene, Object *ob, GPUMaterial *gpu_material=nullptr)
gpu::VertBuf ** DRW_curves_texture_for_evaluated_attribute(Curves *curves, const char *name, bool *r_is_point_domain)
gpu::VertBuf ** DRW_pointcloud_evaluated_attribute(PointCloud *pointcloud, const char *name)
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