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/editors/space_view3d/view3d_draw_legacy.c | |
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/editors/space_view3d/view3d_draw_legacy.c')
-rw-r--r-- | source/blender/editors/space_view3d/view3d_draw_legacy.c | 255 |
1 files changed, 111 insertions, 144 deletions
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; } |