DRW: Selection Occlusion #105498

Merged
Clément Foucault merged 16 commits from bonj/blender:retopology-select into main 2023-04-09 08:08:13 +02:00
6 changed files with 56 additions and 2 deletions

View File

@ -9,6 +9,8 @@
#include "DNA_screen_types.h"
#include "ED_view3d.h"
#include "UI_resources.h"
#include "DRW_engine.h"
@ -138,29 +140,44 @@ static void select_cache_init(void *vedata)
DRWState state = DRW_STATE_DEFAULT;
state |= RV3D_CLIPPING_ENABLED(draw_ctx->v3d, draw_ctx->rv3d) ? DRW_STATE_CLIP_PLANES : 0;
bool retopology_occlusion = RETOPOLOGY_ENABLED(draw_ctx->v3d) && !XRAY_ENABLED(draw_ctx->v3d);
float retopology_offset = RETOPOLOGY_OFFSET(draw_ctx->v3d);
{
DRW_PASS_CREATE(psl->depth_only_pass, state);
pd->shgrp_depth_only = DRW_shgroup_create(sh->select_id_uniform, psl->depth_only_pass);
/* Not setting ID because this pass only draws to the depth buffer. */
DRW_shgroup_uniform_float_copy(pd->shgrp_depth_only, "retopologyOffset", retopology_offset);
if (retopology_occlusion) {
pd->shgrp_occlude = DRW_shgroup_create(sh->select_id_uniform, psl->depth_only_pass);
fclem marked this conversation as resolved Outdated

This feels weird to me. Why is this group using id == 0 when shgrp_depth_only doesn't? I think it is better to be consistent and set it for both cases. Also I wouldn't mind adding a comment saying this id isn't actually used since the pass is written on a depth only framebuffer.

This feels weird to me. Why is this group using `id == 0` when `shgrp_depth_only` doesn't? I think it is better to be consistent and set it for both cases. Also I wouldn't mind adding a comment saying this id isn't actually used since the pass is written on a depth only framebuffer.
/* Not setting ID because this pass only draws to the depth buffer. */
DRW_shgroup_uniform_float_copy(pd->shgrp_occlude, "retopologyOffset", 0.0f);
}
DRW_PASS_CREATE(psl->select_id_face_pass, state);
if (e_data.context.select_mode & SCE_SELECT_FACE) {
pd->shgrp_face_flat = DRW_shgroup_create(sh->select_id_flat, psl->select_id_face_pass);
DRW_shgroup_uniform_float_copy(pd->shgrp_face_flat, "retopologyOffset", retopology_offset);
}
else {
pd->shgrp_face_unif = DRW_shgroup_create(sh->select_id_uniform, psl->select_id_face_pass);
DRW_shgroup_uniform_int_copy(pd->shgrp_face_unif, "id", 0);
DRW_shgroup_uniform_float_copy(pd->shgrp_face_unif, "retopologyOffset", retopology_offset);
}
if (e_data.context.select_mode & SCE_SELECT_EDGE) {
DRW_PASS_CREATE(psl->select_id_edge_pass, state | DRW_STATE_FIRST_VERTEX_CONVENTION);
pd->shgrp_edge = DRW_shgroup_create(sh->select_id_flat, psl->select_id_edge_pass);
DRW_shgroup_uniform_float_copy(pd->shgrp_edge, "retopologyOffset", retopology_offset);
}
if (e_data.context.select_mode & SCE_SELECT_VERTEX) {
DRW_PASS_CREATE(psl->select_id_vert_pass, state);
pd->shgrp_vert = DRW_shgroup_create(sh->select_id_flat, psl->select_id_vert_pass);
DRW_shgroup_uniform_float_copy(pd->shgrp_vert, "sizeVertex", 2 * G_draw.block.size_vertex);
DRW_shgroup_uniform_float_copy(pd->shgrp_vert, "retopologyOffset", retopology_offset);
}
}
@ -197,6 +214,14 @@ static void select_cache_populate(void *vedata, Object *ob)
SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl;
const DRWContextState *draw_ctx = DRW_context_state_get();
if (!DRW_object_is_in_edit_mode(ob)) {
if (ob->dt >= OB_SOLID) {
struct GPUBatch *geom_faces = DRW_mesh_batch_cache_get_surface(ob->data);
DRW_shgroup_call_obmat(stl->g_data->shgrp_occlude, geom_faces, ob->object_to_world);
}
return;
}
SELECTID_ObjectData *sel_data = (SELECTID_ObjectData *)DRW_drawdata_get(
&ob->id, &draw_engine_select_type);

View File

@ -40,6 +40,7 @@ typedef struct SELECTID_Shaders {
typedef struct SELECTID_PrivateData {
DRWShadingGroup *shgrp_depth_only;
DRWShadingGroup *shgrp_occlude;
DRWShadingGroup *shgrp_face_unif;
DRWShadingGroup *shgrp_face_flat;
DRWShadingGroup *shgrp_edge;

View File

@ -11,6 +11,7 @@ GPU_SHADER_INTERFACE_INFO(select_id_iface, "").flat(Type::INT, "id");
GPU_SHADER_CREATE_INFO(select_id_flat)
.push_constant(Type::FLOAT, "sizeVertex")
.push_constant(Type::INT, "offset")
.push_constant(Type::FLOAT, "retopologyOffset")
.vertex_in(0, Type::VEC3, "pos")
.vertex_in(1, Type::INT, "index")
.vertex_out(select_id_iface)
@ -24,6 +25,7 @@ GPU_SHADER_CREATE_INFO(select_id_uniform)
.define("UNIFORM_ID")
.push_constant(Type::FLOAT, "sizeVertex")
.push_constant(Type::INT, "id")
.push_constant(Type::FLOAT, "retopologyOffset")
.vertex_in(0, Type::VEC3, "pos")
.fragment_out(0, Type::UINT, "fragColor")
.vertex_source("select_id_vert.glsl")

View File

@ -8,8 +8,12 @@ void main()
#endif
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);
vec3 view_pos = point_world_to_view(world_pos);
gl_Position = point_view_to_ndc(view_pos);
gl_PointSize = sizeVertex;
/* Offset Z position for retopology selection occlusion. */
gl_Position.z += get_homogenous_z_offset(view_pos.z, gl_Position.w, retopologyOffset);
view_clipping_distances(world_pos);
}

View File

@ -2770,6 +2770,25 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d, cons
drw_engines_cache_populate(obj_eval);
}
if (RETOPOLOGY_ENABLED(v3d) && !XRAY_ENABLED(v3d)) {
DEGObjectIterSettings deg_iter_settings = {0};
deg_iter_settings.depsgraph = depsgraph;
deg_iter_settings.flags = DEG_OBJECT_ITER_FOR_RENDER_ENGINE_FLAGS;
DEG_OBJECT_ITER_BEGIN (&deg_iter_settings, ob) {

Draw manager should be as functionality agnostic as much as possible. Adding this if-statement might be ok as we also check if bone overlay is enabled. But the if statements inside the iterator should be done by the draw engines.

Selection engine is currently being redesigned. I think @fclem @pragma37 can do a better review of this part keeping in mind the new design.

Draw manager should be as functionality agnostic as much as possible. Adding this if-statement might be ok as we also check if bone overlay is enabled. But the if statements inside the iterator should be done by the draw engines. Selection engine is currently being redesigned. I think @fclem @pragma37 can do a better review of this part keeping in mind the new design.

Well this is extending the already existing edit mode selection path. I really don't see the problem as other part of the draw-manager are state aware of the View3D. Obviously this will need to be fitted to the new selection engine but that's not a project for the 3.6 release.

Also note that #102177 is only targeting object selection mode.

Well this is extending the already existing edit mode selection path. I really don't see the problem as other part of the draw-manager are state aware of the View3D. Obviously this will need to be fitted to the new selection engine but that's not a project for the 3.6 release. Also note that #102177 is only targeting object selection mode.
if (ob->type != OB_MESH) {
/* The iterator has evaluated meshes for all solid objects.
* It also has non-mesh objects however, which are not supported here. */
continue;
}
if (DRW_object_is_in_edit_mode(ob)) {
/* Only background (non-edit) objects are used for occlusion. */
continue;
}
drw_engines_cache_populate(ob);
}
DEG_OBJECT_ITER_END;
bonj marked this conversation as resolved Outdated

It might be interesting to put this code inside a condition that checks if it's not X-Ray or wireframe. It may even improve readability.

Why only objects of type OB_MESH have the depth drawn? It may be good to comment on the reason.

It might be interesting to put this code inside a condition that checks if it's not X-Ray or wireframe. It may even improve readability. Why only objects of type `OB_MESH` have the depth drawn? It may be good to comment on the reason.

Not that it's a problem, but another way to make comments more localized could be:

if (ob->type != OB_MESH) {
    /* Non-mesh objects are not supported here. */
    continue;
}

if (DRW_object_is_in_edit_mode(ob)) {
    /* Only background (non-edit) objects are used for occlusion. */
    continue;
}

I'm wondering if Grease Pencil and Image-type Empties couldn't contribute to the depth. But if it matches what you see in the Meshes edit overlay then it's OK.

Not that it's a problem, but another way to make comments more localized could be: ``` if (ob->type != OB_MESH) { /* Non-mesh objects are not supported here. */ continue; } if (DRW_object_is_in_edit_mode(ob)) { /* Only background (non-edit) objects are used for occlusion. */ continue; } ``` I'm wondering if Grease Pencil and Image-type Empties couldn't contribute to the depth. But if it matches what you see in the Meshes edit overlay then it's OK.
}
drw_engines_cache_finish();
drw_task_graph_deinit();

View File

@ -4551,7 +4551,10 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_retopology", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "overlay.edit_flag", V3D_OVERLAY_EDIT_RETOPOLOGY);
RNA_def_property_ui_text(prop, "Retopology", "Use retopology display");
RNA_def_property_ui_text(prop,
"Retopology",
"Hide the solid mesh and offset the overlay towards the view. "
"Selection is occluded by inactive geometry, unless X-Ray is enabled");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
prop = RNA_def_property(srna, "retopology_offset", PROP_FLOAT, PROP_DISTANCE);