Blender V5.0
overlay_instance.cc
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#include "BKE_colorband.hh"
11
12#include "ED_view3d.hh"
13
14#include "BKE_paint.hh"
15
16#include "draw_debug.hh"
17#include "overlay_instance.hh"
18
19namespace blender::draw::overlay {
20
22{
23 /* TODO(fclem): Remove DRW global usage. */
24 const DRWContext *ctx = DRW_context_get();
25 /* Was needed by `object_wire_theme_id()` when doing the port. Not sure if needed nowadays. */
27
28 clipping_enabled_ = RV3D_CLIPPING_ENABLED(ctx->v3d, ctx->rv3d);
29
30 resources.init(clipping_enabled_);
31
32 state.depsgraph = ctx->depsgraph;
33 state.view_layer = ctx->view_layer;
34 state.space_data = ctx->space_data;
35 state.scene = ctx->scene;
36 state.v3d = ctx->v3d;
37 state.region = ctx->region;
38 state.rv3d = ctx->rv3d;
40 state.object_mode = ctx->object_mode;
41 state.cfra = DEG_get_ctime(state.depsgraph);
42 state.is_viewport_image_render = ctx->is_viewport_image_render();
43 state.is_image_render = ctx->is_image_render();
44 state.is_depth_only_drawing = ctx->is_depth();
45 state.skip_particles = ctx->mode == DRWContext::DEPTH_ACTIVE_OBJECT;
46 state.is_material_select = ctx->is_material_select();
47 state.draw_background = ctx->options.draw_background;
48 state.show_text = false;
49
50 /* Note there might be less than 6 planes, but we always compute the 6 of them for simplicity. */
51 state.clipping_plane_count = clipping_enabled_ ? 6 : 0;
52
53 state.ctx_mode = CTX_data_mode_enum_ex(ctx->object_edit, ctx->obact, ctx->object_mode);
54 state.space_data = ctx->space_data;
55 state.space_type = state.v3d != nullptr ? SPACE_VIEW3D : eSpace_Type(ctx->space_data->spacetype);
56 if (state.v3d != nullptr) {
57 state.clear_in_front = (state.v3d->shading.type != OB_SOLID);
58 /* TODO(pragma37): Check with @fclem if this was intentional. */
59 // state.use_in_front = (state.v3d->shading.type <= OB_SOLID) ||
60 // BKE_scene_uses_blender_workbench(state.scene);
61 state.use_in_front = true;
62 state.is_wireframe_mode = (state.v3d->shading.type == OB_WIRE);
63 state.hide_overlays = (state.v3d->flag2 & V3D_HIDE_OVERLAYS) != 0;
64 state.xray_enabled = XRAY_ACTIVE(state.v3d) && !state.is_depth_only_drawing;
65 state.xray_enabled_and_not_wire = state.xray_enabled && (state.v3d->shading.type > OB_WIRE);
66 state.xray_opacity = state.xray_enabled ? XRAY_ALPHA(state.v3d) : 1.0f;
67 state.xray_flag_enabled = SHADING_XRAY_FLAG_ENABLED(state.v3d->shading) &&
68 !state.is_depth_only_drawing;
69 state.vignette_enabled = ctx->mode == DRWContext::VIEWPORT_XR &&
70 state.v3d->vignette_aperture < M_SQRT1_2;
71
72 const bool viewport_uses_workbench = state.v3d->shading.type <= OB_SOLID ||
74 const bool viewport_uses_eevee = STREQ(
75 ED_view3d_engine_type(state.scene, state.v3d->shading.type)->idname,
77 const bool use_resolution_scaling = BKE_render_preview_pixel_size(&state.scene->r) != 1;
78 /* Only workbench ensures the depth buffer is matching overlays.
79 * Force depth prepass for other render engines.
80 * EEVEE is an exception (if not using mixed resolution) to avoid a significant overhead. */
81 state.is_render_depth_available = viewport_uses_workbench ||
82 (viewport_uses_eevee && !use_resolution_scaling);
83
84 /* For depth only drawing, no other render engine is expected. Except for Grease Pencil which
85 * outputs valid depth. Otherwise depth is cleared and is valid. */
86 state.is_render_depth_available |= state.is_depth_only_drawing;
87
88 if (!state.hide_overlays) {
89 state.overlay = state.v3d->overlay;
90 state.v3d_flag = state.v3d->flag;
91 state.v3d_gridflag = state.v3d->gridflag;
92 state.show_text = !resources.is_selection() && !state.is_depth_only_drawing &&
94 }
95 else {
96 memset(&state.overlay, 0, sizeof(state.overlay));
97 state.v3d_flag = 0;
98 state.v3d_gridflag = 0;
102 state.overlay.wireframe_threshold = state.v3d->overlay.wireframe_threshold;
103 state.overlay.wireframe_opacity = state.v3d->overlay.wireframe_opacity;
104 }
105
106 state.do_pose_xray = state.show_bone_selection();
107 state.do_pose_fade_geom = state.do_pose_xray && !(state.object_mode & OB_MODE_WEIGHT_PAINT) &&
108 ctx->object_pose != nullptr;
109 }
110 else if (state.is_space_image()) {
111 SpaceImage *space_image = (SpaceImage *)state.space_data;
112
113 state.clear_in_front = false;
114 state.use_in_front = false;
115 state.is_wireframe_mode = false;
116 state.hide_overlays = (space_image->overlay.flag & SI_OVERLAY_SHOW_OVERLAYS) == 0;
117 state.xray_enabled = false;
118 /* Avoid triggering the depth prepass. */
119 state.is_render_depth_available = true;
120
121 /* During engine initialization phase the `space_image` isn't locked and we are able to
122 * retrieve the needed data. During cache_init the image engine locks the `space_image` and
123 * makes it impossible to retrieve the data. */
124 state.is_image_valid = bool(space_image->image);
125 ED_space_image_get_uv_aspect(space_image, &state.image_uv_aspect.x, &state.image_uv_aspect.y);
126 ED_space_image_get_size(space_image, &state.image_size.x, &state.image_size.y);
127 ED_space_image_get_aspect(space_image, &state.image_aspect.x, &state.image_aspect.y);
128 }
129
130 resources.update_theme_settings(ctx, state);
131 resources.update_clip_planes(state);
132
133 ensure_weight_ramp_texture();
134
135 {
137 if (resources.dummy_depth_tx.ensure_2d(gpu::TextureFormat::SFLOAT_32_DEPTH, int2(1, 1), usage))
138 {
139 float data = 1.0f;
140 GPU_texture_update_sub(resources.dummy_depth_tx, GPU_DATA_FLOAT, &data, 0, 0, 0, 1, 1, 1);
141 }
142 }
143}
144
145void Instance::ensure_weight_ramp_texture()
146{
147 /* Weight Painting color ramp texture */
148 bool user_weight_ramp = (U.flag & USER_CUSTOM_RANGE) != 0;
149
150 auto is_equal = [](const ColorBand &a, const ColorBand &b) {
151 if (a.tot != b.tot || a.cur != b.cur || a.ipotype != b.ipotype ||
152 a.ipotype_hue != b.ipotype_hue || a.color_mode != b.color_mode)
153 {
154 return false;
155 }
156
157 auto is_equal_cbd = [](const CBData &a, const CBData &b) {
158 return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a && a.pos == b.pos &&
159 a.cur == b.cur;
160 };
161
162 for (int i = 0; i < ARRAY_SIZE(a.data); i++) {
163 if (!is_equal_cbd(a.data[i], b.data[i])) {
164 return false;
165 }
166 }
167 return true;
168 };
169
170 if (assign_if_different(resources.weight_ramp_custom, user_weight_ramp)) {
171 resources.weight_ramp_tx.free();
172 }
173
174 if (user_weight_ramp && !is_equal(resources.weight_ramp_copy, U.coba_weight)) {
175 resources.weight_ramp_copy = U.coba_weight;
176 resources.weight_ramp_tx.free();
177 }
178
179 if (resources.weight_ramp_tx.is_valid()) {
180 /* Only recreate on updates. */
181 return;
182 }
183
184 auto evaluate_weight_to_color = [&](const float weight, float result[4]) {
185 if (user_weight_ramp) {
186 BKE_colorband_evaluate(&U.coba_weight, weight, result);
187 }
188 else {
189 /* Use gamma correction to even out the color bands:
190 * increasing widens yellow/cyan vs red/green/blue.
191 * Gamma 1.0 produces the original 2.79 color ramp. */
192 const float gamma = 1.5f;
193 const float hsv[3] = {
194 (2.0f / 3.0f) * (1.0f - weight), 1.0f, pow(0.5f + 0.5f * weight, gamma)};
195
196 hsv_to_rgb_v(hsv, result);
197
198 for (int i = 0; i < 3; i++) {
199 result[i] = pow(result[i], 1.0f / gamma);
200 }
201 }
202 };
203
204 constexpr int res = 256;
205
206 float pixels[res][4];
207 for (int i = 0; i < res; i++) {
208 evaluate_weight_to_color(i / 255.0f, pixels[i]);
209 pixels[i][3] = 1.0f;
210 }
211
212 uchar4 pixels_ubyte[res];
213 for (int i = 0; i < res; i++) {
214 unit_float_to_uchar_clamp_v4(pixels_ubyte[i], pixels[i]);
215 }
216
217 resources.weight_ramp_tx.ensure_1d(
218 gpu::TextureFormat::SRGBA_8_8_8_8, res, GPU_TEXTURE_USAGE_SHADER_READ);
219 GPU_texture_update(resources.weight_ramp_tx, GPU_DATA_UBYTE, pixels_ubyte);
220}
221
223{
224 if (!state.is_space_v3d() || state.clipping_plane_count == 0) {
225 /* Unused, do not care about content but still fulfill the bindings. */
226 clip_planes_buf.push_update();
227 return;
228 }
229
230 for (int i : IndexRange(6)) {
232 }
233
234 int plane_len = (RV3D_LOCK_FLAGS(state.rv3d) & RV3D_BOXCLIP) ? 4 : 6;
235 for (int i : IndexRange(plane_len)) {
236 clip_planes_buf[i] = float4(state.rv3d->clip[i]);
237 }
238
239 clip_planes_buf.push_update();
240}
241
243{
244 using namespace math;
245 UniformData &gb = theme;
246
247 auto rgba_uchar_to_float = [](uchar r, uchar g, uchar b, uchar a) {
248 return float4(r, g, b, a) / 255.0f;
249 };
250
251 UI_GetThemeColor4fv(TH_WIRE, gb.colors.wire);
252 UI_GetThemeColor4fv(TH_WIRE_EDIT, gb.colors.wire_edit);
253 UI_GetThemeColor4fv(TH_ACTIVE, gb.colors.active_object);
254 UI_GetThemeColor4fv(TH_SELECT, gb.colors.object_select);
255 gb.colors.library_select = rgba_uchar_to_float(0x88, 0xFF, 0xFF, 155);
256 gb.colors.library = rgba_uchar_to_float(0x55, 0xCC, 0xCC, 155);
257 UI_GetThemeColor4fv(TH_TRANSFORM, gb.colors.transform);
258 UI_GetThemeColor4fv(TH_LIGHT, gb.colors.light);
259 UI_GetThemeColor4fv(TH_SPEAKER, gb.colors.speaker);
261 UI_GetThemeColor4fv(TH_CAMERA_PATH, gb.colors.camera_path);
262 UI_GetThemeColor4fv(TH_EMPTY, gb.colors.empty);
263 UI_GetThemeColor4fv(TH_VERTEX, gb.colors.vert);
264 UI_GetThemeColor4fv(TH_VERTEX_SELECT, gb.colors.vert_select);
265 UI_GetThemeColor4fv(TH_VERTEX_UNREFERENCED, gb.colors.vert_unreferenced);
266 gb.colors.vert_missing_data = rgba_uchar_to_float(0xB0, 0x00, 0xB0, 0xFF);
267 UI_GetThemeColor4fv(TH_EDITMESH_ACTIVE, gb.colors.edit_mesh_active);
268 UI_GetThemeColor4fv(TH_EDGE_SELECT, gb.colors.edge_select);
269 UI_GetThemeColor4fv(TH_EDGE_MODE_SELECT, gb.colors.edge_mode_select);
270 UI_GetThemeColor4fv(TH_GP_VERTEX, gb.colors.gpencil_vertex);
271 UI_GetThemeColor4fv(TH_GP_VERTEX_SELECT, gb.colors.gpencil_vertex_select);
272
273 UI_GetThemeColor4fv(TH_SEAM, gb.colors.edge_seam);
274 UI_GetThemeColor4fv(TH_SHARP, gb.colors.edge_sharp);
275 UI_GetThemeColor4fv(TH_CREASE, gb.colors.edge_crease);
276 UI_GetThemeColor4fv(TH_BEVEL, gb.colors.edge_bweight);
277 UI_GetThemeColor4fv(TH_FACE, gb.colors.face);
278 UI_GetThemeColor4fv(TH_FACE_SELECT, gb.colors.face_select);
279 UI_GetThemeColor4fv(TH_FACE_MODE_SELECT, gb.colors.face_mode_select);
280 UI_GetThemeColor4fv(TH_FACE_RETOPOLOGY, gb.colors.face_retopology);
281 UI_GetThemeColor4fv(TH_FACE_BACK, gb.colors.face_back);
282 UI_GetThemeColor4fv(TH_FACE_FRONT, gb.colors.face_front);
283 UI_GetThemeColor4fv(TH_NORMAL, gb.colors.normal);
284 UI_GetThemeColor4fv(TH_VNORMAL, gb.colors.vnormal);
285 UI_GetThemeColor4fv(TH_LNORMAL, gb.colors.lnormal);
286 UI_GetThemeColor4fv(TH_FACE_SELECT, gb.colors.facedot), gb.colors.facedot[3] = 1.0f;
287 UI_GetThemeColor4fv(TH_SKIN_ROOT, gb.colors.skinroot);
288 UI_GetThemeColor4fv(TH_BACK, gb.colors.background);
289 UI_GetThemeColor4fv(TH_BACK_GRAD, gb.colors.background_gradient);
290 UI_GetThemeColor4fv(TH_TRANSPARENT_CHECKER_PRIMARY, gb.colors.checker_primary);
291 UI_GetThemeColor4fv(TH_TRANSPARENT_CHECKER_SECONDARY, gb.colors.checker_secondary);
293 gb.fresnel_mix_edit = ((U.gpu_flag & USER_GPU_FLAG_FRESNEL_EDIT) == 0) ? 0.0f : 1.0f;
294 UI_GetThemeColor4fv(TH_V3D_CLIPPING_BORDER, gb.colors.clipping_border);
295
296 /* Custom median color to slightly affect the edit mesh colors. */
297 gb.colors.edit_mesh_middle = interpolate(gb.colors.vert_select, gb.colors.wire_edit, 0.35f);
298 /* Desaturate. */
299 gb.colors.edit_mesh_middle = float4(
300 float3(dot(gb.colors.edit_mesh_middle.xyz(), float3(0.3333f))),
301 gb.colors.edit_mesh_middle.w);
302
303#ifdef WITH_FREESTYLE
304 UI_GetThemeColor4fv(TH_FREESTYLE, gb.colors.edge_freestyle), gb.colors.edge_freestyle[3] = 1.0f;
305 UI_GetThemeColor4fv(TH_FREESTYLE, gb.colors.face_freestyle);
306#else
307 gb.colors.edge_freestyle = float4(0.0f);
308 gb.colors.face_freestyle = float4(0.0f);
309#endif
310
311 UI_GetThemeColor4fv(TH_TEXT, gb.colors.text);
312 UI_GetThemeColor4fv(TH_TEXT_HI, gb.colors.text_hi);
313
314 /* Bone colors */
315 UI_GetThemeColor4fv(TH_BONE_POSE, gb.colors.bone_pose);
316 UI_GetThemeColor4fv(TH_BONE_POSE_ACTIVE, gb.colors.bone_pose_active);
317 UI_GetThemeColorShade4fv(TH_EDGE_SELECT, 60, gb.colors.bone_active);
318 UI_GetThemeColorShade4fv(TH_EDGE_SELECT, -20, gb.colors.bone_select);
319 UI_GetThemeColorBlendShade4fv(TH_WIRE, TH_BONE_POSE, 0.15f, 0, gb.colors.bone_pose_active_unsel);
321 TH_WIRE_EDIT, TH_EDGE_SELECT, 0.15f, 0, gb.colors.bone_active_unsel);
322 gb.colors.bone_pose_no_target = rgba_uchar_to_float(255, 150, 0, 80);
323 gb.colors.bone_pose_ik = rgba_uchar_to_float(255, 255, 0, 80);
324 gb.colors.bone_pose_spline_ik = rgba_uchar_to_float(200, 255, 0, 80);
325 gb.colors.bone_pose_constraint = rgba_uchar_to_float(0, 255, 120, 80);
326 UI_GetThemeColor4fv(TH_BONE_SOLID, gb.colors.bone_solid);
327 UI_GetThemeColor4fv(TH_BONE_LOCKED_WEIGHT, gb.colors.bone_locked);
328 gb.colors.bone_ik_line = float4(0.8f, 0.8f, 0.0f, 1.0f);
329 gb.colors.bone_ik_line_no_target = float4(0.8f, 0.5f, 0.2f, 1.0f);
330 gb.colors.bone_ik_line_spline = float4(0.8f, 0.8f, 0.2f, 1.0f);
331
332 /* Curve */
333 UI_GetThemeColor4fv(TH_HANDLE_FREE, gb.colors.handle_free);
334 UI_GetThemeColor4fv(TH_HANDLE_AUTO, gb.colors.handle_auto);
335 UI_GetThemeColor4fv(TH_HANDLE_VECT, gb.colors.handle_vect);
336 UI_GetThemeColor4fv(TH_HANDLE_ALIGN, gb.colors.handle_align);
337 UI_GetThemeColor4fv(TH_HANDLE_AUTOCLAMP, gb.colors.handle_autoclamp);
338 UI_GetThemeColor4fv(TH_HANDLE_SEL_FREE, gb.colors.handle_sel_free);
339 UI_GetThemeColor4fv(TH_HANDLE_SEL_AUTO, gb.colors.handle_sel_auto);
340 UI_GetThemeColor4fv(TH_HANDLE_SEL_VECT, gb.colors.handle_sel_vect);
341 UI_GetThemeColor4fv(TH_HANDLE_SEL_ALIGN, gb.colors.handle_sel_align);
342 UI_GetThemeColor4fv(TH_HANDLE_SEL_AUTOCLAMP, gb.colors.handle_sel_autoclamp);
343 UI_GetThemeColor4fv(TH_NURB_ULINE, gb.colors.nurb_uline);
344 UI_GetThemeColor4fv(TH_NURB_VLINE, gb.colors.nurb_vline);
345 UI_GetThemeColor4fv(TH_NURB_SEL_ULINE, gb.colors.nurb_sel_uline);
346 UI_GetThemeColor4fv(TH_NURB_SEL_VLINE, gb.colors.nurb_sel_vline);
347
348 UI_GetThemeColor4fv(TH_CFRAME, gb.colors.current_frame);
349 UI_GetThemeColor4fv(TH_FRAME_BEFORE, gb.colors.before_frame);
350 UI_GetThemeColor4fv(TH_FRAME_AFTER, gb.colors.after_frame);
351
352 /* Meta-ball. */
353 gb.colors.mball_radius = rgba_uchar_to_float(0xA0, 0x30, 0x30, 0xFF);
354 gb.colors.mball_radius_select = rgba_uchar_to_float(0xF0, 0xA0, 0xA0, 0xFF);
355 gb.colors.mball_stiffness = rgba_uchar_to_float(0x30, 0xA0, 0x30, 0xFF);
356 gb.colors.mball_stiffness_select = rgba_uchar_to_float(0xA0, 0xF0, 0xA0, 0xFF);
357
358 /* Grid */
359 UI_GetThemeColorShade4fv(TH_GRID, 10, gb.colors.grid);
360 /* Emphasize division lines lighter instead of darker, if background is darker than grid. */
361 const bool is_bg_darker = reduce_add(gb.colors.grid.xyz()) + 0.12f >
362 reduce_add(gb.colors.background.xyz());
363 UI_GetThemeColorShade4fv(TH_GRID, (is_bg_darker) ? 20 : -10, gb.colors.grid_emphasis);
364 /* Grid Axis */
365 UI_GetThemeColorBlendShade4fv(TH_GRID, TH_AXIS_X, 0.5f, -10, gb.colors.grid_axis_x);
366 UI_GetThemeColorBlendShade4fv(TH_GRID, TH_AXIS_Y, 0.5f, -10, gb.colors.grid_axis_y);
367 UI_GetThemeColorBlendShade4fv(TH_GRID, TH_AXIS_Z, 0.5f, -10, gb.colors.grid_axis_z);
368
369 UI_GetThemeColorShadeAlpha4fv(TH_TRANSFORM, 0, -80, gb.colors.deselect);
370 UI_GetThemeColorShadeAlpha4fv(TH_WIRE, 0, -30, gb.colors.outline);
371 UI_GetThemeColorShadeAlpha4fv(TH_LIGHT, 0, 255, gb.colors.light_no_alpha);
372
373 /* UV colors */
374 UI_GetThemeColor4fv(TH_UV_SHADOW, gb.colors.uv_shadow);
375
376 /* Color management. */
377 {
378 float4 *color = reinterpret_cast<float4 *>(&gb.colors);
379 float4 *color_end = color + (sizeof(gb.colors) / sizeof(float4));
380 do {
381 /* TODO: more accurate transform. */
383 } while (++color <= color_end);
384 }
385
386 gb.sizes.pixel = 1.0f;
387 gb.sizes.object_center = UI_GetThemeValuef(TH_OBCENTER_DIA) + 1.0f;
388 gb.sizes.light_center = UI_GetThemeValuef(TH_OBCENTER_DIA) + 1.5f;
389 gb.sizes.light_circle = 9.0f;
390 gb.sizes.light_circle_shadow = (gb.sizes.light_circle + 3.0f);
391
392 /* M_SQRT2 to be at least the same size of the old square */
393 gb.sizes.vert = vertex_size_get();
394 gb.sizes.vertex_gpencil = UI_GetThemeValuef(TH_GP_VERTEX_SIZE);
395 gb.sizes.face_dot = UI_GetThemeValuef(TH_FACEDOT_SIZE);
396 gb.sizes.edge = max_ff(1.0f, UI_GetThemeValuef(TH_EDGE_WIDTH)) / 2.0f;
397
398 /* Pixel size. */
399 {
400 float *size = reinterpret_cast<float *>(&gb.sizes);
401 float *size_end = size + (sizeof(gb.sizes) / sizeof(float));
402 do {
403 *size *= U.pixelsize;
404 } while (++size <= size_end);
405 }
406
407 gb.pixel_fac = (state.rv3d) ? state.rv3d->pixsize : 1.0f;
408 gb.size_viewport = ctx->viewport_size_get();
409 gb.size_viewport_inv = 1.0f / gb.size_viewport;
410
411 if (state.v3d) {
412 const View3DShading &shading = state.v3d->shading;
413 gb.backface_culling = (shading.type == OB_SOLID) &&
415
416 if (is_selection() || state.is_depth_only_drawing) {
417 /* This is bad as this makes a solid mode setting affect material preview / render mode
418 * selection and auto-depth. But users are relying on this to work in scene using backface
419 * culling in shading (see #136335 and #136418). */
420 gb.backface_culling = (shading.flag & V3D_SHADING_BACKFACE_CULLING);
421 }
422 }
423 else {
424 gb.backface_culling = false;
425 }
426
427 globals_buf.push_update();
428}
429
431{
432 /* TODO(fclem): Against design. Should not sync depending on view. */
434 state.camera_position = view.viewinv().location();
435 state.camera_forward = view.viewinv().z_axis();
436
439
440 resources.begin_sync(state.clipping_plane_count);
441
442 background.begin_sync(resources, state);
443 cursor.begin_sync(resources, state);
444 image_prepass.begin_sync(resources, state);
445 motion_paths.begin_sync(resources, state);
446 origins.begin_sync(resources, state);
447 outline.begin_sync(resources, state);
448
449 auto begin_sync_layer = [&](OverlayLayer &layer) {
450 layer.armatures.begin_sync(resources, state);
451 layer.attribute_viewer.begin_sync(resources, state);
452 layer.attribute_texts.begin_sync(resources, state);
453 layer.axes.begin_sync(resources, state);
454 layer.bounds.begin_sync(resources, state);
455 layer.cameras.begin_sync(resources, state);
456 layer.curves.begin_sync(resources, state);
457 layer.text.begin_sync(resources, state);
458 layer.empties.begin_sync(resources, state);
459 layer.facing.begin_sync(resources, state);
460 layer.fade.begin_sync(resources, state);
461 layer.force_fields.begin_sync(resources, state);
462 layer.fluids.begin_sync(resources, state);
463 layer.grease_pencil.begin_sync(resources, state);
464 layer.lattices.begin_sync(resources, state);
465 layer.lights.begin_sync(resources, state);
466 layer.light_probes.begin_sync(resources, state);
467 layer.metaballs.begin_sync(resources, state);
468 layer.meshes.begin_sync(resources, state);
469 layer.mesh_uvs.begin_sync(resources, state);
470 layer.mode_transfer.begin_sync(resources, state);
471 layer.names.begin_sync(resources, state);
472 layer.paints.begin_sync(resources, state);
473 layer.particles.begin_sync(resources, state);
474 layer.pointclouds.begin_sync(resources, state);
475 layer.prepass.begin_sync(resources, state);
476 layer.relations.begin_sync(resources, state);
477 layer.speakers.begin_sync(resources, state);
478 layer.sculpts.begin_sync(resources, state);
479 layer.wireframe.begin_sync(resources, state);
480 };
481 begin_sync_layer(regular);
482 begin_sync_layer(infront);
483
484 grid.begin_sync(resources, state);
485
486 anti_aliasing.begin_sync(resources, state);
487 xray_fade.begin_sync(resources, state);
488}
489
491{
492 const bool in_object_mode = ob_ref.object->mode == OB_MODE_OBJECT;
493 const bool in_edit_mode = ob_ref.object->mode == OB_MODE_EDIT;
494 const bool in_paint_mode = object_is_paint_mode(ob_ref.object);
495 const bool in_sculpt_mode = object_is_sculpt_mode(ob_ref);
496 const bool in_particle_edit_mode = object_is_particle_edit_mode(ob_ref);
497 const bool in_edit_paint_mode = object_is_edit_paint_mode(
498 ob_ref, in_edit_mode, in_paint_mode, in_sculpt_mode);
499 const bool needs_prepass = object_needs_prepass(ob_ref, in_paint_mode);
500
501 OverlayLayer &layer = object_is_in_front(ob_ref.object, state) ? infront : regular;
502
503 layer.mode_transfer.object_sync(manager, ob_ref, resources, state);
504
505 if (needs_prepass) {
506 layer.prepass.object_sync(manager, ob_ref, resources, state);
507 }
508
509 if (in_particle_edit_mode) {
510 layer.particles.edit_object_sync(manager, ob_ref, resources, state);
511 }
512
513 /* For 2D UV overlays. */
514 if (!state.hide_overlays && state.is_space_image()) {
515 switch (ob_ref.object->type) {
516 case OB_MESH:
517 if (in_edit_paint_mode) {
518 /* TODO(fclem): Find a better place / condition. */
519 layer.mesh_uvs.edit_object_sync(manager, ob_ref, resources, state);
520 }
521 else if (in_object_mode) {
522 layer.mesh_uvs.object_sync(manager, ob_ref, resources, state);
523 }
524 default:
525 break;
526 }
527 }
528
529 if (in_paint_mode && !state.hide_overlays) {
530 switch (ob_ref.object->type) {
531 case OB_MESH:
532 /* TODO(fclem): Make it part of a #Meshes. */
533 layer.paints.object_sync(manager, ob_ref, resources, state);
534 break;
535 case OB_GREASE_PENCIL:
536 layer.grease_pencil.paint_object_sync(manager, ob_ref, resources, state);
537 break;
538 default:
539 break;
540 }
541 }
542
543 if (in_sculpt_mode) {
544 switch (ob_ref.object->type) {
545 case OB_MESH:
546 case OB_CURVES:
547 /* TODO(fclem): Make it part of a #Meshes. */
548 layer.sculpts.object_sync(manager, ob_ref, resources, state);
549 break;
550 case OB_GREASE_PENCIL:
551 layer.grease_pencil.sculpt_object_sync(manager, ob_ref, resources, state);
552 break;
553 default:
554 break;
555 }
556 }
557
558 if (in_edit_mode && !state.hide_overlays) {
559 switch (ob_ref.object->type) {
560 case OB_MESH:
561 layer.meshes.edit_object_sync(manager, ob_ref, resources, state);
562 break;
563 case OB_ARMATURE:
564 layer.armatures.edit_object_sync(manager, ob_ref, resources, state);
565 break;
566 case OB_SURF:
567 case OB_CURVES_LEGACY:
568 layer.curves.edit_object_sync_legacy(manager, ob_ref, resources);
569 break;
570 case OB_CURVES:
571 layer.curves.edit_object_sync(manager, ob_ref, resources, state);
572 break;
573 case OB_LATTICE:
574 layer.lattices.edit_object_sync(manager, ob_ref, resources, state);
575 break;
576 case OB_MBALL:
577 layer.metaballs.edit_object_sync(manager, ob_ref, resources, state);
578 break;
579 case OB_POINTCLOUD:
580 layer.pointclouds.edit_object_sync(manager, ob_ref, resources, state);
581 break;
582 case OB_FONT:
583 layer.text.edit_object_sync(manager, ob_ref, resources, state);
584 break;
585 case OB_GREASE_PENCIL:
586 layer.grease_pencil.edit_object_sync(manager, ob_ref, resources, state);
587 break;
588 }
589 }
590
591 if (state.is_wireframe_mode || !state.hide_overlays) {
593 manager, ob_ref, resources, state, in_edit_paint_mode, in_edit_mode);
594 }
595
596 if (!state.hide_overlays) {
597 switch (ob_ref.object->type) {
598 case OB_EMPTY:
599 layer.empties.object_sync(manager, ob_ref, resources, state);
600 break;
601 case OB_CAMERA:
602 layer.cameras.object_sync(manager, ob_ref, resources, state);
603 break;
604 case OB_ARMATURE:
605 if (!in_edit_mode) {
606 layer.armatures.object_sync(manager, ob_ref, resources, state);
607 }
608 break;
609 case OB_LATTICE:
610 if (!in_edit_mode) {
611 layer.lattices.object_sync(manager, ob_ref, resources, state);
612 }
613 break;
614 case OB_LAMP:
615 layer.lights.object_sync(manager, ob_ref, resources, state);
616 break;
617 case OB_LIGHTPROBE:
618 layer.light_probes.object_sync(manager, ob_ref, resources, state);
619 break;
620 case OB_MBALL:
621 if (!in_edit_mode) {
622 layer.metaballs.object_sync(manager, ob_ref, resources, state);
623 }
624 break;
625 case OB_GREASE_PENCIL:
626 layer.grease_pencil.object_sync(manager, ob_ref, resources, state);
627 break;
628 case OB_SPEAKER:
629 layer.speakers.object_sync(manager, ob_ref, resources, state);
630 break;
631 }
632 layer.attribute_viewer.object_sync(manager, ob_ref, resources, state);
633 layer.attribute_texts.object_sync(manager, ob_ref, resources, state);
634 layer.bounds.object_sync(manager, ob_ref, resources, state);
635 layer.facing.object_sync(manager, ob_ref, resources, state);
636 layer.fade.object_sync(manager, ob_ref, resources, state);
637 layer.force_fields.object_sync(manager, ob_ref, resources, state);
638 layer.fluids.object_sync(manager, ob_ref, resources, state);
639 layer.particles.object_sync(manager, ob_ref, resources, state);
640 layer.relations.object_sync(manager, ob_ref, resources, state);
641 layer.axes.object_sync(manager, ob_ref, resources, state);
642 layer.names.object_sync(manager, ob_ref, resources, state);
643
644 motion_paths.object_sync(manager, ob_ref, resources, state);
645 origins.object_sync(manager, ob_ref, resources, state);
646
647 if (object_is_selected(ob_ref) && !in_edit_paint_mode) {
648 outline.object_sync(manager, ob_ref, resources, state);
649 }
650 }
651}
652
654{
655 origins.end_sync(resources, state);
656 resources.end_sync();
657
658 auto end_sync_layer = [&](OverlayLayer &layer) {
659 layer.armatures.end_sync(resources, state);
660 layer.axes.end_sync(resources, state);
661 layer.bounds.end_sync(resources, state);
662 layer.cameras.end_sync(resources, state);
663 layer.text.end_sync(resources, state);
664 layer.empties.end_sync(resources, state);
665 layer.force_fields.end_sync(resources, state);
666 layer.lights.end_sync(resources, state);
667 layer.light_probes.end_sync(resources, state);
668 layer.mesh_uvs.end_sync(resources, state);
669 layer.metaballs.end_sync(resources, state);
670 layer.relations.end_sync(resources, state);
671 layer.fluids.end_sync(resources, state);
672 layer.speakers.end_sync(resources, state);
673 };
674 end_sync_layer(regular);
675 end_sync_layer(infront);
676
677 /* WORKAROUND: This prevents bad frame-buffer config inside workbench when xray is enabled.
678 * Better find a solution to this chicken-egg problem. */
679 {
680 const DRWContext *draw_ctx = DRW_context_get();
681 /* HACK we allocate the in front depth here to avoid the overhead when if is not needed. */
684
685 if (dtxl->depth_in_front == nullptr) {
686 int2 size = int2(draw_ctx->viewport_size_get());
687
688 dtxl->depth_in_front = GPU_texture_create_2d("txl.depth_in_front",
689 size.x,
690 size.y,
691 1,
692 gpu::TextureFormat::SFLOAT_32_DEPTH_UINT_8,
694 nullptr);
695 }
696
698 &dfbl->in_front_fb,
699 {GPU_ATTACHMENT_TEXTURE(dtxl->depth_in_front), GPU_ATTACHMENT_TEXTURE(dtxl->color)});
700 }
701}
702
704{
705 /* TODO(fclem): Remove global access. */
707
708 static gpu::DebugScope select_scope = {"Selection"};
709 static gpu::DebugScope draw_scope = {"Overlay"};
710 static gpu::DebugScope depth_scope = {"DepthOnly"};
711
712 if (state.is_depth_only_drawing) {
713 depth_scope.begin_capture();
714 }
715 else if (resources.is_selection()) {
716 select_scope.begin_capture();
717 }
718 else {
719 draw_scope.begin_capture();
720 }
721
722 /* TODO(fclem): To be moved to overlay UBO. */
723 state.ndc_offset_factor = state.offset_data_get().polygon_offset_factor(view.winmat());
724
725 resources.pre_draw();
726
727 outline.flat_objects_pass_sync(manager, view, resources, state);
728 GreasePencil::compute_depth_planes(manager, view, resources, state);
729
730 /* Pre-Draw: Run the compute steps of all passes up-front
731 * to avoid constant GPU compute/raster context switching. */
732 {
733 manager.ensure_visibility(view);
734
735 auto pre_draw = [&](OverlayLayer &layer) {
736 layer.attribute_viewer.pre_draw(manager, view);
737 layer.cameras.pre_draw(manager, view);
738 layer.empties.pre_draw(manager, view);
739 layer.facing.pre_draw(manager, view);
740 layer.fade.pre_draw(manager, view);
741 layer.lattices.pre_draw(manager, view);
742 layer.light_probes.pre_draw(manager, view);
743 layer.particles.pre_draw(manager, view);
744 layer.pointclouds.pre_draw(manager, view);
745 layer.prepass.pre_draw(manager, view);
746 layer.wireframe.pre_draw(manager, view);
747 };
748
749 pre_draw(regular);
750 pre_draw(infront);
751
752 outline.pre_draw(manager, view);
753 }
754
755 resources.acquire(DRW_context_get(), this->state);
756
758
759 /* TODO(fclem): Would be better to have a v2d overlay class instead of these conditions. */
760 switch (state.space_type) {
761 case SPACE_NODE:
762 draw_node(manager, view);
763 break;
764 case SPACE_IMAGE:
765 draw_v2d(manager, view);
766 break;
767 case SPACE_VIEW3D:
768 draw_v3d(manager, view);
769 break;
770 default:
772 }
773
775
776 resources.release();
777
778 resources.read_result();
779
780 if (state.is_depth_only_drawing) {
781 depth_scope.end_capture();
782 }
783 else if (resources.is_selection()) {
784 select_scope.end_capture();
785 }
786 else {
787 draw_scope.end_capture();
788 }
789}
790
791void Instance::draw_node(Manager &manager, View &view)
792{
793 /* Don't clear background for the node editor. The node editor draws the background and we
794 * need to mask out the image from the already drawn overlay color buffer. */
796}
797
798void Instance::draw_v2d(Manager &manager, View &view)
799{
801 regular.mesh_uvs.draw_on_render(resources.render_fb, manager, view);
802
805
808 regular.mesh_uvs.draw(resources.overlay_output_fb, manager, view);
809
811}
812
813void Instance::draw_v3d(Manager &manager, View &view)
814{
815 float4 clear_color(0.0f);
816
817 auto draw = [&](OverlayLayer &layer, Framebuffer &framebuffer) {
818 /* TODO(fclem): Depth aware outlines (see #130751). */
819 // layer.facing.draw(framebuffer, manager, view);
820 layer.fade.draw(framebuffer, manager, view);
821 layer.mode_transfer.draw(framebuffer, manager, view);
822 layer.text.draw(framebuffer, manager, view);
823 layer.paints.draw(framebuffer, manager, view);
824 layer.particles.draw(framebuffer, manager, view);
825 };
826
827 auto draw_line = [&](OverlayLayer &layer, Framebuffer &framebuffer) {
828 layer.bounds.draw_line(framebuffer, manager, view);
829 layer.wireframe.draw_line(framebuffer, manager, view);
830 layer.cameras.draw_line(framebuffer, manager, view);
831 layer.empties.draw_line(framebuffer, manager, view);
832 layer.axes.draw_line(framebuffer, manager, view);
833 layer.force_fields.draw_line(framebuffer, manager, view);
834 layer.lights.draw_line(framebuffer, manager, view);
835 layer.light_probes.draw_line(framebuffer, manager, view);
836 layer.speakers.draw_line(framebuffer, manager, view);
837 layer.lattices.draw_line(framebuffer, manager, view);
838 layer.metaballs.draw_line(framebuffer, manager, view);
839 layer.pointclouds.draw_line(framebuffer, manager, view);
840 layer.relations.draw_line(framebuffer, manager, view);
841 layer.fluids.draw_line(framebuffer, manager, view);
842 layer.particles.draw_line(framebuffer, manager, view);
843 layer.attribute_viewer.draw_line(framebuffer, manager, view);
844 layer.armatures.draw_line(framebuffer, manager, view);
845 layer.sculpts.draw_line(framebuffer, manager, view);
846 layer.grease_pencil.draw_line(framebuffer, manager, view);
847 /* NOTE: Temporarily moved after grid drawing (See #136764). */
848 // layer.meshes.draw_line(framebuffer, manager, view);
849 layer.curves.draw_line(framebuffer, manager, view);
850 };
851
852 auto draw_color_only = [&](OverlayLayer &layer, Framebuffer &framebuffer) {
853 layer.light_probes.draw_color_only(framebuffer, manager, view);
854 layer.meshes.draw_color_only(framebuffer, manager, view);
855 layer.curves.draw_color_only(framebuffer, manager, view);
856 layer.grease_pencil.draw_color_only(framebuffer, manager, view);
857 };
858
859 {
860 /* Render pass. Draws directly on render result (instead of overlay result). */
861 /* TODO(fclem): Split overlay and rename draw functions. */
862 regular.cameras.draw_scene_background_images(resources.render_fb, manager, view);
863 infront.cameras.draw_scene_background_images(resources.render_in_front_fb, manager, view);
864
865 regular.sculpts.draw_on_render(resources.render_fb, manager, view);
866 infront.sculpts.draw_on_render(resources.render_in_front_fb, manager, view);
867 }
868 {
869 /* Overlay Line prepass. */
870 GPU_framebuffer_bind(resources.overlay_line_fb);
871 if (state.xray_enabled) {
872 /* Rendering to a new depth buffer that needs to be cleared. */
873 GPU_framebuffer_clear_color_depth(resources.overlay_line_fb, clear_color, 1.0f);
874 }
875 else {
876 if (!state.is_render_depth_available) {
877 /* If the render engine is not outputting correct depth,
878 * clear the depth and render a depth prepass. */
879 GPU_framebuffer_clear_color_depth(resources.overlay_line_fb, clear_color, 1.0f);
880 }
881 else {
882 GPU_framebuffer_clear_color(resources.overlay_line_fb, clear_color);
883 }
884 }
885
886 if (BLI_thread_is_main() && !state.hide_overlays) {
888 }
889
890 regular.prepass.draw_line(resources.overlay_line_fb, manager, view);
891
892 /* TODO(fclem): Split overlay and rename draw functions. */
893 /* TODO(fclem): Draw on line framebuffer. */
894 regular.empties.draw_images(resources.overlay_fb, manager, view);
895
896 if (state.xray_enabled || (state.v3d && state.v3d->shading.type > OB_SOLID)) {
897 /* If workbench is not enabled, the infront buffer might contain garbage. */
898 GPU_framebuffer_bind(resources.overlay_line_in_front_fb);
899 GPU_framebuffer_clear_depth(resources.overlay_line_in_front_fb, 1.0f);
900 }
901
902 infront.prepass.draw_line(resources.overlay_line_in_front_fb, manager, view);
903 }
904 {
905 /* Copy depth at the end of the prepass to avoid splitting the main render pass. */
906 /* TODO(fclem): Better get rid of it. */
907 regular.wireframe.copy_depth(resources.depth_target_tx);
908 infront.wireframe.copy_depth(resources.depth_target_in_front_tx);
909 }
910 {
911 /* TODO(fclem): This is really bad for performance as the outline pass will then split the
912 * render pass and do a framebuffer switch. This also only fix the issue for non-infront
913 * objects.
914 * We need to figure a way to merge the outline with correct depth awareness (see #130751). */
915 regular.facing.draw(resources.overlay_fb, manager, view);
916
917 /* Line only pass. */
918 outline.draw_line_only_ex(resources.overlay_line_only_fb, resources, manager, view);
919 }
920 {
921 /* Overlay (+Line) pass. */
922 draw(regular, resources.overlay_fb);
923 draw_line(regular, resources.overlay_line_fb);
924
925 /* Here because of custom order of regular.facing. */
926 infront.facing.draw(resources.overlay_fb, manager, view);
927
928 draw(infront, resources.overlay_in_front_fb);
929 draw_line(infront, resources.overlay_line_in_front_fb);
930 }
931 {
932 /* Color only pass. */
933 motion_paths.draw_color_only(resources.overlay_color_only_fb, manager, view);
934 xray_fade.draw_color_only(resources.overlay_color_only_fb, manager, view);
935 grid.draw_color_only(resources.overlay_color_only_fb, manager, view);
936
937 regular.meshes.draw_line(resources.overlay_line_fb, manager, view);
938 infront.meshes.draw_line(resources.overlay_line_in_front_fb, manager, view);
939
940 draw_color_only(regular, resources.overlay_color_only_fb);
941 draw_color_only(infront, resources.overlay_color_only_fb);
942
943 /* TODO(fclem): Split overlay and rename draw functions. */
944 regular.empties.draw_in_front_images(resources.overlay_color_only_fb, manager, view);
945 infront.empties.draw_in_front_images(resources.overlay_color_only_fb, manager, view);
946 regular.cameras.draw_in_front(resources.overlay_color_only_fb, manager, view);
947 infront.cameras.draw_in_front(resources.overlay_color_only_fb, manager, view);
948
949 origins.draw_color_only(resources.overlay_color_only_fb, manager, view);
950 }
951
952 if (state.is_depth_only_drawing == false) {
953 /* Output pass. */
954 GPU_framebuffer_bind(resources.overlay_output_color_only_fb);
955 GPU_framebuffer_clear_color(resources.overlay_output_color_only_fb, clear_color);
956
957 /* TODO(fclem): Split overlay and rename draw functions. */
958 regular.cameras.draw_background_images(resources.overlay_output_color_only_fb, manager, view);
959 infront.cameras.draw_background_images(resources.overlay_output_color_only_fb, manager, view);
960 regular.empties.draw_background_images(resources.overlay_output_color_only_fb, manager, view);
961
962 background.draw_output(resources.overlay_output_color_only_fb, manager, view);
963 anti_aliasing.draw_output(resources.overlay_output_color_only_fb, manager, view);
964 cursor.draw_output(resources.overlay_output_color_only_fb, manager, view);
965
966 draw_text(resources.overlay_output_color_only_fb);
967
968 if (state.vignette_enabled) {
969 background.draw_vignette(resources.overlay_output_color_only_fb, manager, view);
970 }
971 }
972}
973
974void Instance::draw_text(Framebuffer &framebuffer)
975{
976 if (state.show_text == false) {
977 return;
978 }
979 GPU_framebuffer_bind(framebuffer);
980
982 DRW_text_cache_draw(state.dt, state.region, state.v3d);
983}
984
985bool Instance::object_is_selected(const ObjectRef &ob_ref)
986{
987 return (ob_ref.object->base_flag & BASE_SELECTED);
988}
989
990bool Instance::object_is_paint_mode(const Object *object)
991{
992 return (object == state.object_active) &&
994}
995
996bool Instance::object_is_sculpt_mode(const ObjectRef &ob_ref)
997{
998 if (state.object_mode == OB_MODE_SCULPT_CURVES) {
999 const Object *active_object = state.object_active;
1000 const bool is_active_object = ob_ref.object == active_object;
1001
1002 bool is_active_geonode_preview = ob_ref.preview_base_geometry() != nullptr &&
1003 ob_ref.is_active(state.object_active);
1004 return is_active_object || is_active_geonode_preview;
1005 }
1006
1007 if (state.object_mode == OB_MODE_SCULPT) {
1008 const Object *active_object = state.object_active;
1009 const bool is_active_object = ob_ref.object == active_object;
1010 return is_active_object;
1011 }
1012
1013 return false;
1014}
1015
1016bool Instance::object_is_particle_edit_mode(const ObjectRef &ob_ref)
1017{
1018 return (ob_ref.object->mode == OB_MODE_PARTICLE_EDIT) && (state.ctx_mode == CTX_MODE_PARTICLE);
1019}
1020
1021bool Instance::object_is_sculpt_mode(const Object *object)
1022{
1023 if (object->sculpt && (object->sculpt->mode_type == OB_MODE_SCULPT)) {
1024 return object == state.object_active;
1025 }
1026 return false;
1027}
1028
1029bool Instance::object_is_edit_paint_mode(const ObjectRef &ob_ref,
1030 bool in_edit_mode,
1031 bool in_paint_mode,
1032 bool in_sculpt_mode)
1033{
1034 bool in_edit_paint_mode = in_edit_mode || in_paint_mode || in_sculpt_mode;
1035 /* Disable outlines for objects instanced by an object in sculpt, paint or edit mode. */
1036 return in_edit_paint_mode || ob_ref.parent_is_in_edit_paint_mode(
1037 state.object_active, state.object_mode, state.ctx_mode);
1038}
1039
1040bool Instance::object_is_edit_mode(const Object *object)
1041{
1042 if (DRW_object_is_in_edit_mode(object)) {
1043 /* Also check for context mode as the object mode is not 100% reliable. (see T72490) */
1044 switch (object->type) {
1045 case OB_MESH:
1046 return state.ctx_mode == CTX_MODE_EDIT_MESH;
1047 case OB_ARMATURE:
1048 return state.ctx_mode == CTX_MODE_EDIT_ARMATURE;
1049 case OB_CURVES_LEGACY:
1050 return state.ctx_mode == CTX_MODE_EDIT_CURVE;
1051 case OB_SURF:
1052 return state.ctx_mode == CTX_MODE_EDIT_SURFACE;
1053 case OB_LATTICE:
1054 return state.ctx_mode == CTX_MODE_EDIT_LATTICE;
1055 case OB_MBALL:
1056 return state.ctx_mode == CTX_MODE_EDIT_METABALL;
1057 case OB_FONT:
1058 return state.ctx_mode == CTX_MODE_EDIT_TEXT;
1059 case OB_CURVES:
1060 return state.ctx_mode == CTX_MODE_EDIT_CURVES;
1061 case OB_POINTCLOUD:
1062 return state.ctx_mode == CTX_MODE_EDIT_POINTCLOUD;
1063 case OB_GREASE_PENCIL:
1064 return state.ctx_mode == CTX_MODE_EDIT_GREASE_PENCIL;
1065 case OB_VOLUME:
1066 /* No edit mode yet. */
1067 return false;
1068 }
1069 }
1070 return false;
1071}
1072
1073bool Instance::object_is_in_front(const Object *object, const State &state)
1074{
1075 switch (object->type) {
1076 case OB_ARMATURE:
1077 return (object->dtx & OB_DRAW_IN_FRONT) ||
1078 (state.do_pose_xray && Armatures::is_pose_mode(object, state));
1079 default:
1080 return state.use_in_front && (object->dtx & OB_DRAW_IN_FRONT);
1081 }
1082}
1083
1084bool Instance::object_needs_prepass(const ObjectRef &ob_ref, bool in_paint_mode)
1085{
1086 if (resources.is_selection() && state.is_wireframe_mode && !state.is_solid()) {
1087 /* Selection in wireframe mode only use wires unless xray opacity is 1. */
1088 return false;
1089 }
1090
1091 if (resources.is_selection() || state.is_depth_only_drawing) {
1092 if (ob_ref.object->visibility_flag & OB_HIDE_SURFACE_PICK) {
1093 /* Special flag to avoid surfaces to contribute to depth picking and selection. */
1094 return false;
1095 }
1096 /* Selection and depth picking always need a prepass.
1097 * Note that depth writing and depth test might be disable for certain selection mode. */
1098 return true;
1099 }
1100
1101 if (in_paint_mode) {
1102 /* Allow paint overlays to draw with depth equal test. */
1103 if (object_is_rendered_transparent(ob_ref.object, state) ||
1104 object_is_in_front(ob_ref.object, state))
1105 {
1106 return true;
1107 }
1108 }
1109
1110 if (!state.xray_enabled) {
1111 /* Force depth prepass if depth buffer form render engine is not available. */
1112 if (!state.is_render_depth_available && (ob_ref.object->dt >= OB_SOLID)) {
1113 return true;
1114 }
1115 }
1116
1117 return false;
1118}
1119
1120bool Instance::object_is_rendered_transparent(const Object *object, const State &state)
1121{
1122 if (state.v3d == nullptr) {
1123 return false;
1124 }
1125
1126 if (!state.is_solid()) {
1127 return true;
1128 }
1129
1130 if (ELEM(object->dt, OB_WIRE, OB_BOUNDBOX)) {
1131 return true;
1132 }
1133
1134 const View3DShading &shading = state.v3d->shading;
1135
1136 if (shading.type == OB_WIRE) {
1137 return true;
1138 }
1139
1140 if (shading.type > OB_SOLID) {
1141 return false;
1142 }
1143
1144 if (shading.color_type == V3D_SHADING_OBJECT_COLOR) {
1145 return object->color[3] < 1.0f;
1146 }
1147
1148 if (shading.color_type == V3D_SHADING_MATERIAL_COLOR) {
1149 if (object->type == OB_MESH) {
1150 const int materials_num = BKE_object_material_used_with_fallback_eval(*object);
1151 for (int i = 0; i < materials_num; i++) {
1152 Material *mat = BKE_object_material_get_eval(const_cast<Object *>(object), i + 1);
1153 if (mat && mat->a < 1.0f) {
1154 return true;
1155 }
1156 }
1157 }
1158 }
1159
1160 return false;
1161}
1162
1163} // namespace blender::draw::overlay
bool BKE_colorband_evaluate(const ColorBand *coba, float in, float out[4])
Definition colorband.cc:396
@ CTX_MODE_EDIT_CURVE
@ CTX_MODE_EDIT_SURFACE
@ CTX_MODE_PARTICLE
@ CTX_MODE_EDIT_MESH
@ CTX_MODE_EDIT_POINTCLOUD
@ CTX_MODE_EDIT_GREASE_PENCIL
@ CTX_MODE_EDIT_TEXT
@ CTX_MODE_EDIT_CURVES
@ CTX_MODE_EDIT_ARMATURE
@ CTX_MODE_EDIT_LATTICE
@ CTX_MODE_EDIT_METABALL
enum eContextObjectMode CTX_data_mode_enum_ex(const Object *obedit, const Object *ob, eObjectMode object_mode)
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
Object * BKE_view_layer_active_object_get(const ViewLayer *view_layer)
Material * BKE_object_material_get_eval(Object *ob, short act)
int BKE_object_material_used_with_fallback_eval(const Object &ob)
int BKE_render_preview_pixel_size(const RenderData *r)
Definition scene.cc:2930
bool BKE_scene_uses_blender_workbench(const Scene *scene)
Definition scene.cc:2829
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
MINLINE float max_ff(float a, float b)
void hsv_to_rgb_v(const float hsv[3], float r_rgb[3])
Definition math_color.cc:57
MINLINE void rgba_uchar_to_float(float r_col[4], const unsigned char col_ub[4])
MINLINE void srgb_to_linearrgb_v4(float linear[4], const float srgb[4])
#define M_SQRT1_2
unsigned char uchar
int BLI_thread_is_main(void)
Definition threads.cc:179
#define ARRAY_SIZE(arr)
#define ELEM(...)
#define STREQ(a, b)
float DEG_get_ctime(const Depsgraph *graph)
struct Material Material
#define OB_MODE_ALL_PAINT
@ OB_WIRE
@ OB_BOUNDBOX
@ OB_SOLID
#define OB_MODE_ALL_PAINT_GPENCIL
@ OB_MODE_PARTICLE_EDIT
@ OB_MODE_EDIT
@ OB_MODE_WEIGHT_PAINT
@ OB_MODE_SCULPT
@ OB_MODE_SCULPT_CURVES
@ OB_MODE_OBJECT
@ OB_HIDE_SURFACE_PICK
@ OB_DRAW_IN_FRONT
@ OB_SPEAKER
@ OB_LATTICE
@ OB_MBALL
@ OB_EMPTY
@ OB_SURF
@ OB_CAMERA
@ OB_FONT
@ OB_GREASE_PENCIL
@ OB_ARMATURE
@ OB_LAMP
@ OB_MESH
@ OB_POINTCLOUD
@ OB_VOLUME
@ OB_CURVES_LEGACY
@ OB_CURVES
@ OB_LIGHTPROBE
struct Object Object
#define BASE_SELECTED(v3d, base)
@ SI_OVERLAY_SHOW_OVERLAYS
eSpace_Type
@ SPACE_NODE
@ SPACE_IMAGE
@ SPACE_VIEW3D
@ USER_GPU_FLAG_FRESNEL_EDIT
@ USER_CUSTOM_RANGE
@ V3D_SHADING_MATERIAL_COLOR
@ V3D_SHADING_OBJECT_COLOR
@ V3D_HIDE_OVERLAYS
@ V3D_SHADING_BACKFACE_CULLING
#define RV3D_LOCK_FLAGS(rv3d)
#define RV3D_CLIPPING_ENABLED(v3d, rv3d)
struct View3DShading View3DShading
@ RV3D_BOXCLIP
@ V3D_OVERLAY_HIDE_OBJECT_ORIGINS
@ V3D_OVERLAY_HIDE_BONES
@ V3D_OVERLAY_HIDE_MOTION_PATHS
@ V3D_OVERLAY_HIDE_OBJECT_XTRAS
@ V3D_OVERLAY_HIDE_TEXT
void DRW_submission_end()
void DRW_submission_start()
void ED_space_image_get_size(SpaceImage *sima, int *r_width, int *r_height)
void ED_space_image_get_uv_aspect(SpaceImage *sima, float *r_aspx, float *r_aspy)
void ED_space_image_get_aspect(SpaceImage *sima, float *r_aspx, float *r_aspy)
#define XRAY_ACTIVE(v3d)
#define SHADING_XRAY_FLAG_ENABLED(shading)
#define XRAY_ALPHA(v3d)
RenderEngineType * ED_view3d_engine_type(const Scene *scene, int drawtype)
static AppView * view
static void View(GHOST_IWindow *window, bool stereo, int eye=0)
void GPU_framebuffer_clear_depth(blender::gpu::FrameBuffer *fb, float clear_depth)
void GPU_framebuffer_clear_color(blender::gpu::FrameBuffer *fb, const float clear_col[4])
#define GPU_framebuffer_ensure_config(_fb,...)
void GPU_framebuffer_clear_color_depth(blender::gpu::FrameBuffer *fb, const float clear_col[4], float clear_depth)
void GPU_framebuffer_bind(blender::gpu::FrameBuffer *fb)
@ GPU_DEPTH_NONE
Definition GPU_state.hh:111
void GPU_depth_test(GPUDepthTest test)
Definition gpu_state.cc:68
void GPU_texture_update_sub(blender::gpu::Texture *texture, eGPUDataFormat data_format, const void *pixels, int offset_x, int offset_y, int offset_z, int width, int height, int depth)
@ GPU_DATA_UBYTE
@ GPU_DATA_FLOAT
eGPUTextureUsage
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_GENERAL
blender::gpu::Texture * GPU_texture_create_2d(const char *name, int width, int height, int mip_len, blender::gpu::TextureFormat format, eGPUTextureUsage usage, const float *data)
void GPU_texture_update(blender::gpu::Texture *texture, eGPUDataFormat data_format, const void *data)
@ TH_BONE_SOLID
@ TH_HANDLE_ALIGN
@ TH_NORMAL
@ TH_LIGHT
@ TH_FACE_BACK
@ TH_BACK_GRAD
@ TH_LNORMAL
@ TH_NURB_SEL_VLINE
@ TH_FRAME_AFTER
@ TH_SEAM
@ TH_TRANSPARENT_CHECKER_PRIMARY
@ TH_BONE_POSE_ACTIVE
@ TH_GRID
@ TH_BACK
@ TH_WIRE
@ TH_BONE_LOCKED_WEIGHT
@ TH_FACEDOT_SIZE
@ TH_BONE_POSE
@ TH_HANDLE_SEL_AUTO
@ TH_SHARP
@ TH_SKIN_ROOT
@ TH_EDGE_SELECT
@ TH_TRANSPARENT_CHECKER_SECONDARY
@ TH_HANDLE_SEL_AUTOCLAMP
@ TH_CAMERA
@ TH_TRANSFORM
@ TH_HANDLE_AUTO
@ TH_NURB_VLINE
@ TH_SPEAKER
@ TH_VERTEX
@ TH_HANDLE_SEL_ALIGN
@ TH_GP_VERTEX_SELECT
@ TH_OBCENTER_DIA
@ TH_UV_SHADOW
@ TH_FACE_RETOPOLOGY
@ TH_BEVEL
@ TH_HANDLE_SEL_FREE
@ TH_FACE_SELECT
@ TH_CFRAME
@ TH_NURB_ULINE
@ TH_AXIS_Y
@ TH_AXIS_X
@ TH_HANDLE_SEL_VECT
@ TH_VERTEX_SELECT
@ TH_EMPTY
@ TH_FACE_FRONT
@ TH_VERTEX_UNREFERENCED
@ TH_TRANSPARENT_CHECKER_SIZE
@ TH_V3D_CLIPPING_BORDER
@ TH_AXIS_Z
@ TH_EDGE_WIDTH
@ TH_EDITMESH_ACTIVE
@ TH_GP_VERTEX_SIZE
@ TH_GP_VERTEX
@ TH_FRAME_BEFORE
@ TH_EDGE_MODE_SELECT
@ TH_FACE_MODE_SELECT
@ TH_CAMERA_PATH
@ TH_SELECT
@ TH_HANDLE_FREE
@ TH_HANDLE_AUTOCLAMP
@ TH_HANDLE_VECT
@ TH_TEXT
@ TH_WIRE_EDIT
@ TH_FREESTYLE
@ TH_NURB_SEL_ULINE
@ TH_ACTIVE
@ TH_FACE
@ TH_VNORMAL
@ TH_CREASE
@ TH_TEXT_HI
void UI_GetThemeColorBlendShade4fv(int colorid1, int colorid2, float fac, int offset, float col[4])
void UI_GetThemeColorBlendShade3fv(int colorid1, int colorid2, float fac, int offset, float col[3])
void UI_GetThemeColorShadeAlpha4fv(int colorid, int coloffset, int alphaoffset, float col[4])
void UI_GetThemeColor4fv(int colorid, float col[4])
void UI_GetThemeColorShade4fv(int colorid, int offset, float col[4])
float UI_GetThemeValuef(int colorid)
#define U
BMesh const char void * data
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
void display_to_view(View &view)
static DebugDraw & get()
void ensure_visibility(View &view)
static View & default_get()
Definition draw_view.cc:317
static bool is_pose_mode(const Object *armature_ob, const State &state)
void edit_object_sync(Manager &, const ObjectRef &ob_ref, Resources &res, const State &state) final
void object_sync(Manager &, const ObjectRef &ob_ref, Resources &res, const State &state) final
void object_sync(Manager &, const ObjectRef &ob_ref, Resources &, const State &state) final
void object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &, const State &state) final
void object_sync(Manager &, const ObjectRef &ob_ref, Resources &res, const State &state) final
void draw_output(Framebuffer &framebuffer, Manager &manager, View &view) final
void object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &res, const State &state) final
void draw_output(Framebuffer &framebuffer, Manager &manager, View &) final
void edit_object_sync_legacy(Manager &manager, const ObjectRef &ob_ref, Resources &)
void edit_object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &, const State &) final
void object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &res, const State &state) final
void object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &, const State &state) final
void object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &, const State &state) final
void object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &res, const State &state) final
void object_sync(Manager &, const ObjectRef &ob_ref, Resources &res, const State &state) final
void sculpt_object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &res, const State &state)
void object_sync(Manager &, const ObjectRef &ob_ref, Resources &, const State &state) final
void edit_object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &res, const State &state) final
void paint_object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &res, const State &state)
void draw_color_only(Framebuffer &framebuffer, Manager &manager, View &view) final
void draw_on_render(gpu::FrameBuffer *framebuffer, Manager &manager, View &view) final
void draw(Manager &manager) final
void object_sync(ObjectRef &ob_ref, Manager &manager) final
void edit_object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &res, const State &) final
void object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &res, const State &state) final
void object_sync(Manager &, const ObjectRef &ob_ref, Resources &res, const State &state) final
void object_sync(Manager &, const ObjectRef &ob_ref, Resources &res, const State &state) final
void object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &, const State &state) final
void edit_object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &, const State &state) final
void edit_object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &, const State &state) final
void object_sync(Manager &, const ObjectRef &ob_ref, Resources &res, const State &state) final
void edit_object_sync(Manager &, const ObjectRef &ob_ref, Resources &res, const State &) final
void object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &, const State &state) final
void object_sync(Manager &, const ObjectRef &ob_ref, Resources &res, const State &state) final
void object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &, const State &state) final
void object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &res, const State &state) final
void edit_object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &, const State &state) final
void edit_object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &res, const State &) final
void object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &res, const State &state) final
void object_sync(Manager &, const ObjectRef &ob_ref, Resources &res, const State &state) final
void object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &, const State &state) final
void object_sync(Manager &, const ObjectRef &ob_ref, Resources &res, const State &state) final
void edit_object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &res, const State &) final
void object_sync_ex(Manager &manager, const ObjectRef &ob_ref, Resources &res, const State &state, const bool in_edit_paint_mode, const bool in_edit_mode)
nullptr float
const DRWContext * DRW_context_get()
bool DRW_object_is_in_edit_mode(const Object *ob)
Simple API to draw debug shapes and log in the viewport.
void DRW_text_cache_draw(const DRWTextStore *dt, const ARegion *region, const View3D *v3d)
DRWTextStore * DRW_text_cache_create()
void DRW_text_cache_destroy(DRWTextStore *dt)
#define pow
#define unit_float_to_uchar_clamp_v4(v1, v2)
static ulong state[N]
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
T interpolate(const T &a, const T &b, const FactorT &t)
bool is_equal(const MatBase< T, NumCol, NumRow > &a, const MatBase< T, NumCol, NumRow > &b, const T epsilon=T(0))
T reduce_add(const VecBase< T, Size > &a)
bool assign_if_different(T &old_value, T new_value)
blender::VecBase< uint8_t, 4 > uchar4
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 3 > float3
const char * RE_engine_id_BLENDER_EEVEE
Definition scene.cc:1580
bool is_image_render() const
Object * object_edit
bool draw_background
DefaultFramebufferList * viewport_framebuffer_list_get() const
View3D * v3d
Depsgraph * depsgraph
RegionView3D * rv3d
@ DEPTH_ACTIVE_OBJECT
Object * obact
enum DRWContext::Mode mode
blender::float2 viewport_size_get() const
Scene * scene
Object * object_pose
bool is_depth() const
bool is_viewport_image_render() const
eObjectMode object_mode
ARegion * region
SpaceLink * space_data
DefaultTextureList * viewport_texture_list_get() const
struct DRWContext::@137223300060360004345077367045216134275315355136 options
ViewLayer * view_layer
bool is_material_select() const
blender::gpu::FrameBuffer * in_front_fb
blender::gpu::Texture * depth_in_front
struct SculptSession * sculpt
char idname[64]
Definition RE_engine.h:73
eObjectMode mode_type
Definition BKE_paint.hh:491
SpaceImageOverlay overlay
struct Image * image
View3DOverlay overlay
void update_theme_settings(const DRWContext *ctx, const State &state)
draw::UniformArrayBuffer< float4, 6 > clip_planes_buf
draw::UniformBuffer< UniformData > globals_buf
void update_clip_planes(const State &state)
i
Definition text_draw.cc:230