Blender V5.0
overlay_curve.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#pragma once
10
11#include "BKE_attribute.hh"
12
13#include "DNA_curves_types.h"
14
15#include "GPU_capabilities.hh"
16
17#include "draw_cache.hh"
18#include "draw_cache_impl.hh"
19
20#include "overlay_base.hh"
21
22namespace blender::draw::overlay {
23
27class Curves : Overlay {
28 private:
29 PassSimple edit_curves_ps_ = {"Curve Edit"};
30 PassSimple::Sub *edit_curves_lines_ = nullptr;
31
32 PassSimple edit_legacy_curve_handles_ps_ = {"Curve Edit Handles"};
33 PassSimple::Sub *edit_curves_points_ = nullptr;
34 PassSimple::Sub *edit_curves_handles_ = nullptr;
35
36 PassSimple edit_legacy_curve_ps_ = {"Legacy Curve Edit"};
37 PassSimple::Sub *edit_legacy_curve_wires_ = nullptr;
38 PassSimple::Sub *edit_legacy_curve_normals_ = nullptr;
39
40 PassSimple edit_curves_handles_ps_ = {"Legacy Curve Edit Handles"};
41 PassSimple::Sub *edit_legacy_curve_points_ = nullptr;
42 PassSimple::Sub *edit_legacy_curve_handles_ = nullptr;
43
44 PassSimple edit_legacy_surface_handles_ps = {"Surface Edit"};
45 PassSimple::Sub *edit_legacy_surface_handles_ = nullptr;
46 /* Handles that are below the geometry and are rendered with lower alpha. */
47 PassSimple::Sub *edit_legacy_surface_xray_handles_ = nullptr;
48
49 /* TODO(fclem): This is quite wasteful and expensive, prefer in shader Z modification like the
50 * retopology offset. */
51 View view_edit_cage = {"view_edit_cage"};
52 View::OffsetData offset_data_;
53
54 public:
55 void begin_sync(Resources &res, const State &state) final
56 {
57 enabled_ = state.is_space_v3d();
58
59 if (!enabled_) {
60 return;
61 }
62
63 offset_data_ = state.offset_data_get();
64
65 {
66 auto &pass = edit_curves_ps_;
67 pass.init();
68 pass.bind_ubo(OVERLAY_GLOBALS_SLOT, &res.globals_buf);
69 pass.bind_ubo(DRW_CLIPPING_UBO_SLOT, &res.clip_planes_buf);
70 {
71 auto &sub = pass.sub("Lines");
74 state.clipping_plane_count);
75 sub.shader_set(res.shaders->curve_edit_line.get());
76 sub.bind_texture("weight_tx", &res.weight_ramp_tx);
77 sub.push_constant("use_weight", false);
78 sub.push_constant("use_grease_pencil", false);
79 edit_curves_lines_ = ⊂
80 }
81 }
82
83 {
84 auto &pass = edit_curves_handles_ps_;
85 pass.init();
86 pass.bind_ubo(OVERLAY_GLOBALS_SLOT, &res.globals_buf);
87 pass.bind_ubo(DRW_CLIPPING_UBO_SLOT, &res.clip_planes_buf);
88 {
89 auto &sub = pass.sub("Handles");
90 sub.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA, state.clipping_plane_count);
91 sub.shader_set(res.shaders->curve_edit_handles.get());
92 sub.push_constant("curve_handle_display", int(state.overlay.handle_display));
93 edit_curves_handles_ = ⊂
94 }
95 {
96 auto &sub = pass.sub("Points");
99 state.clipping_plane_count);
100 sub.shader_set(res.shaders->curve_edit_points.get());
101 sub.bind_texture("weight_tx", &res.weight_ramp_tx);
102 sub.push_constant("use_weight", false);
103 sub.push_constant("use_grease_pencil", false);
104 sub.push_constant("do_stroke_endpoints", false);
105 sub.push_constant("curve_handle_display", int(state.overlay.handle_display));
106 edit_curves_points_ = ⊂
107 }
108 }
109
110 const bool show_normals = (state.overlay.edit_flag & V3D_OVERLAY_EDIT_CU_NORMALS);
111 const bool use_hq_normals = (state.scene->r.perf_flag & SCE_PERF_HQ_NORMALS) ||
113
114 {
115 auto &pass = edit_legacy_curve_ps_;
116 pass.init();
117 pass.bind_ubo(OVERLAY_GLOBALS_SLOT, &res.globals_buf);
118 pass.bind_ubo(DRW_CLIPPING_UBO_SLOT, &res.clip_planes_buf);
119 {
120 auto &sub = pass.sub("Wires");
122 state.clipping_plane_count);
123 sub.shader_set(res.shaders->legacy_curve_edit_wires.get());
124 sub.push_constant("normal_size", 0.0f);
125 edit_legacy_curve_wires_ = ⊂
126 }
127 if (show_normals) {
128 auto &sub = pass.sub("Normals");
130 state.clipping_plane_count);
131 sub.shader_set(res.shaders->legacy_curve_edit_normals.get());
132 sub.push_constant("normal_size", state.overlay.normals_length);
133 sub.push_constant("use_hq_normals", use_hq_normals);
134 edit_legacy_curve_normals_ = ⊂
135 }
136 else {
137 edit_legacy_curve_normals_ = nullptr;
138 }
139 }
140
141 {
142 auto &pass = edit_legacy_curve_handles_ps_;
143 pass.init();
144 pass.bind_ubo(OVERLAY_GLOBALS_SLOT, &res.globals_buf);
145 pass.bind_ubo(DRW_CLIPPING_UBO_SLOT, &res.clip_planes_buf);
146 {
147 auto &sub = pass.sub("Handles");
148 sub.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA, state.clipping_plane_count);
149 sub.shader_set(res.shaders->legacy_curve_edit_handles.get());
150 sub.push_constant("show_curve_handles", state.overlay.handle_display != CURVE_HANDLE_NONE);
151 sub.push_constant("curve_handle_display", int(state.overlay.handle_display));
152 sub.push_constant("alpha", 1.0f);
153 edit_legacy_curve_handles_ = ⊂
154 }
155 /* Points need to be rendered after handles. */
156 {
157 auto &sub = pass.sub("Points");
158 sub.state_set(DRW_STATE_WRITE_COLOR, state.clipping_plane_count);
159 sub.shader_set(res.shaders->legacy_curve_edit_points.get());
160 sub.push_constant("show_curve_handles", state.overlay.handle_display != CURVE_HANDLE_NONE);
161 sub.push_constant("curve_handle_display", int(state.overlay.handle_display));
162 sub.push_constant("use_grease_pencil", false);
163 sub.push_constant("do_stroke_endpoints", false);
164 edit_legacy_curve_points_ = ⊂
165 }
166 }
167
168 {
169 auto &pass = edit_legacy_surface_handles_ps;
170 pass.init();
171 pass.bind_ubo(OVERLAY_GLOBALS_SLOT, &res.globals_buf);
172 pass.bind_ubo(DRW_CLIPPING_UBO_SLOT, &res.clip_planes_buf);
173
174 auto create_sub = [&](const char *name, DRWState drw_state, float alpha) {
175 auto &sub = pass.sub(name);
176 sub.state_set(drw_state, state.clipping_plane_count);
177 sub.shader_set(res.shaders->legacy_curve_edit_handles.get());
178 sub.push_constant("show_curve_handles", state.overlay.handle_display != CURVE_HANDLE_NONE);
179 sub.push_constant("curve_handle_display", int(state.overlay.handle_display));
180 sub.push_constant("alpha", alpha);
181 return ⊂
182 };
183
186 edit_legacy_surface_xray_handles_ = create_sub("SurfaceXrayHandles", state_xray, 0.2f);
187
190 edit_legacy_surface_handles_ = create_sub("SurfaceHandles", state_front, 1.0f);
191 }
192 }
193
195 const ObjectRef &ob_ref,
196 Resources & /*res*/,
197 const State & /*state*/) final
198 {
199 if (!enabled_) {
200 return;
201 }
202
203 Object *ob = ob_ref.object;
205 const bool show_points = bke::AttrDomain(curves.selection_domain) == bke::AttrDomain::Point;
206
207 if (show_points) {
208 gpu::Batch *geom = DRW_curves_batch_cache_get_edit_points(&curves);
209 edit_curves_points_->draw(geom, manager.unique_handle(ob_ref));
210 }
211 {
212 gpu::Batch *geom = DRW_curves_batch_cache_get_edit_curves_handles(&curves);
213 edit_curves_handles_->draw_expand(geom, GPU_PRIM_TRIS, 8, 1, manager.unique_handle(ob_ref));
214 }
215 {
216 gpu::Batch *geom = DRW_curves_batch_cache_get_edit_curves_lines(&curves);
217 edit_curves_lines_->draw(geom, manager.unique_handle(ob_ref));
218 }
219 }
220
221 /* Used for legacy curves. */
222 void edit_object_sync_legacy(Manager &manager, const ObjectRef &ob_ref, Resources & /*res*/)
223 {
224 if (!enabled_) {
225 return;
226 }
227
228 ResourceHandleRange res_handle = manager.unique_handle(ob_ref);
229
230 Object *ob = ob_ref.object;
232
233 if (ob->type == OB_CURVES_LEGACY) {
234 gpu::Batch *geom = DRW_cache_curve_edge_wire_get(ob);
235 edit_legacy_curve_wires_->draw(geom, res_handle);
236 }
237 if (edit_legacy_curve_normals_ && (curve.flag & CU_3D)) {
238 gpu::Batch *geom = DRW_cache_curve_edge_normal_get(ob);
239 edit_legacy_curve_normals_->draw_expand(geom, GPU_PRIM_LINES, 2, 1, res_handle);
240 }
241 {
242 gpu::Batch *geom = DRW_cache_curve_edge_overlay_get(ob);
243 if (ob->type == OB_CURVES_LEGACY) {
244 edit_legacy_curve_handles_->draw_expand(geom, GPU_PRIM_TRIS, 8, 1, res_handle);
245 }
246 else {
247 edit_legacy_surface_xray_handles_->draw_expand(geom, GPU_PRIM_TRIS, 8, 1, res_handle);
248 edit_legacy_surface_handles_->draw_expand(geom, GPU_PRIM_TRIS, 8, 1, res_handle);
249 }
250 }
251 {
252 gpu::Batch *geom = DRW_cache_curve_vert_overlay_get(ob);
253 edit_legacy_curve_points_->draw(geom, res_handle);
254 }
255 }
256
257 void draw_line(Framebuffer &framebuffer, Manager &manager, View &view) final
258 {
259 if (!enabled_) {
260 return;
261 }
262
263 view_edit_cage.sync(view.viewmat(), offset_data_.winmat_polygon_offset(view.winmat(), 0.5f));
264
265 GPU_framebuffer_bind(framebuffer);
266 manager.submit(edit_legacy_curve_ps_, view);
267 manager.submit(edit_curves_ps_, view_edit_cage);
268 manager.submit(edit_legacy_surface_handles_ps, view);
269 }
270
271 void draw_color_only(Framebuffer &framebuffer, Manager &manager, View &view) final
272 {
273 if (!enabled_) {
274 return;
275 }
276
277 view_edit_cage.sync(view.viewmat(), offset_data_.winmat_polygon_offset(view.winmat(), 0.5f));
278
279 GPU_framebuffer_bind(framebuffer);
280 manager.submit(edit_legacy_curve_handles_ps_, view);
281 manager.submit(edit_curves_handles_ps_, view_edit_cage);
282 }
283};
284
285} // namespace blender::draw::overlay
@ CU_3D
@ OB_CURVES_LEGACY
@ SCE_PERF_HQ_NORMALS
@ V3D_OVERLAY_EDIT_CU_NORMALS
@ CURVE_HANDLE_NONE
T & DRW_object_get_data_for_drawing(const Object &object)
static AppView * view
bool GPU_use_hq_normals_workaround()
void GPU_framebuffer_bind(blender::gpu::FrameBuffer *fb)
@ GPU_PRIM_LINES
@ GPU_PRIM_TRIS
ResourceHandleRange unique_handle(const ObjectRef &ref)
detail::PassBase< command::DrawCommandBuf > Sub
Definition draw_pass.hh:499
void edit_object_sync_legacy(Manager &manager, const ObjectRef &ob_ref, Resources &)
void begin_sync(Resources &res, const State &state) final
void draw_line(Framebuffer &framebuffer, Manager &manager, View &view) final
void draw_color_only(Framebuffer &framebuffer, Manager &manager, View &view) final
void edit_object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &, const 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
@ DRW_STATE_DEPTH_GREATER
Definition draw_state.hh:40
static ulong state[N]
blender::gpu::Batch * DRW_curves_batch_cache_get_edit_points(Curves *curves)
detail::Pass< command::DrawCommandBuf > PassSimple
blender::gpu::Batch * DRW_curves_batch_cache_get_edit_curves_handles(Curves *curves)
gpu::Batch * DRW_cache_curve_edge_overlay_get(Object *ob)
gpu::Batch * DRW_cache_curve_edge_wire_get(Object *ob)
gpu::Batch * DRW_cache_curve_edge_normal_get(Object *ob)
blender::gpu::Batch * DRW_curves_batch_cache_get_edit_curves_lines(Curves *curves)
gpu::Batch * DRW_cache_curve_vert_overlay_get(Object *ob)
const char * name
char selection_domain