diff options
author | mano-wii <germano.costa@ig.com.br> | 2019-03-15 22:02:55 +0300 |
---|---|---|
committer | mano-wii <germano.costa@ig.com.br> | 2019-03-15 23:02:48 +0300 |
commit | 681661dbed121c7b81e9129c57df5eadb03c1009 (patch) | |
tree | 8802195c72af13e1bb7324131024cc98fb5971a7 /source/blender | |
parent | 4510f88d00a721a3d4ad3aa675050723eec2292c (diff) |
GPU: Simplify select shaders.
The shaders are: `GPU_SHADER_3D_FLAT_SELECT_ID` and `GPU_SHADER_3D_UNIFORM_SELECT_ID`.
This commit allows the drawing of the mesh select ids to be done on a 32UI format texture.
This simplifies the shader that previously acted on the backbuffer and had to do an uint to rgba conversion.
Differential Revision: https://developer.blender.org/D4350
Diffstat (limited to 'source/blender')
23 files changed, 390 insertions, 468 deletions
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 655b1772130..e9bd8821d30 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7085,7 +7085,6 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype) rv3d->clipbb = newdataadr(fd, rv3d->clipbb); rv3d->depths = NULL; - rv3d->gpuoffscreen = NULL; rv3d->render_engine = NULL; rv3d->sms = NULL; rv3d->smooth_timer = NULL; diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index e261de3c900..68d4ef04f95 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -123,6 +123,10 @@ void DRW_draw_depth_loop( struct Depsgraph *depsgraph, struct ARegion *ar, struct View3D *v3d); +void DRW_framebuffer_select_id_setup(struct ARegion *ar, const bool clear); +void DRW_framebuffer_select_id_release(struct ARegion *ar); +void DRW_framebuffer_select_id_read(const struct rcti *rect, uint *r_buf); + /* grease pencil render */ bool DRW_render_check_grease_pencil(struct Depsgraph *depsgraph); void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph); diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index a34d2532bb5..fb30e4391e7 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -2015,20 +2015,26 @@ void DRW_custom_pipeline( } static struct DRWSelectBuffer { - struct GPUFrameBuffer *framebuffer; + struct GPUFrameBuffer *framebuffer_depth_only; + struct GPUFrameBuffer *framebuffer_select_id; struct GPUTexture *texture_depth; + struct GPUTexture *texture_u32; } g_select_buffer = {NULL}; -static void draw_select_framebuffer_setup(const rcti *rect) +static void draw_select_framebuffer_depth_only_setup(const rcti *rect) { - if (g_select_buffer.framebuffer == NULL) { - g_select_buffer.framebuffer = GPU_framebuffer_create(); + float size[2]; + size[0] = BLI_rcti_size_x(rect); + size[1] = BLI_rcti_size_y(rect); + + if (g_select_buffer.framebuffer_depth_only == NULL) { + g_select_buffer.framebuffer_depth_only = GPU_framebuffer_create(); + g_select_buffer.framebuffer_select_id = GPU_framebuffer_create(); } - /* If size mismatch recreate the texture. */ if ((g_select_buffer.texture_depth != NULL) && - ((GPU_texture_width(g_select_buffer.texture_depth) != BLI_rcti_size_x(rect)) || - (GPU_texture_height(g_select_buffer.texture_depth) != BLI_rcti_size_y(rect)))) + ((GPU_texture_width(g_select_buffer.texture_depth) != size[0]) || + (GPU_texture_height(g_select_buffer.texture_depth) != size[1]))) { GPU_texture_free(g_select_buffer.texture_depth); g_select_buffer.texture_depth = NULL; @@ -2036,13 +2042,50 @@ static void draw_select_framebuffer_setup(const rcti *rect) if (g_select_buffer.texture_depth == NULL) { g_select_buffer.texture_depth = GPU_texture_create_2D( - BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), GPU_DEPTH_COMPONENT24, NULL, NULL); + size[0], size[1], GPU_DEPTH_COMPONENT24, NULL, NULL); - GPU_framebuffer_texture_attach(g_select_buffer.framebuffer, g_select_buffer.texture_depth, 0, 0); + GPU_framebuffer_texture_attach( + g_select_buffer.framebuffer_depth_only, + g_select_buffer.texture_depth, 0, 0); - if (!GPU_framebuffer_check_valid(g_select_buffer.framebuffer, NULL)) { - printf("Error invalid selection framebuffer\n"); - } + GPU_framebuffer_texture_attach( + g_select_buffer.framebuffer_select_id, + g_select_buffer.texture_depth, 0, 0); + + GPU_framebuffer_check_valid( + g_select_buffer.framebuffer_depth_only, __func__); + + GPU_framebuffer_check_valid( + g_select_buffer.framebuffer_select_id, __func__); + } +} + +static void draw_select_framebuffer_select_id_setup(const rcti *rect) +{ + float size[2]; + size[0] = BLI_rcti_size_x(rect); + size[1] = BLI_rcti_size_y(rect); + + draw_select_framebuffer_depth_only_setup(rect); + + if ((g_select_buffer.texture_u32 != NULL) && + ((GPU_texture_width(g_select_buffer.texture_u32) != size[0]) || + (GPU_texture_height(g_select_buffer.texture_u32) != size[1]))) + { + GPU_texture_free(g_select_buffer.texture_u32); + g_select_buffer.texture_u32 = NULL; + } + + if (g_select_buffer.texture_u32 == NULL) { + g_select_buffer.texture_u32 = GPU_texture_create_2D( + size[0], size[1], GPU_R32UI, NULL, NULL); + + GPU_framebuffer_texture_attach( + g_select_buffer.framebuffer_select_id, + g_select_buffer.texture_u32, 0, 0); + + GPU_framebuffer_check_valid( + g_select_buffer.framebuffer_select_id, __func__); } } @@ -2209,9 +2252,9 @@ void DRW_draw_select_loop( } /* Setup framebuffer */ - draw_select_framebuffer_setup(rect); - GPU_framebuffer_bind(g_select_buffer.framebuffer); - GPU_framebuffer_clear_depth(g_select_buffer.framebuffer, 1.0f); + draw_select_framebuffer_depth_only_setup(rect); + GPU_framebuffer_bind(g_select_buffer.framebuffer_depth_only); + GPU_framebuffer_clear_depth(g_select_buffer.framebuffer_depth_only, 1.0f); /* Start Drawing */ DRW_state_reset(); @@ -2315,9 +2358,9 @@ void DRW_draw_depth_loop( GPU_viewport_size_set(viewport, (const int[2]){ar->winx, ar->winy}); /* Setup framebuffer */ - draw_select_framebuffer_setup(&ar->winrct); - GPU_framebuffer_bind(g_select_buffer.framebuffer); - GPU_framebuffer_clear_depth(g_select_buffer.framebuffer, 1.0f); + draw_select_framebuffer_depth_only_setup(&ar->winrct); + GPU_framebuffer_bind(g_select_buffer.framebuffer_depth_only); + GPU_framebuffer_clear_depth(g_select_buffer.framebuffer_depth_only, 1.0f); DST.viewport = viewport; DST.options.is_depth = true; @@ -2421,6 +2464,67 @@ void DRW_draw_depth_loop( GPU_matrix_pop_projection(); } + +/* Set an opengl context to be used with shaders that draw on U32 colors. */ +void DRW_framebuffer_select_id_setup(ARegion *ar, const bool clear) +{ + RegionView3D *rv3d = ar->regiondata; + + DRW_opengl_context_enable(); + + /* Setup framebuffer */ + draw_select_framebuffer_select_id_setup(&ar->winrct); + GPU_framebuffer_bind(g_select_buffer.framebuffer_select_id); + + /* dithering and AA break color coding, so disable */ + glDisable(GL_DITHER); + + GPU_depth_test(true); + + if (clear) { + GPU_framebuffer_clear_color_depth( + g_select_buffer.framebuffer_select_id, (const float[4]){0.0f}, 1.0f); + } + + if (rv3d->rflag & RV3D_CLIPPING) { + ED_view3d_clipping_set(rv3d); + } +} + + +/* Ends the context for selection and restoring the previous one. */ +void DRW_framebuffer_select_id_release(ARegion *ar) +{ + RegionView3D *rv3d = ar->regiondata; + + if (rv3d->rflag & RV3D_CLIPPING) { + ED_view3d_clipping_disable(); + } + + GPU_framebuffer_restore(); + + GPU_depth_test(false); + glEnable(GL_DITHER); + + DRW_opengl_context_disable(); +} + + +/* Read a block of pixels from the select frame buffer. */ +void DRW_framebuffer_select_id_read(const rcti *rect, uint *r_buf) +{ + DRW_opengl_context_enable(); + GPU_framebuffer_bind(g_select_buffer.framebuffer_select_id); + glReadBuffer(GL_COLOR_ATTACHMENT0); + + glReadPixels(rect->xmin, rect->ymin, + BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), + GL_RED_INTEGER, GL_UNSIGNED_INT, r_buf); + + GPU_framebuffer_restore(); + DRW_opengl_context_disable(); +} + /** \} */ @@ -2612,8 +2716,10 @@ void DRW_engines_free(void) DRW_opengl_context_enable(); + DRW_TEXTURE_FREE_SAFE(g_select_buffer.texture_u32); DRW_TEXTURE_FREE_SAFE(g_select_buffer.texture_depth); - GPU_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer); + GPU_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer_select_id); + GPU_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer_depth_only); DRW_hair_free(); DRW_shape_cache_free(); diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 7318df8adab..e8c5e0dd789 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -237,7 +237,7 @@ void EDBM_project_snap_verts(struct bContext *C, struct ARegion *ar, struct BMEd /* editface.c */ void paintface_flush_flags(struct bContext *C, struct Object *ob, short flag); bool paintface_mouse_select(struct bContext *C, struct Object *ob, const int mval[2], bool extend, bool deselect, bool toggle); -int do_paintface_box_select(struct ViewContext *vc, struct rcti *rect, int sel_op); +int do_paintface_box_select(struct ViewContext *vc, const struct rcti *rect, int sel_op); void paintface_deselect_all_visible(struct bContext *C, struct Object *ob, int action, bool flush_flags); void paintface_select_linked(struct bContext *C, struct Object *ob, const int mval[2], const bool select); bool paintface_minmax(struct Object *ob, float r_min[3], float r_max[3]); @@ -365,9 +365,9 @@ int *mesh_get_x_mirror_faces(struct Object *ob, struct BMEditMesh *em, struct Me int ED_mesh_mirror_get_vert(struct Object *ob, int index); -bool ED_mesh_pick_vert(struct bContext *C, struct Object *ob, const int mval[2], unsigned int *index, int size, bool use_zbuf); -bool ED_mesh_pick_face(struct bContext *C, struct Object *ob, const int mval[2], unsigned int *index, int size); -bool ED_mesh_pick_face_vert(struct bContext *C, struct Object *ob, const int mval[2], unsigned int *index, int size); +bool ED_mesh_pick_vert(struct bContext *C, struct Object *ob, const int mval[2], unsigned int *index, int dist_px, bool use_zbuf); +bool ED_mesh_pick_face(struct bContext *C, struct Object *ob, const int mval[2], unsigned int *index, int dist_px); +bool ED_mesh_pick_face_vert(struct bContext *C, struct Object *ob, const int mval[2], unsigned int *index, int dist_px); struct MDeformVert *ED_mesh_active_dvert_get_em(struct Object *ob, struct BMVert **r_eve); @@ -377,8 +377,8 @@ struct MDeformVert *ED_mesh_active_dvert_get_only(struct Object *ob); void EDBM_mesh_stats_multi(struct Object **objects, const uint objects_len, int totelem[3], int totelem_sel[3]); void EDBM_mesh_elem_index_ensure_multi(struct Object **objects, const uint objects_len, const char htype); -#define ED_MESH_PICK_DEFAULT_VERT_SIZE 50 -#define ED_MESH_PICK_DEFAULT_FACE_SIZE 3 +#define ED_MESH_PICK_DEFAULT_VERT_DIST 25 +#define ED_MESH_PICK_DEFAULT_FACE_DIST 1 #define USE_LOOPSLIDE_HACK diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 131069bfb5f..e8cd6ebf5f3 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -348,16 +348,24 @@ float ED_view3d_radius_to_dist( void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned pos); /* backbuffer select and draw support */ -void ED_view3d_backbuf_validate_with_select_mode(struct ViewContext *vc, short select_mode); -void ED_view3d_backbuf_validate(struct ViewContext *vc); -struct ImBuf *ED_view3d_backbuf_read( - struct ViewContext *vc, int xmin, int ymin, int xmax, int ymax); -unsigned int ED_view3d_backbuf_sample_rect( - struct ViewContext *vc, const int mval[2], int size, - unsigned int min, unsigned int max, float *r_dist); -int ED_view3d_backbuf_sample_size_clamp(struct ARegion *ar, const float dist); -unsigned int ED_view3d_backbuf_sample( +void ED_view3d_backbuf_depth_validate(struct ViewContext *vc); +int ED_view3d_backbuf_sample_size_clamp(struct ARegion *ar, const float dist); + +void ED_view3d_select_id_validate(struct ViewContext *vc); +void ED_view3d_select_id_validate_with_select_mode( + struct ViewContext *vc, short select_mode); + +uint ED_view3d_select_id_sample( struct ViewContext *vc, int x, int y); +uint *ED_view3d_select_id_read( + struct ViewContext *vc, + int xmin, int ymin, int xmax, int ymax, + uint *r_buf_len); +uint *ED_view3d_select_id_read_rect( + struct ViewContext *vc, const struct rcti *rect, uint *r_buf_len); +uint ED_view3d_select_id_read_nearest( + struct ViewContext *vc, const int mval[2], + const uint min, const uint max, uint *r_dist); bool ED_view3d_autodist( struct Depsgraph *depsgraph, struct ARegion *ar, struct View3D *v3d, diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index 5afde1b3ba1..e226985300c 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -272,7 +272,7 @@ void paintface_select_linked(bContext *C, Object *ob, const int mval[2], const b if (me == NULL || me->totpoly == 0) return; if (mval) { - if (!ED_mesh_pick_face(C, ob, mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) { + if (!ED_mesh_pick_face(C, ob, mval, &index, ED_MESH_PICK_DEFAULT_FACE_DIST)) { return; } } @@ -374,7 +374,7 @@ bool paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], b /* Get the face under the cursor */ me = BKE_mesh_from_object(ob); - if (!ED_mesh_pick_face(C, ob, mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) + if (!ED_mesh_pick_face(C, ob, mval, &index, ED_MESH_PICK_DEFAULT_FACE_DIST)) return false; if (index >= me->totpoly) @@ -418,22 +418,17 @@ bool paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], b return true; } -int do_paintface_box_select(ViewContext *vc, rcti *rect, int sel_op) +int do_paintface_box_select(ViewContext *vc, const rcti *rect, int sel_op) { Object *ob = vc->obact; Mesh *me; MPoly *mpoly; - struct ImBuf *ibuf; - unsigned int *rt; + uint *rt; char *selar; int a, index; - const int size[2] = { - BLI_rcti_size_x(rect) + 1, - BLI_rcti_size_y(rect) + 1}; me = BKE_mesh_from_object(ob); - - if ((me == NULL) || (me->totpoly == 0) || (size[0] * size[1] <= 0)) { + if ((me == NULL) || (me->totpoly == 0) || BLI_rcti_is_empty(rect)) { return OPERATOR_CANCELLED; } @@ -443,17 +438,12 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, int sel_op) paintface_deselect_all_visible(vc->C, vc->obact, SEL_DESELECT, false); } - ED_view3d_backbuf_validate(vc); + uint buf_len; + uint *buf = ED_view3d_select_id_read_rect(vc, rect, &buf_len); - ibuf = IMB_allocImBuf(size[0], size[1], 32, IB_rect); - rt = ibuf->rect; - view3d_opengl_read_pixels(vc->ar, rect->xmin, rect->ymin, size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); - if (ENDIAN_ORDER == B_ENDIAN) { - IMB_convert_rgba_to_abgr(ibuf); - } - GPU_select_to_index_array(ibuf->rect, size[0] * size[1]); + rt = buf; - a = size[0] * size[1]; + a = buf_len; while (a--) { if (*rt) { index = *rt; @@ -476,7 +466,7 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, int sel_op) } } - IMB_freeImBuf(ibuf); + MEM_freeN(buf); MEM_freeN(selar); #ifdef __APPLE__ diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 80d23f37e71..991e0f94383 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -213,32 +213,29 @@ bool EDBM_backbuf_border_init( ViewContext *vc, short xmin, short ymin, short xmax, short ymax) { - struct ImBuf *buf; - unsigned int *dr; - int a; + uint *buf, *dr, buf_len; if (vc->obedit == NULL || !V3D_IS_ZBUF(vc->v3d)) { return false; } - buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax); + buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, &buf_len); if ((buf == NULL) || (bm_vertoffs == 0)) { return false; } - dr = buf->rect; + dr = buf; /* build selection lookup */ selbuf = edbm_backbuf_alloc(bm_vertoffs + 1); - a = (xmax - xmin + 1) * (ymax - ymin + 1); - while (a--) { + while (buf_len--) { if (*dr > 0 && *dr <= bm_vertoffs) { BLI_BITMAP_ENABLE(selbuf, *dr); } dr++; } - IMB_freeImBuf(buf); + MEM_freeN(buf); return true; } @@ -286,9 +283,7 @@ static void edbm_mask_lasso_px_cb(int x, int x_end, int y, void *user_data) */ bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax) { - unsigned int *dr, *dr_mask, *dr_mask_arr; - struct ImBuf *buf; - int a; + uint *buf, *dr, *dr_mask, *dr_mask_arr, buf_len; struct LassoMaskData lasso_mask_data; /* method in use for face selecting too */ @@ -301,14 +296,14 @@ bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short return false; } - buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax); + buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, &buf_len); if ((buf == NULL) || (bm_vertoffs == 0)) { return false; } - dr = buf->rect; + dr = buf; - dr_mask = dr_mask_arr = MEM_callocN(sizeof(*dr_mask) * buf->x * buf->y, __func__); + dr_mask = dr_mask_arr = MEM_callocN(sizeof(*dr_mask) * buf_len, __func__); lasso_mask_data.px = dr_mask; lasso_mask_data.width = (xmax - xmin) + 1; @@ -320,14 +315,13 @@ bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short /* build selection lookup */ selbuf = edbm_backbuf_alloc(bm_vertoffs + 1); - a = (xmax - xmin + 1) * (ymax - ymin + 1); - while (a--) { + while (buf_len--) { if (*dr > 0 && *dr <= bm_vertoffs && *dr_mask == true) { BLI_BITMAP_ENABLE(selbuf, *dr); } dr++; dr_mask++; } - IMB_freeImBuf(buf); + MEM_freeN(buf); MEM_freeN(dr_mask_arr); return true; @@ -338,8 +332,7 @@ bool EDBM_backbuf_circle_init( ViewContext *vc, short xs, short ys, short rads) { - struct ImBuf *buf; - unsigned int *dr; + uint *buf, *dr; short xmin, ymin, xmax, ymax, xc, yc; int radsq; @@ -355,12 +348,12 @@ bool EDBM_backbuf_circle_init( xmin = xs - rads; xmax = xs + rads; ymin = ys - rads; ymax = ys + rads; - buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax); + buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, NULL); if ((buf == NULL) || (bm_vertoffs == 0)) { return false; } - dr = buf->rect; + dr = buf; /* build selection lookup */ selbuf = edbm_backbuf_alloc(bm_vertoffs + 1); @@ -375,7 +368,7 @@ bool EDBM_backbuf_circle_init( } } - IMB_freeImBuf(buf); + MEM_freeN(buf); return true; } @@ -472,26 +465,24 @@ BMVert *EDBM_vert_find_nearest_ex( BMesh *bm = vc->em->bm; if (V3D_IS_ZBUF(vc->v3d)) { - const int dist_px = ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist); - float dist_test; + uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist); unsigned int index; BMVert *eve; /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */ { FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_VERTEX); - ED_view3d_backbuf_validate_with_select_mode(vc, select_mode); + ED_view3d_select_id_validate_with_select_mode(vc, select_mode); - index = ED_view3d_backbuf_sample_rect( - vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &dist_test); + index = ED_view3d_select_id_read_nearest(vc, vc->mval, bm_wireoffs, 0xFFFFFF, &dist_px); eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL; FAKE_SELECT_MODE_END(vc, fake_select_mode); } if (eve) { - if (dist_test < *r_dist) { - *r_dist = dist_test; + if (dist_px < *r_dist) { + *r_dist = dist_px; return eve; } } @@ -665,17 +656,16 @@ BMEdge *EDBM_edge_find_nearest_ex( BMesh *bm = vc->em->bm; if (V3D_IS_ZBUF(vc->v3d)) { - const int dist_px = ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist); - float dist_test = 0.0f; + uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist); unsigned int index; BMEdge *eed; /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */ { FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_EDGE); - ED_view3d_backbuf_validate_with_select_mode(vc, select_mode); + ED_view3d_select_id_validate_with_select_mode(vc, select_mode); - index = ED_view3d_backbuf_sample_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &dist_test); + index = ED_view3d_select_id_read_nearest(vc, vc->mval, bm_solidoffs, bm_wireoffs, &dist_px); eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL; FAKE_SELECT_MODE_END(vc, fake_select_mode); @@ -703,8 +693,8 @@ BMEdge *EDBM_edge_find_nearest_ex( /* end exception */ if (eed) { - if (dist_test < *r_dist) { - *r_dist = dist_test; + if (dist_px < *r_dist) { + *r_dist = dist_px; return eed; } } @@ -842,9 +832,9 @@ BMFace *EDBM_face_find_nearest_ex( { FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_FACE); - ED_view3d_backbuf_validate_with_select_mode(vc, select_mode); + ED_view3d_select_id_validate_with_select_mode(vc, select_mode); - index = ED_view3d_backbuf_sample(vc, vc->mval[0], vc->mval[1]); + index = ED_view3d_select_id_sample(vc, vc->mval[0], vc->mval[1]); efa = index ? BM_face_at_index_find_or_table(bm, index - 1) : NULL; FAKE_SELECT_MODE_END(vc, fake_select_mode); @@ -974,7 +964,6 @@ static bool unified_findnearest( Object *obedit = base_iter->object; ED_view3d_viewcontext_init_object(vc, obedit); BLI_assert(vc->em->selectmode == em->selectmode); - ED_view3d_backbuf_validate(vc); BMFace *efa_zbuf = NULL; BMFace *efa_test = EDBM_face_find_nearest_ex(vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf); if (efa_test && dist_center_p) { @@ -999,7 +988,6 @@ static bool unified_findnearest( Base *base_iter = bases[base_index]; Object *obedit = base_iter->object; ED_view3d_viewcontext_init_object(vc, obedit); - ED_view3d_backbuf_validate(vc); BMEdge *eed_zbuf = NULL; BMEdge *eed_test = EDBM_edge_find_nearest_ex(vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf); if (eed_test && dist_center_p) { @@ -1021,7 +1009,6 @@ static bool unified_findnearest( Base *base_iter = bases[base_index]; Object *obedit = base_iter->object; ED_view3d_viewcontext_init_object(vc, obedit); - ED_view3d_backbuf_validate(vc); BMVert *eve_test = EDBM_vert_find_nearest_ex(vc, &dist, true, use_cycle); if (eve_test) { hit.v.base_index = base_index; diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index 2b8535f868b..952690775b7 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -1014,7 +1014,7 @@ int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, Mesh *me_eval) * * \return boolean true == Found */ -bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], unsigned int *index, int size) +bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], unsigned int *index, int dist_px) { ViewContext vc; Mesh *me = ob->data; @@ -1026,16 +1026,18 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], unsigned int ED_view3d_viewcontext_init(C, &vc); - if (size) { + if (dist_px) { /* sample rect to increase chances of selecting, so that when clicking * on an edge in the backbuf, we can still select a face */ - float dummy_dist; - *index = ED_view3d_backbuf_sample_rect(&vc, mval, size, 1, me->totpoly + 1, &dummy_dist); + ED_view3d_select_id_validate(&vc); + + *index = ED_view3d_select_id_read_nearest( + &vc, mval, 1, me->totpoly + 1, &dist_px); } else { /* sample only on the exact position */ - *index = ED_view3d_backbuf_sample(&vc, mval[0], mval[1]); + *index = ED_view3d_select_id_sample(&vc, mval[0], mval[1]); } if ((*index) == 0 || (*index) > (unsigned int)me->totpoly) @@ -1045,6 +1047,7 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], unsigned int return true; } + static void ed_mesh_pick_face_vert__mpoly_find( /* context */ struct ARegion *ar, const float mval[2], @@ -1073,7 +1076,7 @@ static void ed_mesh_pick_face_vert__mpoly_find( * Use when the back buffer stores face index values. but we want a vert. * This gets the face then finds the closest vertex to mval. */ -bool ED_mesh_pick_face_vert(bContext *C, Object *ob, const int mval[2], unsigned int *index, int size) +bool ED_mesh_pick_face_vert(bContext *C, Object *ob, const int mval[2], unsigned int *index, int dist_px) { Depsgraph *depsgraph = CTX_data_depsgraph(C); unsigned int poly_index; @@ -1081,7 +1084,7 @@ bool ED_mesh_pick_face_vert(bContext *C, Object *ob, const int mval[2], unsigned BLI_assert(me && GS(me->id.name) == ID_ME); - if (ED_mesh_pick_face(C, ob, mval, &poly_index, size)) { + if (ED_mesh_pick_face(C, ob, mval, &poly_index, dist_px)) { Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); struct ARegion *ar = CTX_wm_region(C); @@ -1181,7 +1184,7 @@ static void ed_mesh_pick_vert__mapFunc(void *userData, int index, const float co } } } -bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int *index, int size, bool use_zbuf) +bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int *index, int dist_px, bool use_zbuf) { ViewContext vc; Mesh *me = ob->data; @@ -1194,16 +1197,18 @@ bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int ED_view3d_viewcontext_init(C, &vc); if (use_zbuf) { - if (size > 0) { + if (dist_px > 0) { /* sample rect to increase chances of selecting, so that when clicking * on an face in the backbuf, we can still select a vert */ - float dummy_dist; - *index = ED_view3d_backbuf_sample_rect(&vc, mval, size, 1, me->totvert + 1, &dummy_dist); + ED_view3d_select_id_validate(&vc); + + *index = ED_view3d_select_id_read_nearest( + &vc, mval, 1, me->totvert + 1, &dist_px); } else { /* sample only on the exact position */ - *index = ED_view3d_backbuf_sample(&vc, mval[0], mval[1]); + *index = ED_view3d_select_id_sample(&vc, mval[0], mval[1]); } if ((*index) == 0 || (*index) > (unsigned int)me->totvert) diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 0b63d7455f2..97f191a217a 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -451,7 +451,7 @@ static void PE_set_view3d_data(bContext *C, PEData *data) /* needed or else the draw matrix can be incorrect */ view3d_operator_needs_opengl(C); - ED_view3d_backbuf_validate(&data->vc); + ED_view3d_backbuf_depth_validate(&data->vc); /* we may need to force an update here by setting the rv3d as dirty * for now it seems ok, but take care!: * rv3d->depths->dirty = 1; */ diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index b8c067d61e7..7de8e6bb07f 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -362,7 +362,7 @@ static int imapaint_pick_face( return 0; /* sample only on the exact position */ - *r_index = ED_view3d_backbuf_sample(vc, mval[0], mval[1]); + *r_index = ED_view3d_select_id_sample(vc, mval[0], mval[1]); if ((*r_index) == 0 || (*r_index) > (unsigned int)totpoly) { return 0; diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c index aa3f424f816..24a26676df3 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c @@ -188,15 +188,15 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *even ED_view3d_init_mats_rv3d(vc.obact, vc.rv3d); if (use_vert_sel) { - if (ED_mesh_pick_vert(C, vc.obact, event->mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE, true)) { + if (ED_mesh_pick_vert(C, vc.obact, event->mval, &index, ED_MESH_PICK_DEFAULT_VERT_DIST, true)) { v_idx_best = index; } } else { - if (ED_mesh_pick_face_vert(C, vc.obact, event->mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) { + if (ED_mesh_pick_face_vert(C, vc.obact, event->mval, &index, ED_MESH_PICK_DEFAULT_FACE_DIST)) { v_idx_best = index; } - else if (ED_mesh_pick_face(C, vc.obact, event->mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) { + else if (ED_mesh_pick_face(C, vc.obact, event->mval, &index, ED_MESH_PICK_DEFAULT_FACE_DIST)) { /* this relies on knowning the internal worksings of ED_mesh_pick_face_vert() */ BKE_report(op->reports, RPT_WARNING, "The modifier used does not support deformed locations"); } @@ -312,13 +312,13 @@ static const EnumPropertyItem *weight_paint_sample_enum_itemf( ED_view3d_init_mats_rv3d(vc.obact, vc.rv3d); if (use_vert_sel) { - if (ED_mesh_pick_vert(C, vc.obact, mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE, true)) { + if (ED_mesh_pick_vert(C, vc.obact, mval, &index, ED_MESH_PICK_DEFAULT_VERT_DIST, true)) { MDeformVert *dvert = &me->dvert[index]; found |= weight_paint_sample_enum_itemf__helper(dvert, defbase_tot, groups); } } else { - if (ED_mesh_pick_face(C, vc.obact, mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) { + if (ED_mesh_pick_face(C, vc.obact, mval, &index, ED_MESH_PICK_DEFAULT_FACE_DIST)) { const MPoly *mp = &me->mpoly[index]; uint fidx = mp->totloop - 1; diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index e6e0438164c..b976c231841 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -47,6 +47,8 @@ #include "UI_resources.h" +#include "DRW_engine.h" + #include "view3d_intern.h" /* bad level include */ #include "../../draw/intern/draw_cache_impl.h" /* bad level include (temporary) */ @@ -281,7 +283,7 @@ static void bbs_mesh_solid_faces(Scene *UNUSED(scene), Object *ob, const float w bbs_mesh_face(geom_faces, true, world_clip_planes); } -void draw_object_backbufsel( +void draw_object_select_id( Depsgraph *depsgraph, Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, short select_mode) { @@ -380,6 +382,52 @@ void draw_object_backbufsel( GPU_matrix_set(rv3d->viewmat); } +void draw_object_depth(RegionView3D *rv3d, Object *ob) +{ + GPU_matrix_mul(ob->obmat); + GPU_depth_test(true); + + const float (*world_clip_planes)[4] = NULL; + if (rv3d->rflag & RV3D_CLIPPING) { + ED_view3d_clipping_local(rv3d, ob->obmat); + world_clip_planes = rv3d->clip_local; + } + + switch (ob->type) { + case OB_MESH: + { + GPUBatch *batch; + + Mesh *me = ob->data; + + if (ob->mode & OB_MODE_EDIT) { + batch = DRW_mesh_batch_cache_get_edit_triangles(me); + } + else { + batch = DRW_mesh_batch_cache_get_surface(me); + } + + DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true); + + DRW_opengl_context_enable(); + const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : GPU_SHADER_CFG_DEFAULT; + GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_DEPTH_ONLY, sh_cfg); + if (world_clip_planes != NULL) { + bbs_world_clip_planes_from_rv3d(batch, world_clip_planes); + } + + GPU_batch_draw(batch); + DRW_opengl_context_disable(); + } + break; + case OB_CURVE: + case OB_SURF: + break; + } + + GPU_matrix_set(rv3d->viewmat); +} + void ED_draw_object_facemap( Depsgraph *depsgraph, Object *ob, const float col[4], const int facemap) diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index ca18a96c253..25cc8854607 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -536,11 +536,6 @@ static void view3d_main_region_exit(wmWindowManager *wm, ARegion *ar) RegionView3D *rv3d = ar->regiondata; ED_view3d_stop_render_preview(wm, ar); - - if (rv3d->gpuoffscreen) { - GPU_offscreen_free(rv3d->gpuoffscreen); - rv3d->gpuoffscreen = NULL; - } } static bool view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip)) @@ -729,9 +724,6 @@ static void view3d_main_region_free(ARegion *ar) if (rv3d->sms) { MEM_freeN(rv3d->sms); } - if (rv3d->gpuoffscreen) { - GPU_offscreen_free(rv3d->gpuoffscreen); - } MEM_freeN(rv3d); ar->regiondata = NULL; @@ -751,7 +743,6 @@ static void *view3d_main_region_duplicate(void *poin) new->clipbb = MEM_dupallocN(rv3d->clipbb); new->depths = NULL; - new->gpuoffscreen = NULL; new->render_engine = NULL; new->sms = NULL; new->smooth_timer = NULL; diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c index a52fd89d284..eed6fc31235 100644 --- a/source/blender/editors/space_view3d/view3d_draw_legacy.c +++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c @@ -149,7 +149,7 @@ void ED_view3d_clipping_enable(void) /* *********************** backdraw for selection *************** */ -static void backdrawview3d( +static void validate_object_select_id( struct Depsgraph *depsgraph, Scene *scene, ARegion *ar, View3D *v3d, Object *obact, Object *obedit, @@ -203,81 +203,24 @@ static void backdrawview3d( if (v3d->shading.type > OB_WIRE) v3d->zbuf = true; #endif - /* dithering and AA break color coding, so disable */ - glDisable(GL_DITHER); - - if (false) { - /* for multisample we use an offscreen FBO. multisample drawing can fail - * with color coded selection drawing, and reading back depths from such - * a buffer can also cause a few seconds freeze on OS X / NVidia. - * - * NOTE: code is no longer used now, but offscreen drawing is likely - * what we will always want to do for the new viewport. */ - int w = BLI_rcti_size_x(&ar->winrct); - int h = BLI_rcti_size_y(&ar->winrct); - char error[256]; - - if (rv3d->gpuoffscreen) { - if (GPU_offscreen_width(rv3d->gpuoffscreen) != w || - GPU_offscreen_height(rv3d->gpuoffscreen) != h) - { - GPU_offscreen_free(rv3d->gpuoffscreen); - rv3d->gpuoffscreen = NULL; - } - } - - if (!rv3d->gpuoffscreen) { - rv3d->gpuoffscreen = GPU_offscreen_create(w, h, 0, true, false, error); - - if (!rv3d->gpuoffscreen) - fprintf(stderr, "Failed to create offscreen selection buffer for multisample: %s\n", error); - } - } - - if (rv3d->gpuoffscreen) - GPU_offscreen_bind(rv3d->gpuoffscreen, true); - else - GPU_scissor(ar->winrct.xmin, ar->winrct.ymin, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct)); - - GPU_clear_color(0.0, 0.0, 0.0, 0.0); - GPU_depth_test(true); - GPU_clear(GPU_COLOR_BIT | GPU_DEPTH_BIT); - - if (rv3d->rflag & RV3D_CLIPPING) - ED_view3d_clipping_set(rv3d); - G.f |= G_FLAG_BACKBUFSEL; if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE) != 0)) { - draw_object_backbufsel(depsgraph, scene_eval, v3d, rv3d, obact_eval, select_mode); + DRW_framebuffer_select_id_setup(ar, true); + draw_object_select_id(depsgraph, scene_eval, v3d, rv3d, obact_eval, select_mode); + DRW_framebuffer_select_id_release(ar); } - if (rv3d->gpuoffscreen) - GPU_offscreen_unbind(rv3d->gpuoffscreen, true); - + /* TODO: Create a flag in `DRW_manager` because the drawing is no longer + * made on the backbuffer in this case. */ v3d->flag &= ~V3D_INVALID_BACKBUF; G.f &= ~G_FLAG_BACKBUFSEL; - GPU_depth_test(false); - glEnable(GL_DITHER); - - if (rv3d->rflag & RV3D_CLIPPING) - ED_view3d_clipping_disable(); } void view3d_opengl_read_pixels(ARegion *ar, int x, int y, int w, int h, int format, int type, void *data) { - RegionView3D *rv3d = ar->regiondata; - - if (rv3d->gpuoffscreen) { - GPU_offscreen_bind(rv3d->gpuoffscreen, true); - glReadBuffer(GL_COLOR_ATTACHMENT0); - glReadPixels(x, y, w, h, format, type, data); - GPU_offscreen_unbind(rv3d->gpuoffscreen, true); - } - else { - glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data); - } + glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data); } /* XXX depth reading exception, for code not using gpu offscreen */ @@ -286,16 +229,70 @@ static void view3d_opengl_read_Z_pixels(ARegion *ar, int x, int y, int w, int h, glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data); } -void ED_view3d_backbuf_validate_with_select_mode(ViewContext *vc, short select_mode) +void ED_view3d_select_id_validate_with_select_mode(ViewContext *vc, short select_mode) { + /* TODO: Create a flag in `DRW_manager` because the drawing is no longer + * made on the backbuffer in this case. */ if (vc->v3d->flag & V3D_INVALID_BACKBUF) { - backdrawview3d(vc->depsgraph, vc->scene, vc->ar, vc->v3d, vc->obact, vc->obedit, select_mode); + validate_object_select_id( + vc->depsgraph, vc->scene, vc->ar, vc->v3d, + vc->obact, vc->obedit, select_mode); + } +} + +void ED_view3d_select_id_validate(ViewContext *vc) +{ + ED_view3d_select_id_validate_with_select_mode(vc, -1); +} + +void ED_view3d_backbuf_depth_validate(ViewContext *vc) +{ + if (vc->v3d->flag & V3D_INVALID_BACKBUF) { + ARegion *ar = vc->ar; + RegionView3D *rv3d = ar->regiondata; + Object *obact_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact); + + if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE) != 0)) { + GPU_scissor(ar->winrct.xmin, ar->winrct.ymin, + BLI_rcti_size_x(&ar->winrct), + BLI_rcti_size_y(&ar->winrct)); + + GPU_depth_test(true); + GPU_clear(GPU_DEPTH_BIT); + + if (rv3d->rflag & RV3D_CLIPPING) { + ED_view3d_clipping_set(rv3d); + } + + draw_object_depth(rv3d, obact_eval); + + if (rv3d->rflag & RV3D_CLIPPING) { + ED_view3d_clipping_disable(rv3d); + } + + GPU_depth_test(false); + } + + vc->v3d->flag &= ~V3D_INVALID_BACKBUF; } } -void ED_view3d_backbuf_validate(ViewContext *vc) +uint *ED_view3d_select_id_read_rect(ViewContext *vc, const rcti *clip, uint *r_buf_len) { - ED_view3d_backbuf_validate_with_select_mode(vc, -1); + ED_view3d_select_id_validate(vc); + + uint width = BLI_rcti_size_x(clip); + uint height = BLI_rcti_size_y(clip); + uint buf_len = width * height; + uint *buf = MEM_mallocN(buf_len * sizeof(*buf), __func__); + + DRW_framebuffer_select_id_read(clip, buf); + + if (r_buf_len) { + *r_buf_len = buf_len; + } + + return buf; } /** @@ -308,111 +305,81 @@ int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist) } /* samples a single pixel (copied from vpaint) */ -uint ED_view3d_backbuf_sample( +uint ED_view3d_select_id_sample( ViewContext *vc, int x, int y) { if (x >= vc->ar->winx || y >= vc->ar->winy) { return 0; } - ED_view3d_backbuf_validate(vc); - - uint col; - view3d_opengl_read_pixels(vc->ar, x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col); - glReadBuffer(GL_BACK); + uint buf_len; + uint *buf = ED_view3d_select_id_read(vc, x, y, x, y, &buf_len); + BLI_assert(0 != buf_len); + uint ret = buf[0]; + MEM_freeN(buf); - if (ENDIAN_ORDER == B_ENDIAN) { - BLI_endian_switch_uint32(&col); - } - - return GPU_select_to_index(col); + return ret; } /* reads full rect, converts indices */ -ImBuf *ED_view3d_backbuf_read( - ViewContext *vc, int xmin, int ymin, int xmax, int ymax) +uint *ED_view3d_select_id_read( + ViewContext *vc, int xmin, int ymin, int xmax, int ymax, uint *r_buf_len) { - /* clip */ - const rcti clip = { - max_ii(xmin, 0), min_ii(xmax, vc->ar->winx - 1), - max_ii(ymin, 0), min_ii(ymax, vc->ar->winy - 1)}; - const int size_clip[2] = { - BLI_rcti_size_x(&clip) + 1, - BLI_rcti_size_y(&clip) + 1}; - - if (UNLIKELY((clip.xmin > clip.xmax) || - (clip.ymin > clip.ymax))) - { + if (UNLIKELY((xmin > xmax) || (ymin > ymax))) { return NULL; } - ImBuf *ibuf_clip = IMB_allocImBuf(size_clip[0], size_clip[1], 32, IB_rect); - - ED_view3d_backbuf_validate(vc); - - view3d_opengl_read_pixels(vc->ar, clip.xmin, clip.ymin, size_clip[0], size_clip[1], GL_RGBA, GL_UNSIGNED_BYTE, ibuf_clip->rect); + const rcti rect = { + .xmin = xmin, .xmax = xmax + 1, + .ymin = ymin, .ymax = ymax + 1, + }; - glReadBuffer(GL_BACK); + uint buf_len; + uint *buf = ED_view3d_select_id_read_rect(vc, &rect, &buf_len); - if (ENDIAN_ORDER == B_ENDIAN) { - IMB_convert_rgba_to_abgr(ibuf_clip); + if (r_buf_len) { + *r_buf_len = buf_len; } - GPU_select_to_index_array(ibuf_clip->rect, size_clip[0] * size_clip[1]); - - if ((clip.xmin == xmin) && - (clip.xmax == xmax) && - (clip.ymin == ymin) && - (clip.ymax == ymax)) - { - return ibuf_clip; - } - else { - /* put clipped result into a non-clipped buffer */ - const int size[2] = { - (xmax - xmin + 1), - (ymax - ymin + 1)}; - - ImBuf *ibuf_full = IMB_allocImBuf(size[0], size[1], 32, IB_rect); - - IMB_rectcpy( - ibuf_full, ibuf_clip, - clip.xmin - xmin, clip.ymin - ymin, - 0, 0, - size_clip[0], size_clip[1]); - IMB_freeImBuf(ibuf_clip); - return ibuf_full; - } + return buf; } /* smart function to sample a rect spiralling outside, nice for backbuf selection */ -uint ED_view3d_backbuf_sample_rect( - ViewContext *vc, const int mval[2], int size, - uint min, uint max, float *r_dist) +uint ED_view3d_select_id_read_nearest( + struct ViewContext *vc, const int mval[2], + const uint min, const uint max, uint *r_dist) { + uint index = 0; + int dirvec[4][2]; - const int amount = (size - 1) / 2; + rcti rect; + BLI_rcti_init_pt_radius(&rect, mval, *r_dist); + rect.xmax += 1; + rect.ymax += 1; + + uint width, height; + width = height = BLI_rcti_size_x(&rect); + + uint buf_len = width * height; + uint *buf = MEM_mallocN(buf_len * sizeof(*buf), __func__); + + DRW_framebuffer_select_id_read(&rect, buf); - const int minx = mval[0] - (amount + 1); - const int miny = mval[1] - (amount + 1); - ImBuf *buf = ED_view3d_backbuf_read(vc, minx, miny, minx + size - 1, miny + size - 1); - if (!buf) return 0; + BLI_assert(width == height); /* This algorithm doesn't work well with rectangles */ - unsigned index = 0; int rc = 0; dirvec[0][0] = 1; dirvec[0][1] = 0; - dirvec[1][0] = 0; dirvec[1][1] = -size; + dirvec[1][0] = 0; dirvec[1][1] = -height; dirvec[2][0] = -1; dirvec[2][1] = 0; - dirvec[3][0] = 0; dirvec[3][1] = size; + dirvec[3][0] = 0; dirvec[3][1] = height; - const unsigned *bufmin = buf->rect; - const unsigned *tbuf = buf->rect; - const unsigned *bufmax = buf->rect + size * size; - tbuf += amount * size + amount; + const uint *bufmin = buf; + const uint *bufmax = buf + buf_len; + const uint *tbuf = buf + (height * (int)(width / 2) + height / 2 - 1); - for (int nr = 1; nr <= size; nr++) { + for (int nr = 1; nr <= height; nr++) { for (int a = 0; a < 2; a++) { for (int b = 0; b < nr; b++) { if (*tbuf && *tbuf >= min && *tbuf < max) { @@ -421,8 +388,8 @@ uint ED_view3d_backbuf_sample_rect( /* get x,y pixel coords from the offset * (manhatten distance in keeping with other screen-based selection) */ *r_dist = (float)( - abs(((int)(tbuf - buf->rect) % size) - (size / 2)) + - abs(((int)(tbuf - buf->rect) / size) - (size / 2))); + abs(((int)(tbuf - buf) % height) - (height / 2)) + + abs(((int)(tbuf - buf) / height) - (height / 2))); /* indices start at 1 here */ index = (*tbuf - min) + 1; @@ -441,7 +408,7 @@ uint ED_view3d_backbuf_sample_rect( } exit: - IMB_freeImBuf(buf); + MEM_freeN(buf); return index; } diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index bb6b96b96d5..e85558765b6 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -123,11 +123,13 @@ void VIEW3D_OT_fly(struct wmOperatorType *ot); void VIEW3D_OT_walk(struct wmOperatorType *ot); /* drawobject.c */ -void draw_object_backbufsel( +void draw_object_select_id( struct Depsgraph *depsgraph, Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob, short select_mode); +void draw_object_depth(RegionView3D *rv3d, struct Object *ob); + int view3d_effective_drawtype(const struct View3D *v3d); /* view3d_draw.c */ diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index fc13968def7..02d469bfa73 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -1924,7 +1924,7 @@ static bool ed_wpaint_vertex_select_pick( uint index = 0; MVert *mv; - if (ED_mesh_pick_vert(C, obact, mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE, use_zbuf)) { + if (ED_mesh_pick_vert(C, obact, mval, &index, ED_MESH_PICK_DEFAULT_VERT_DIST, use_zbuf)) { mv = &me->mvert[index]; if (extend) { mv->flag |= SELECT; @@ -2112,22 +2112,17 @@ static void do_paintvert_box_select__doSelectVert(void *userData, MVert *mv, con } } static int do_paintvert_box_select( - ViewContext *vc, rcti *rect, const eSelectOp sel_op) + ViewContext *vc, const rcti *rect, const eSelectOp sel_op) { const bool use_zbuf = V3D_IS_ZBUF(vc->v3d); Mesh *me; MVert *mvert; - struct ImBuf *ibuf; - uint *rt; + unsigned int *rt; int a, index; char *selar; - const int size[2] = { - BLI_rcti_size_x(rect) + 1, - BLI_rcti_size_y(rect) + 1}; me = vc->obact->data; - - if ((me == NULL) || (me->totvert == 0) || (size[0] * size[1] <= 0)) { + if ((me == NULL) || (me->totvert == 0) || BLI_rcti_is_empty(rect)) { return OPERATOR_CANCELLED; } @@ -2137,20 +2132,13 @@ static int do_paintvert_box_select( if (use_zbuf) { selar = MEM_callocN(me->totvert + 1, "selar"); - ED_view3d_backbuf_validate(vc); - ibuf = IMB_allocImBuf(size[0], size[1], 32, IB_rect); - rt = ibuf->rect; - glReadPixels( - rect->xmin + vc->ar->winrct.xmin, - rect->ymin + vc->ar->winrct.ymin, - size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); - if (ENDIAN_ORDER == B_ENDIAN) { - IMB_convert_rgba_to_abgr(ibuf); - } - GPU_select_to_index_array(ibuf->rect, size[0] * size[1]); + uint buf_len; + uint *buf = ED_view3d_select_id_read_rect(vc, rect, &buf_len); + + rt = buf; - a = size[0] * size[1]; + a = buf_len; while (a--) { if (*rt) { index = *rt; @@ -2173,7 +2161,7 @@ static int do_paintvert_box_select( } } - IMB_freeImBuf(ibuf); + MEM_freeN(buf); MEM_freeN(selar); #ifdef __APPLE__ diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index f9ea9a35084..ce9a20bcf7c 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -99,11 +99,6 @@ void GPU_create_smoke_velocity(struct SmokeModifierData *smd); void GPU_free_unused_buffers(struct Main *bmain); /* utilities */ -void GPU_select_index_set(int index); -void GPU_select_index_get(int index, int *r_col); -int GPU_select_to_index(unsigned int col); -void GPU_select_to_index_array(unsigned int *col, const unsigned int size); - typedef enum eGPUAttrMask { GPU_DEPTH_BUFFER_BIT = (1 << 0), GPU_ENABLE_BIT = (1 << 1), diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h index 3154119592d..b656bb74d4b 100644 --- a/source/blender/gpu/GPU_extensions.h +++ b/source/blender/gpu/GPU_extensions.h @@ -42,7 +42,6 @@ int GPU_max_cube_map_size(void); int GPU_max_ubo_binds(void); int GPU_max_ubo_size(void); float GPU_max_line_width(void); -int GPU_color_depth(void); void GPU_get_dfdy_factors(float fac[2]); bool GPU_mip_render_workaround(void); bool GPU_depth_blitting_workaround(void); diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 62dcbb94d1c..d91ea234931 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -1275,148 +1275,6 @@ void GPU_disable_program_point_size(void) /** \name Framebuffer color depth, for selection codes * \{ */ -#ifdef __APPLE__ - -/* apple seems to round colors to below and up on some configs */ - -static uint index_to_framebuffer(int index) -{ - uint i = index; - - switch (GPU_color_depth()) { - case 12: - i = ((i & 0xF00) << 12) + ((i & 0xF0) << 8) + ((i & 0xF) << 4); - /* sometimes dithering subtracts! */ - i |= 0x070707; - break; - case 15: - case 16: - i = ((i & 0x7C00) << 9) + ((i & 0x3E0) << 6) + ((i & 0x1F) << 3); - i |= 0x030303; - break; - case 24: - break; - default: /* 18 bits... */ - i = ((i & 0x3F000) << 6) + ((i & 0xFC0) << 4) + ((i & 0x3F) << 2); - i |= 0x010101; - break; - } - - return i; -} - -#else - -/* this is the old method as being in use for ages.... seems to work? colors are rounded to lower values */ - -static uint index_to_framebuffer(int index) -{ - uint i = index; - - switch (GPU_color_depth()) { - case 8: - i = ((i & 48) << 18) + ((i & 12) << 12) + ((i & 3) << 6); - i |= 0x3F3F3F; - break; - case 12: - i = ((i & 0xF00) << 12) + ((i & 0xF0) << 8) + ((i & 0xF) << 4); - /* sometimes dithering subtracts! */ - i |= 0x0F0F0F; - break; - case 15: - case 16: - i = ((i & 0x7C00) << 9) + ((i & 0x3E0) << 6) + ((i & 0x1F) << 3); - i |= 0x070707; - break; - case 24: - break; - default: /* 18 bits... */ - i = ((i & 0x3F000) << 6) + ((i & 0xFC0) << 4) + ((i & 0x3F) << 2); - i |= 0x030303; - break; - } - - return i; -} - -#endif - - -void GPU_select_index_set(int index) -{ - const int col = index_to_framebuffer(index); - glColor3ub(( (col) & 0xFF), - (((col) >> 8) & 0xFF), - (((col) >> 16) & 0xFF)); -} - -void GPU_select_index_get(int index, int *r_col) -{ - const int col = index_to_framebuffer(index); - char *c_col = (char *)r_col; - c_col[0] = (col & 0xFF); /* red */ - c_col[1] = ((col >> 8) & 0xFF); /* green */ - c_col[2] = ((col >> 16) & 0xFF); /* blue */ - c_col[3] = 0xFF; /* alpha */ -} - - -#define INDEX_FROM_BUF_8(col) ((((col) & 0xC00000) >> 18) + (((col) & 0xC000) >> 12) + (((col) & 0xC0) >> 6)) -#define INDEX_FROM_BUF_12(col) ((((col) & 0xF00000) >> 12) + (((col) & 0xF000) >> 8) + (((col) & 0xF0) >> 4)) -#define INDEX_FROM_BUF_15_16(col) ((((col) & 0xF80000) >> 9) + (((col) & 0xF800) >> 6) + (((col) & 0xF8) >> 3)) -#define INDEX_FROM_BUF_18(col) ((((col) & 0xFC0000) >> 6) + (((col) & 0xFC00) >> 4) + (((col) & 0xFC) >> 2)) -#define INDEX_FROM_BUF_24(col) ((col) & 0xFFFFFF) - -int GPU_select_to_index(uint col) -{ - if (col == 0) { - return 0; - } - - switch (GPU_color_depth()) { - case 8: return INDEX_FROM_BUF_8(col); - case 12: return INDEX_FROM_BUF_12(col); - case 15: - case 16: return INDEX_FROM_BUF_15_16(col); - case 24: return INDEX_FROM_BUF_24(col); - default: return INDEX_FROM_BUF_18(col); - } -} - -void GPU_select_to_index_array(uint *col, const uint size) -{ -#define INDEX_BUF_ARRAY(INDEX_FROM_BUF_BITS) \ - for (i = size; i--; col++) { \ - if ((c = *col)) { \ - *col = INDEX_FROM_BUF_BITS(c); \ - } \ - } ((void)0) - - if (size > 0) { - uint i, c; - - switch (GPU_color_depth()) { - case 8: - INDEX_BUF_ARRAY(INDEX_FROM_BUF_8); - break; - case 12: - INDEX_BUF_ARRAY(INDEX_FROM_BUF_12); - break; - case 15: - case 16: - INDEX_BUF_ARRAY(INDEX_FROM_BUF_15_16); - break; - case 24: - INDEX_BUF_ARRAY(INDEX_FROM_BUF_24); - break; - default: - INDEX_BUF_ARRAY(INDEX_FROM_BUF_18); - break; - } - } - -#undef INDEX_BUF_ARRAY -} #define STATE_STACK_DEPTH 16 diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index 6fb40b06177..282b9dfc388 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -67,7 +67,6 @@ static struct GPUGlobal { GLint maxtexturesvert; GLint maxubosize; GLint maxubobinds; - int colordepth; int samples_color_texture_max; eGPUDeviceType device; eGPUOSType os; @@ -252,12 +251,6 @@ void gpu_extensions_init(void) BLI_assert(ret == GL_FRAMEBUFFER_DEFAULT); #endif - GLint r, g, b; - glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, &r); - glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE, &g); - glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE, &b); - GG.colordepth = r + g + b; /* Assumes same depth for RGB. */ - glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &GG.samples_color_texture_max); const char *vendor = (const char *)glGetString(GL_VENDOR); @@ -402,11 +395,6 @@ void gpu_extensions_exit(void) GPU_invalid_tex_free(); } -int GPU_color_depth(void) -{ - return GG.colordepth; -} - bool GPU_mem_stats_supported(void) { return (GLEW_NVX_gpu_memory_info || GLEW_ATI_meminfo) && (G.debug & G_DEBUG_GPU_MEM); diff --git a/source/blender/gpu/shaders/gpu_shader_3D_selection_id_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_selection_id_vert.glsl index b2d186efa91..bdb26981399 100644 --- a/source/blender/gpu/shaders/gpu_shader_3D_selection_id_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_3D_selection_id_vert.glsl @@ -7,17 +7,13 @@ in vec3 pos; uniform uint offset; in uint color; -flat out vec4 id; +flat out uint id; #endif void main() { #ifndef UNIFORM_ID - id = vec4( - (((color + offset) ) & 0xFFu) * (1.0f / 255.0f), - (((color + offset) >> 8u) & 0xFFu) * (1.0f / 255.0f), - (((color + offset) >> 16u) & 0xFFu) * (1.0f / 255.0f), - (((color + offset) >> 24u) ) * (1.0f / 255.0f)); + id = offset + color; #endif vec4 pos_4d = vec4(pos, 1.0); diff --git a/source/blender/gpu/shaders/gpu_shader_selection_id_frag.glsl b/source/blender/gpu/shaders/gpu_shader_selection_id_frag.glsl index a38113fad87..45ba6cf4d08 100644 --- a/source/blender/gpu/shaders/gpu_shader_selection_id_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_selection_id_frag.glsl @@ -2,20 +2,12 @@ #ifdef UNIFORM_ID uniform uint id; #else -flat in vec4 id; +flat in uint id; #endif -out vec4 fragColor; +out uint fragColor; void main() { -#ifdef UNIFORM_ID - fragColor = vec4( - ((id ) & 0xFFu) * (1.0f / 255.0f), - ((id >> 8u) & 0xFFu) * (1.0f / 255.0f), - ((id >> 16u) & 0xFFu) * (1.0f / 255.0f), - ((id >> 24u) ) * (1.0f / 255.0f)); -#else fragColor = id; -#endif } diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 3259587f4cb..1e164438c9f 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -75,7 +75,6 @@ typedef struct RegionView3D { struct RegionView3D *localvd; struct RenderEngine *render_engine; struct ViewDepths *depths; - void *gpuoffscreen; /** Animated smooth view. */ struct SmoothView3DStore *sms; |