Xray: Add possibility to select wires in priority before surfaces

If no wires were found, try to select surfaces in a second loop.
This commit is contained in:
Clément Foucault 2018-09-04 17:14:46 +02:00
parent 950dcaea10
commit 30ae0ce0e1
Notes: blender-bot 2023-02-14 05:22:11 +01:00
Referenced by issue #56695, Selecting an occluded object in xray causes crash
Referenced by issue #56649, Proposal: Blender 2.8: Wireframe, Select Through & X-Ray
7 changed files with 128 additions and 46 deletions

View File

@ -119,7 +119,7 @@ void DRW_draw_render_loop_offscreen(
void DRW_draw_select_loop(
struct Depsgraph *depsgraph,
struct ARegion *ar, struct View3D *v3d,
bool use_obedit_skip, bool use_nearest, const struct rcti *rect,
bool use_obedit_skip, bool draw_surface, bool use_nearest, const struct rcti *rect,
DRW_SelectPassFn select_pass_fn, void *select_pass_user_data,
DRW_ObjectFilterFn object_filter_fn, void *object_filter_user_data);
void DRW_draw_depth_loop(

View File

@ -1987,7 +1987,7 @@ void DRW_render_instance_buffer_finish(void)
void DRW_draw_select_loop(
struct Depsgraph *depsgraph,
ARegion *ar, View3D *v3d,
bool UNUSED(use_obedit_skip), bool UNUSED(use_nearest), const rcti *rect,
bool UNUSED(use_obedit_skip), bool draw_surface, bool UNUSED(use_nearest), const rcti *rect,
DRW_SelectPassFn select_pass_fn, void *select_pass_user_data,
DRW_ObjectFilterFn object_filter_fn, void *object_filter_user_data)
{
@ -2037,6 +2037,10 @@ void DRW_draw_select_loop(
drw_engines_enable_from_paint_mode(obedit_mode);
drw_engines_enable_from_mode(obedit_mode);
}
else if (!draw_surface) {
drw_engines_enable_from_overlays(v3d->overlay.flag);
drw_engines_enable_from_object_mode();
}
else {
drw_engines_enable_basic();
drw_engines_enable_from_object_mode();

View File

@ -67,6 +67,7 @@ static struct {
/* Face orientation shader */
struct GPUShader *face_orientation_sh;
/* Wireframe shader */
struct GPUShader *select_wireframe_sh;
struct GPUShader *face_wireframe_sh;
struct GPUShader *face_wireframe_pretty_sh;
struct GPUShader *face_wireframe_sculpt_sh;
@ -105,6 +106,14 @@ static void overlay_engine_init(void *vedata)
if (!e_data.face_wireframe_sh) {
bool use_geom = GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY);
e_data.select_wireframe_sh = DRW_shader_create(
datatoc_overlay_face_wireframe_vert_glsl,
datatoc_overlay_face_wireframe_geom_glsl,
datatoc_overlay_face_wireframe_frag_glsl,
"#define SELECT_EDGES\n"
"#define LIGHT_EDGES\n"
"#define USE_GEOM_SHADER\n");
e_data.face_wireframe_sh = DRW_shader_create(
datatoc_overlay_face_wireframe_vert_glsl,
use_geom ? datatoc_overlay_face_wireframe_geom_glsl : NULL,
@ -207,6 +216,7 @@ static void overlay_cache_populate(void *vedata, Object *ob)
OVERLAY_PrivateData *pd = stl->g_data;
OVERLAY_PassList *psl = data->psl;
const DRWContextState *draw_ctx = DRW_context_state_get();
View3D *v3d = draw_ctx->v3d;
if (!stl->g_data->show_overlays)
return;
@ -250,13 +260,31 @@ static void overlay_cache_populate(void *vedata, Object *ob)
DRWPass *pass = (all_wires) ? psl->face_wireframe_full_pass : psl->face_wireframe_pass;
GPUShader *sh = (all_wires) ? e_data.face_wireframe_sh : e_data.face_wireframe_pretty_sh;
DRWShadingGroup *shgrp = DRW_shgroup_create(sh, pass);
DRW_shgroup_stencil_mask(shgrp, (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF);
DRW_shgroup_uniform_texture(shgrp, "vertData", verts);
DRW_shgroup_uniform_texture(shgrp, "faceIds", faceids);
DRW_shgroup_uniform_vec3(shgrp, "wireColor", ts.colorWire, 1);
DRW_shgroup_uniform_vec3(shgrp, "rimColor", rim_col, 1);
DRW_shgroup_call_object_procedural_triangles_culled_add(shgrp, tri_count, ob);
if ((DRW_state_is_select() || DRW_state_is_depth()) &&
(v3d->shading.flag & V3D_SHADING_XRAY) != 0)
{
static float params[2] = {1.2f, 1.0f}; /* Parameters for all wires */
sh = e_data.select_wireframe_sh;
DRWShadingGroup *shgrp = DRW_shgroup_create(sh, pass);
DRW_shgroup_uniform_vec2(shgrp, "viewportSize", DRW_viewport_size_get(), 1);
DRW_shgroup_uniform_vec2(shgrp, "wireStepParam", (all_wires)
? params
: stl->g_data->wire_step_param, 1);
DRW_shgroup_uniform_texture(shgrp, "vertData", verts);
DRW_shgroup_uniform_texture(shgrp, "faceIds", faceids);
DRW_shgroup_call_object_procedural_triangles_culled_add(shgrp, tri_count, ob);
}
else {
DRWShadingGroup *shgrp = DRW_shgroup_create(sh, pass);
DRW_shgroup_stencil_mask(shgrp, (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF);
DRW_shgroup_uniform_texture(shgrp, "vertData", verts);
DRW_shgroup_uniform_texture(shgrp, "faceIds", faceids);
DRW_shgroup_uniform_vec3(shgrp, "wireColor", ts.colorWire, 1);
DRW_shgroup_uniform_vec3(shgrp, "rimColor", rim_col, 1);
DRW_shgroup_call_object_procedural_triangles_culled_add(shgrp, tri_count, ob);
}
}
}
}
@ -291,7 +319,9 @@ static void overlay_draw_scene(void *vedata)
OVERLAY_PassList *psl = data->psl;
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
GPU_framebuffer_bind(dfbl->default_fb);
if (DRW_state_is_fbo()) {
GPU_framebuffer_bind(dfbl->default_fb);
}
DRW_draw_pass(psl->face_orientation_pass);
DRW_draw_pass(psl->face_wireframe_pass);
DRW_draw_pass(psl->face_wireframe_full_pass);
@ -300,6 +330,7 @@ static void overlay_draw_scene(void *vedata)
static void overlay_engine_free(void)
{
DRW_SHADER_FREE_SAFE(e_data.face_orientation_sh);
DRW_SHADER_FREE_SAFE(e_data.select_wireframe_sh);
DRW_SHADER_FREE_SAFE(e_data.face_wireframe_sh);
DRW_SHADER_FREE_SAFE(e_data.face_wireframe_pretty_sh);
DRW_SHADER_FREE_SAFE(e_data.face_wireframe_sculpt_sh);

View File

@ -1,3 +1,4 @@
#ifndef SELECT_EDGES
uniform vec3 wireColor;
uniform vec3 rimColor;
@ -6,11 +7,12 @@ flat in vec3 ssVec1;
flat in vec3 ssVec2;
in float facing;
#ifdef LIGHT_EDGES
# ifdef LIGHT_EDGES
flat in vec3 edgeSharpness;
#endif
# endif
out vec4 fragColor;
#endif
float min_v3(vec3 v) { return min(v.x, min(v.y, v.z)); }
float max_v3(vec3 v) { return max(v.x, max(v.y, v.z)); }
@ -25,6 +27,7 @@ const float rim_alpha = 0.75;
void main()
{
#ifndef SELECT_EDGES
vec3 ss_pos = vec3(gl_FragCoord.xy, 1.0);
vec3 dist_to_edge = vec3(
dot(ss_pos, ssVec0),
@ -32,11 +35,11 @@ void main()
dot(ss_pos, ssVec2)
);
#ifdef LIGHT_EDGES
# ifdef LIGHT_EDGES
vec3 fac = abs(dist_to_edge);
#else
# else
float fac = min_v3(abs(dist_to_edge));
#endif
# endif
fac = smoothstep(wire_size + wire_smooth, wire_size, fac);
@ -45,9 +48,10 @@ void main()
vec3 final_front_col = mix(rimColor, wireColor, 0.05);
fragColor = mix(vec4(rimColor, rim_alpha), vec4(final_front_col, front_alpha), facing_clamped);
#ifdef LIGHT_EDGES
# ifdef LIGHT_EDGES
fragColor.a *= max_v3(fac * edgeSharpness);
#else
# else
fragColor.a *= fac;
# endif
#endif
}

View File

@ -3,24 +3,32 @@
* than doing everything thrice in the vertex shader. */
layout(triangles) in;
#ifdef SELECT_EDGES
layout(line_strip, max_vertices = 6) out;
#else
layout(triangle_strip, max_vertices = 3) out;
#endif
uniform vec2 wireStepParam;
in vec2 ssPos[];
in float facingOut[];
#ifndef SELECT_EDGES
flat out vec3 ssVec0;
flat out vec3 ssVec1;
flat out vec3 ssVec2;
out float facing;
#endif
#ifdef LIGHT_EDGES
in vec3 obPos[];
in vec3 vNor[];
in float forceEdge[];
# ifndef SELECT_EDGES
flat out vec3 edgeSharpness;
# endif
#endif
#define NO_EDGE vec3(10000.0);
@ -53,9 +61,13 @@ void main(void)
bvec3 do_edge = greaterThan(abs(facings), vec3(1.0));
facings = fract(facings) - clamp(-sign(facings), 0.0, 1.0);
#ifndef SELECT_EDGES
ssVec0 = do_edge.x ? compute_vec(ssPos[0], ssPos[1]) : NO_EDGE;
ssVec1 = do_edge.y ? compute_vec(ssPos[1], ssPos[2]) : NO_EDGE;
ssVec2 = do_edge.z ? compute_vec(ssPos[2], ssPos[0]) : NO_EDGE;
#else
vec3 edgeSharpness;
#endif
#ifdef LIGHT_EDGES
vec3 edges[3];
@ -71,6 +83,34 @@ void main(void)
edgeSharpness.y = (forceEdge[1] == 1.0) ? 1.0 : edgeSharpness.y;
edgeSharpness.z = (forceEdge[2] == 1.0) ? 1.0 : edgeSharpness.z;
#endif
#ifdef SELECT_EDGES
const float edge_select_threshold = 0.3;
if (edgeSharpness.x > edge_select_threshold) {
gl_Position = gl_in[0].gl_Position;
EmitVertex();
gl_Position = gl_in[1].gl_Position;
EmitVertex();
EndPrimitive();
}
if (edgeSharpness.y > edge_select_threshold) {
gl_Position = gl_in[1].gl_Position;
EmitVertex();
gl_Position = gl_in[2].gl_Position;
EmitVertex();
EndPrimitive();
}
if (edgeSharpness.z > edge_select_threshold) {
gl_Position = gl_in[2].gl_Position;
EmitVertex();
gl_Position = gl_in[0].gl_Position;
EmitVertex();
EndPrimitive();
}
#else
gl_Position = gl_in[0].gl_Position;
facing = facings.x;
EmitVertex();
@ -83,4 +123,5 @@ void main(void)
facing = facings.z;
EmitVertex();
EndPrimitive();
#endif
}

View File

@ -27,13 +27,13 @@ out float facing;
#endif
#ifdef LIGHT_EDGES
#ifdef USE_GEOM_SHADER
# ifdef USE_GEOM_SHADER
out vec3 obPos;
out vec3 vNor;
out float forceEdge;
#else
# else
flat out vec3 edgeSharpness;
#endif
# endif
#endif
/* project to screen space */

View File

@ -857,7 +857,6 @@ void view3d_opengl_select_cache_end(void)
GPU_select_cache_end();
}
#ifndef WITH_OPENGL_LEGACY
struct DrawSelectLoopUserData {
uint pass;
uint hits;
@ -894,7 +893,6 @@ static bool drw_select_loop_pass(eDRWSelectStage stage, void *user_data)
return continue_pass;
}
#endif /* WITH_OPENGL_LEGACY */
/** Implement #VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK. */
static bool drw_select_filter_object_mode_lock(Object *ob, void *user_data)
@ -920,7 +918,7 @@ int view3d_opengl_select(
View3D *v3d = vc->v3d;
ARegion *ar = vc->ar;
rcti rect;
int hits;
int hits = 0;
const bool use_obedit_skip = (OBEDIT_FROM_VIEW_LAYER(vc->view_layer) != NULL) && (vc->obedit == NULL);
const bool is_pick_select = (U.gpu_select_pick_deph != 0);
const bool do_passes = (
@ -928,6 +926,7 @@ int view3d_opengl_select(
(select_mode == VIEW3D_SELECT_PICK_NEAREST) &&
GPU_select_query_check_active());
const bool use_nearest = (is_pick_select && select_mode == VIEW3D_SELECT_PICK_NEAREST);
bool draw_surface = true;
char gpu_select_mode;
@ -992,10 +991,8 @@ int view3d_opengl_select(
goto finally;
}
#ifndef WITH_OPENGL_LEGACY
/* All of the queries need to be perform on the drawing context. */
DRW_opengl_context_enable();
#endif
G.f |= G_PICKSEL;
@ -1007,25 +1004,12 @@ int view3d_opengl_select(
GPU_depth_test(true);
}
if (vc->rv3d->rflag & RV3D_CLIPPING)
if (vc->rv3d->rflag & RV3D_CLIPPING) {
ED_view3d_clipping_set(vc->rv3d);
#ifdef WITH_OPENGL_LEGACY
if (IS_VIEWPORT_LEGACY(vc->v3d)) {
GPU_select_begin(buffer, bufsize, &rect, gpu_select_mode, 0);
ED_view3d_draw_select_loop(vc, scene, sl, v3d, ar, use_obedit_skip, use_nearest);
hits = GPU_select_end();
if (do_passes && (hits > 0)) {
GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
ED_view3d_draw_select_loop(vc, scene, sl, v3d, ar, use_obedit_skip, use_nearest);
GPU_select_end();
}
}
else
#else
{
/* If in xray mode, we select the wires in priority. */
if (v3d->shading.flag & V3D_SHADING_XRAY) {
/* We need to call "GPU_select_*" API's inside DRW_draw_select_loop
* because the OpenGL context created & destroyed inside this function. */
struct DrawSelectLoopUserData drw_select_loop_user_data = {
@ -1036,14 +1020,34 @@ int view3d_opengl_select(
.rect = &rect,
.gpu_select_mode = gpu_select_mode,
};
draw_surface = false;
DRW_draw_select_loop(
depsgraph, ar, v3d,
use_obedit_skip, use_nearest, &rect,
use_obedit_skip, draw_surface, use_nearest, &rect,
drw_select_loop_pass, &drw_select_loop_user_data,
object_filter.fn, object_filter.user_data);
hits = drw_select_loop_user_data.hits;
}
if (hits == 0) {
/* We need to call "GPU_select_*" API's inside DRW_draw_select_loop
* because the OpenGL context created & destroyed inside this function. */
struct DrawSelectLoopUserData drw_select_loop_user_data = {
.pass = 0,
.hits = 0,
.buffer = buffer,
.buffer_len = bufsize,
.rect = &rect,
.gpu_select_mode = gpu_select_mode,
};
draw_surface = true;
DRW_draw_select_loop(
depsgraph, ar, v3d,
use_obedit_skip, draw_surface, use_nearest, &rect,
drw_select_loop_pass, &drw_select_loop_user_data,
object_filter.fn, object_filter.user_data);
hits = drw_select_loop_user_data.hits;
}
#endif /* WITH_OPENGL_LEGACY */
G.f &= ~G_PICKSEL;
ED_view3d_draw_setup_view(vc->win, depsgraph, scene, ar, v3d, vc->rv3d->viewmat, NULL, NULL);
@ -1055,9 +1059,7 @@ int view3d_opengl_select(
if (vc->rv3d->rflag & RV3D_CLIPPING)
ED_view3d_clipping_disable();
#ifndef WITH_OPENGL_LEGACY
DRW_opengl_context_disable();
#endif
finally: