From 19aa873f70026e4745584915466e9da6910457b8 Mon Sep 17 00:00:00 2001 From: mano-wii Date: Tue, 23 Jul 2019 07:51:16 -0300 Subject: Fix T67299: UV Stretching Overlay of type "Area" fail when any face is hidden We want to include this for 2.80 --- source/blender/draw/intern/draw_cache_impl_mesh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index 306031809d1..2376787a273 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -4830,7 +4830,7 @@ static void uvedit_fill_buffer_data(MeshRenderData *rdata, /* Tag hidden faces */ BM_elem_flag_set(efa, BM_ELEM_TAG, uvedit_face_visible_nolocal_ex(rdata->toolsettings, efa)); - if (vbo_area && BM_elem_flag_test(efa, BM_ELEM_TAG)) { + if (vbo_area) { edit_uv_preprocess_stretch_area( efa, cd_loop_uv_offset, fidx++, &totarea, &totuvarea, faces_areas); } -- cgit v1.2.3 From ef0e06d7644727883c250975133264b046930b70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Tue, 23 Jul 2019 13:20:00 +0200 Subject: Fix T65386 Eevee: Crash after baking indirect lights or cubemap I'm not sure this fixes the root of the problem. The file from the ticket seems to have been corrupted in some way. We MIGHT want this in 2.80. --- source/blender/draw/engines/eevee/eevee_lightcache.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c index 3977fd160fc..c82a112b343 100644 --- a/source/blender/draw/engines/eevee/eevee_lightcache.c +++ b/source/blender/draw/engines/eevee/eevee_lightcache.c @@ -266,7 +266,8 @@ static bool EEVEE_lightcache_validate(const LightCache *light_cache, (irr_size[2] == light_cache->grid_tx.tex_size[2]) && (grid_len == light_cache->grid_len)) { int mip_len = (int)(floorf(log2f(cube_res)) - MIN_CUBE_LOD_LEVEL); if ((cube_res == light_cache->cube_tx.tex_size[0]) && - (cube_len == light_cache->cube_tx.tex_size[2]) && (mip_len == light_cache->mips_len)) { + (cube_len == light_cache->cube_tx.tex_size[2]) && (cube_len == light_cache->cube_len) && + (mip_len == light_cache->mips_len)) { return true; } } -- cgit v1.2.3 From 4fe0fafb875581e4a116db17da6a032fd1749f65 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 24 Jul 2019 20:42:39 +1000 Subject: Fix T67548: Camera background-image ignores shift Regression from 2.79 --- source/blender/draw/modes/object_mode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c index 9fc11e4f36f..ffa013d2758 100644 --- a/source/blender/draw/modes/object_mode.c +++ b/source/blender/draw/modes/object_mode.c @@ -1256,7 +1256,7 @@ static void DRW_shgroup_camera_background_images(OBJECT_Shaders *sh_data, if (!DRW_state_is_image_render()) { rctf render_border; - ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &render_border, true); + ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &render_border, false); camera_width = render_border.xmax - render_border.xmin; camera_height = render_border.ymax - render_border.ymin; camera_aspect = camera_width / camera_height; -- cgit v1.2.3 From bfe580642f46539ba85341fa8db451c52afd0cb4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 24 Jul 2019 22:30:31 +1000 Subject: Fix background image rotation and offset - Offset was halved & not compensating for non-square aspect. - Rotation was flipped. --- source/blender/draw/modes/object_mode.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c index ffa013d2758..8d4083f1723 100644 --- a/source/blender/draw/modes/object_mode.c +++ b/source/blender/draw/modes/object_mode.c @@ -1242,7 +1242,7 @@ static void DRW_shgroup_camera_background_images(OBJECT_Shaders *sh_data, unit_m4(win_m4_scale); unit_m4(win_m4_translate); unit_m4(scale_m4); - axis_angle_to_mat4_single(rot_m4, 'Z', bgpic->rotation); + axis_angle_to_mat4_single(rot_m4, 'Z', -bgpic->rotation); unit_m4(translate_m4); const float *size = DRW_viewport_size_get(); @@ -1311,9 +1311,9 @@ static void DRW_shgroup_camera_background_images(OBJECT_Shaders *sh_data, scale_m4[0][0] = scale_x; scale_m4[1][1] = scale_y; - // translate - translate_m4[3][0] = bgpic->offset[0]; - translate_m4[3][1] = bgpic->offset[1]; + /* Translate, using coordinates that aren't squashed by the aspect. */ + translate_m4[3][0] = bgpic->offset[0] * 2.0f * max_ff(1.0f, 1.0f / camera_aspect); + translate_m4[3][1] = bgpic->offset[1] * 2.0f * max_ff(1.0f, camera_aspect); mul_m4_series(bg_data->transform_mat, win_m4_translate, -- cgit v1.2.3 From d438e71729d1e95edf58ee6b8e99def22adf813e Mon Sep 17 00:00:00 2001 From: Antonioya Date: Sat, 27 Jul 2019 17:37:31 +0200 Subject: GPencil: Use uniform_int_copy instead to pass reference The constant variable was passed as reference to constant variable, but it's better use the new function to copy values. This could be the problem with T67772 --- source/blender/draw/engines/gpencil/gpencil_shader_fx.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c index 306444303e2..0f4043ce278 100644 --- a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c +++ b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c @@ -463,12 +463,11 @@ static void gpencil_fx_shadow(ShaderFxData *fx, DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->runtime.loc, 1); } - const int nowave = -1; if (fxd->flag & FX_SHADOW_USE_WAVE) { DRW_shgroup_uniform_int(fx_shgrp, "orientation", &fxd->orientation, 1); } else { - DRW_shgroup_uniform_int(fx_shgrp, "orientation", &nowave, 1); + DRW_shgroup_uniform_int_copy(fx_shgrp, "orientation", -1); } DRW_shgroup_uniform_float(fx_shgrp, "amplitude", &fxd->amplitude, 1); DRW_shgroup_uniform_float(fx_shgrp, "period", &fxd->period, 1); -- cgit v1.2.3 From b83a1b62c7db4e11c96b65cb68b2a88eeab7fcbc Mon Sep 17 00:00:00 2001 From: Antonioya Date: Tue, 23 Jul 2019 22:29:42 +0200 Subject: Fix T66233: Grease Pencil Swirl Effect not working at origin If the control object is in the origin the radius is wrongly calculated because the result is 0. Now, this value is clamped to avoid this situation --- .../draw/engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl index b226d4f93bc..01d4fe40195 100644 --- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl @@ -42,7 +42,11 @@ void main() vec2 tc = uv - center; float dist = length(tc); - float pxradius = (ProjectionMatrix[3][3] == 0.0) ? (radius / (loc.z * defaultpixsize)) : + float locpixsize = abs((loc.z * defaultpixsize)); + if (locpixsize == 0) { + locpixsize = 1; + } + float pxradius = (ProjectionMatrix[3][3] == 0.0) ? (radius / locpixsize) : (radius / defaultpixsize); pxradius = max(pxradius, 1); -- cgit v1.2.3 From 651d8bfd98db11eb58018412cc030cfe2705c519 Mon Sep 17 00:00:00 2001 From: mano-wii Date: Tue, 30 Jul 2019 06:46:59 -0300 Subject: 3D View: Move selection API to a Selection engine. This commit moves the API of selecting faces, vertices and edges to a DRW manager engine. Reviewers: campbellbarton, fclem Subscribers: jbakker, brecht Differential Revision: https://developer.blender.org/D5090 --- source/blender/draw/CMakeLists.txt | 5 + source/blender/draw/DRW_engine.h | 36 +- source/blender/draw/engines/select/select_engine.c | 647 +++++++++++++++++++++ source/blender/draw/engines/select/select_engine.h | 29 + .../select/shaders/selection_id_3D_vert.glsl | 26 + .../engines/select/shaders/selection_id_frag.glsl | 14 + source/blender/draw/intern/draw_manager.c | 392 +++---------- 7 files changed, 818 insertions(+), 331 deletions(-) create mode 100644 source/blender/draw/engines/select/select_engine.c create mode 100644 source/blender/draw/engines/select/select_engine.h create mode 100644 source/blender/draw/engines/select/shaders/selection_id_3D_vert.glsl create mode 100644 source/blender/draw/engines/select/shaders/selection_id_frag.glsl (limited to 'source/blender/draw') diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 8631a9f556b..664484d9a57 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -126,6 +126,7 @@ set(SRC engines/gpencil/gpencil_engine.h engines/gpencil/gpencil_render.c engines/gpencil/gpencil_shader_fx.c + engines/select/select_engine.c DRW_engine.h intern/DRW_render.h @@ -150,6 +151,7 @@ set(SRC engines/external/external_engine.h engines/workbench/workbench_engine.h engines/workbench/workbench_private.h + engines/select/select_engine.h ) set(LIB @@ -363,6 +365,9 @@ data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_shadow_resolve_frag.glsl data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl SRC) data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_wave_frag.glsl SRC) +data_to_c_simple(engines/select/shaders/selection_id_3D_vert.glsl SRC) +data_to_c_simple(engines/select/shaders/selection_id_frag.glsl SRC) + list(APPEND INC ) diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index 5919e100ddd..64a02f3931b 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -26,6 +26,7 @@ #include "BLI_sys_types.h" /* for bool */ struct ARegion; +struct Base; struct DRWInstanceDataList; struct DRWPass; struct Depsgraph; @@ -136,19 +137,12 @@ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph, void DRW_draw_depth_object(struct ARegion *ar, struct GPUViewport *viewport, struct Object *object); -void DRW_draw_select_id_object(struct Scene *scene, - struct RegionView3D *rv3d, - struct Object *ob, - short select_mode, - bool draw_facedot, - uint initial_offset, - uint *r_vert_offset, - uint *r_edge_offset, - uint *r_face_offset); - -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); +void DRW_draw_select_id(struct Depsgraph *depsgraph, + struct ARegion *ar, + struct View3D *v3d, + struct Base **bases, + const uint bases_len, + short select_mode); /* grease pencil render */ bool DRW_render_check_grease_pencil(struct Depsgraph *depsgraph); @@ -181,4 +175,20 @@ void DRW_deferred_shader_remove(struct GPUMaterial *mat); struct DrawDataList *DRW_drawdatalist_from_id(struct ID *id); void DRW_drawdata_free(struct ID *id); +/* select_engine.c */ +void DRW_select_context_create(struct Depsgraph *depsgraph, + struct Base **bases, + const uint bases_len, + short select_mode); +bool DRW_select_elem_get(const uint sel_id, uint *r_elem, uint *r_base_index, char *r_elem_type); +uint DRW_select_context_offset_for_object_elem(const uint base_index, char elem_type); +uint DRW_select_context_elem_len(void); +void DRW_framebuffer_select_id_read(const struct rcti *rect, uint *r_buf); +void DRW_draw_select_id_object(struct Depsgraph *depsgraph, + struct ViewLayer *view_layer, + struct ARegion *ar, + struct View3D *v3d, + struct Object *ob, + short select_mode); + #endif /* __DRW_ENGINE_H__ */ diff --git a/source/blender/draw/engines/select/select_engine.c b/source/blender/draw/engines/select/select_engine.c new file mode 100644 index 00000000000..f1fc9cbc0d6 --- /dev/null +++ b/source/blender/draw/engines/select/select_engine.c @@ -0,0 +1,647 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2019, Blender Foundation. + */ + +/** \file + * \ingroup draw_engine + * + * Engine for drawing a selection map where the pixels indicate the selection indices. + */ + +#include "BLI_rect.h" + +#include "BKE_editmesh.h" + +#include "DNA_mesh_types.h" +#include "DNA_screen_types.h" + +#include "ED_view3d.h" + +#include "GPU_shader.h" +#include "GPU_select.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + +#include "UI_resources.h" + +#include "DRW_engine.h" +#include "DRW_render.h" + +#include "draw_cache_impl.h" + +#include "select_engine.h" +/* Shaders */ + +#define SELECT_ENGINE "SELECT_ENGINE" + +/* *********** LISTS *********** */ + +/* GPUViewport.storage + * Is freed everytime the viewport engine changes */ +typedef struct SELECTID_StorageList { + struct SELECTID_PrivateData *g_data; +} SELECTID_StorageList; + +typedef struct SELECTID_PassList { + struct DRWPass *select_id_face_pass; + struct DRWPass *select_id_edge_pass; + struct DRWPass *select_id_vert_pass; +} SELECTID_PassList; + +typedef struct SELECTID_Data { + void *engine_type; + DRWViewportEmptyList *fbl; + DRWViewportEmptyList *txl; + SELECTID_PassList *psl; + SELECTID_StorageList *stl; +} SELECTID_Data; + +typedef struct SELECTID_Shaders { + /* Depth Pre Pass */ + struct GPUShader *select_id_flat; + struct GPUShader *select_id_uniform; +} SELECTID_Shaders; + +/* *********** STATIC *********** */ + +static struct { + SELECTID_Shaders sh_data[GPU_SHADER_CFG_LEN]; + + struct GPUFrameBuffer *framebuffer_select_id; + struct GPUTexture *texture_u32; + + struct { + struct BaseOffset *base_array_index_offsets; + uint bases_len; + uint last_base_drawn; + /** Total number of items `base_array_index_offsets[bases_len - 1].vert`. */ + uint last_index_drawn; + + struct Depsgraph *depsgraph; + short select_mode; + } context; +} e_data = {{{NULL}}}; /* Engine data */ + +typedef struct SELECTID_PrivateData { + DRWShadingGroup *shgrp_face_unif; + DRWShadingGroup *shgrp_face_flat; + DRWShadingGroup *shgrp_edge; + DRWShadingGroup *shgrp_vert; + + DRWView *view_faces; + DRWView *view_edges; + DRWView *view_verts; +} SELECTID_PrivateData; /* Transient data */ + +struct BaseOffset { + /* For convenience only. */ + union { + uint offset; + uint face_start; + }; + union { + uint face; + uint edge_start; + }; + union { + uint edge; + uint vert_start; + }; + uint vert; +}; + +/* Shaders */ +extern char datatoc_common_view_lib_glsl[]; +extern char datatoc_selection_id_3D_vert_glsl[]; +extern char datatoc_selection_id_frag_glsl[]; + +/* -------------------------------------------------------------------- */ +/** \name Selection Utilities + * \{ */ + +static void draw_select_framebuffer_select_id_setup(void) +{ + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + int size[2]; + size[0] = GPU_texture_width(dtxl->depth); + size[1] = GPU_texture_height(dtxl->depth); + + if (e_data.framebuffer_select_id == NULL) { + e_data.framebuffer_select_id = GPU_framebuffer_create(); + } + + if ((e_data.texture_u32 != NULL) && ((GPU_texture_width(e_data.texture_u32) != size[0]) || + (GPU_texture_height(e_data.texture_u32) != size[1]))) { + + GPU_texture_free(e_data.texture_u32); + e_data.texture_u32 = NULL; + } + + if (e_data.texture_u32 == NULL) { + e_data.texture_u32 = GPU_texture_create_2d(size[0], size[1], GPU_R32UI, NULL, NULL); + + GPU_framebuffer_texture_attach(e_data.framebuffer_select_id, dtxl->depth, 0, 0); + GPU_framebuffer_texture_attach(e_data.framebuffer_select_id, e_data.texture_u32, 0, 0); + GPU_framebuffer_check_valid(e_data.framebuffer_select_id, NULL); + } +} + +static void draw_select_id_object(void *vedata, + Object *ob, + short select_mode, + bool draw_facedot, + uint initial_offset, + uint *r_vert_offset, + uint *r_edge_offset, + uint *r_face_offset) +{ + SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl; + + BLI_assert(initial_offset > 0); + + switch (ob->type) { + case OB_MESH: + if (ob->mode & OB_MODE_EDIT) { + Mesh *me = ob->data; + BMEditMesh *em = me->edit_mesh; + const bool use_faceselect = (select_mode & SCE_SELECT_FACE) != 0; + + DRW_mesh_batch_cache_validate(me); + + BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE); + + struct GPUBatch *geom_faces, *geom_edges, *geom_verts, *geom_facedots; + geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); + if (select_mode & SCE_SELECT_EDGE) { + geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me); + } + if (select_mode & SCE_SELECT_VERTEX) { + geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me); + } + if (use_faceselect && draw_facedot) { + geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me); + } + DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true); + + DRWShadingGroup *face_shgrp; + if (use_faceselect) { + face_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_face_flat); + DRW_shgroup_uniform_int_copy(face_shgrp, "offset", *(int *)&initial_offset); + + if (draw_facedot) { + DRW_shgroup_call(face_shgrp, geom_facedots, ob); + } + *r_face_offset = initial_offset + em->bm->totface; + } + else { + face_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_face_unif); + DRW_shgroup_uniform_int_copy(face_shgrp, "id", 0); + + *r_face_offset = initial_offset; + } + DRW_shgroup_call(face_shgrp, geom_faces, ob); + + /* Unlike faces, only draw edges if edge select mode. */ + if (select_mode & SCE_SELECT_EDGE) { + DRWShadingGroup *edge_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_edge); + DRW_shgroup_uniform_int_copy(edge_shgrp, "offset", *(int *)r_face_offset); + DRW_shgroup_call(edge_shgrp, geom_edges, ob); + *r_edge_offset = *r_face_offset + em->bm->totedge; + } + else { + /* Note that `r_vert_offset` is calculated from `r_edge_offset`. + * Otherwise the first vertex is never selected, see: T53512. */ + *r_edge_offset = *r_face_offset; + } + + /* Unlike faces, only verts if vert select mode. */ + if (select_mode & SCE_SELECT_VERTEX) { + DRWShadingGroup *vert_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_vert); + DRW_shgroup_uniform_int_copy(vert_shgrp, "offset", *(int *)r_edge_offset); + DRW_shgroup_call(vert_shgrp, geom_verts, ob); + *r_vert_offset = *r_edge_offset + em->bm->totvert; + } + else { + *r_vert_offset = *r_edge_offset; + } + } + else { + Mesh *me_orig = DEG_get_original_object(ob)->data; + Mesh *me_eval = ob->data; + + DRW_mesh_batch_cache_validate(me_eval); + struct GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me_eval); + if ((me_orig->editflag & ME_EDIT_PAINT_VERT_SEL) && + /* Currently vertex select supports weight paint and vertex paint. */ + ((ob->mode & OB_MODE_WEIGHT_PAINT) || (ob->mode & OB_MODE_VERTEX_PAINT))) { + + struct GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me_eval); + DRW_mesh_batch_cache_create_requested(ob, me_eval, NULL, false, true); + + /* Only draw faces to mask out verts, we don't want their selection ID's. */ + DRWShadingGroup *face_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_face_unif); + DRW_shgroup_uniform_int_copy(face_shgrp, "id", 0); + DRW_shgroup_call(face_shgrp, geom_faces, ob); + + DRWShadingGroup *vert_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_vert); + DRW_shgroup_uniform_int_copy(vert_shgrp, "offset", 1); + DRW_shgroup_call(vert_shgrp, geom_verts, ob); + + *r_face_offset = *r_edge_offset = initial_offset; + *r_vert_offset = me_eval->totvert + 1; + } + else { + const bool use_hide = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL); + DRW_mesh_batch_cache_create_requested(ob, me_eval, NULL, false, use_hide); + + DRWShadingGroup *face_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_face_flat); + DRW_shgroup_uniform_int_copy(face_shgrp, "offset", *(int *)&initial_offset); + DRW_shgroup_call(face_shgrp, geom_faces, ob); + + *r_face_offset = initial_offset + me_eval->totpoly; + *r_edge_offset = *r_vert_offset = *r_face_offset; + } + } + break; + case OB_CURVE: + case OB_SURF: + break; + } +} + +static bool check_ob_drawface_dot(short select_mode, const View3D *v3d, char dt) +{ + if (select_mode & SCE_SELECT_FACE) { + if ((dt < OB_SOLID) || XRAY_FLAG_ENABLED(v3d)) { + return true; + } + if (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) { + return true; + } + if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_EDGES) == 0) { + /* Since we can't deduce face selection when edges aren't visible - show dots. */ + return true; + } + } + return false; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Engine Functions + * \{ */ + +static void select_engine_init(void *vedata) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + eGPUShaderConfig sh_cfg = draw_ctx->sh_cfg; + + SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl; + SELECTID_Shaders *sh_data = &e_data.sh_data[sh_cfg]; + + /* Prepass */ + if (!sh_data->select_id_flat) { + const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg]; + sh_data->select_id_flat = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_view_lib_glsl, + datatoc_selection_id_3D_vert_glsl, + NULL}, + .frag = (const char *[]){datatoc_selection_id_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, NULL}, + }); + } + if (!sh_data->select_id_uniform) { + const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg]; + sh_data->select_id_uniform = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_view_lib_glsl, + datatoc_selection_id_3D_vert_glsl, + NULL}, + .frag = (const char *[]){datatoc_selection_id_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, "#define UNIFORM_ID\n", NULL}, + }); + } + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + { + /* Create view with depth offset */ + stl->g_data->view_faces = (DRWView *)DRW_view_default_get(); + stl->g_data->view_edges = DRW_view_create_with_zoffset(draw_ctx->rv3d, 1.0f); + stl->g_data->view_verts = DRW_view_create_with_zoffset(draw_ctx->rv3d, 1.1f); + } +} + +static void select_cache_init(void *vedata) +{ + SELECTID_PassList *psl = ((SELECTID_Data *)vedata)->psl; + SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + SELECTID_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; + { + psl->select_id_face_pass = DRW_pass_create("Face Pass", DRW_STATE_DEFAULT); + stl->g_data->shgrp_face_unif = DRW_shgroup_create(sh_data->select_id_uniform, + psl->select_id_face_pass); + + stl->g_data->shgrp_face_flat = DRW_shgroup_create(sh_data->select_id_flat, + psl->select_id_face_pass); + + psl->select_id_edge_pass = DRW_pass_create( + "Edge Pass", DRW_STATE_DEFAULT | DRW_STATE_FIRST_VERTEX_CONVENTION); + + stl->g_data->shgrp_edge = DRW_shgroup_create(sh_data->select_id_flat, + psl->select_id_edge_pass); + + psl->select_id_vert_pass = DRW_pass_create("Vert Pass", DRW_STATE_DEFAULT); + stl->g_data->shgrp_vert = DRW_shgroup_create(sh_data->select_id_flat, + psl->select_id_vert_pass); + + DRW_shgroup_uniform_float_copy(stl->g_data->shgrp_vert, "sizeVertex", G_draw.block.sizeVertex); + + if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { + DRW_shgroup_state_enable(stl->g_data->shgrp_face_unif, DRW_STATE_CLIP_PLANES); + DRW_shgroup_state_enable(stl->g_data->shgrp_face_flat, DRW_STATE_CLIP_PLANES); + DRW_shgroup_state_enable(stl->g_data->shgrp_edge, DRW_STATE_CLIP_PLANES); + DRW_shgroup_state_enable(stl->g_data->shgrp_vert, DRW_STATE_CLIP_PLANES); + } + } + + e_data.context.last_base_drawn = 0; + e_data.context.last_index_drawn = 1; +} + +static void select_cache_populate(void *vedata, Object *ob) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + short select_mode = e_data.context.select_mode; + + if (select_mode == -1) { + ToolSettings *ts = draw_ctx->scene->toolsettings; + select_mode = ts->selectmode; + } + + bool draw_facedot = check_ob_drawface_dot(select_mode, draw_ctx->v3d, ob->dt); + + struct BaseOffset *base_ofs = + &e_data.context.base_array_index_offsets[e_data.context.last_base_drawn++]; + + uint offset = e_data.context.last_index_drawn; + + draw_select_id_object(vedata, + ob, + select_mode, + draw_facedot, + offset, + &base_ofs->vert, + &base_ofs->edge, + &base_ofs->face); + + base_ofs->offset = offset; + e_data.context.last_index_drawn = base_ofs->vert; +} + +static void select_draw_scene(void *vedata) +{ + SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl; + SELECTID_PassList *psl = ((SELECTID_Data *)vedata)->psl; + + /* Setup framebuffer */ + draw_select_framebuffer_select_id_setup(); + GPU_framebuffer_bind(e_data.framebuffer_select_id); + + /* dithering and AA break color coding, so disable */ + glDisable(GL_DITHER); + + GPU_framebuffer_clear_color_depth(e_data.framebuffer_select_id, (const float[4]){0.0f}, 1.0f); + + DRW_view_set_active(stl->g_data->view_faces); + DRW_draw_pass(psl->select_id_face_pass); + + DRW_view_set_active(stl->g_data->view_edges); + DRW_draw_pass(psl->select_id_edge_pass); + + DRW_view_set_active(stl->g_data->view_verts); + DRW_draw_pass(psl->select_id_vert_pass); +} + +static void select_engine_free(void) +{ + for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) { + SELECTID_Shaders *sh_data = &e_data.sh_data[sh_data_index]; + DRW_SHADER_FREE_SAFE(sh_data->select_id_flat); + DRW_SHADER_FREE_SAFE(sh_data->select_id_uniform); + } + + DRW_TEXTURE_FREE_SAFE(e_data.texture_u32); + GPU_FRAMEBUFFER_FREE_SAFE(e_data.framebuffer_select_id); + MEM_SAFE_FREE(e_data.context.base_array_index_offsets); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Exposed `DRW_engine.h` functions + * \{ */ + +bool DRW_select_elem_get(const uint sel_id, uint *r_elem, uint *r_base_index, char *r_elem_type) +{ + char elem_type = 0; + uint elem_id; + uint base_index = 0; + + for (; base_index < e_data.context.bases_len; base_index++) { + struct BaseOffset *base_ofs = &e_data.context.base_array_index_offsets[base_index]; + + if (base_ofs->face > sel_id) { + elem_id = sel_id - base_ofs->face_start; + elem_type = SCE_SELECT_FACE; + break; + } + if (base_ofs->edge > sel_id) { + elem_id = sel_id - base_ofs->edge_start; + elem_type = SCE_SELECT_EDGE; + break; + } + if (base_ofs->vert > sel_id) { + elem_id = sel_id - base_ofs->vert_start; + elem_type = SCE_SELECT_VERTEX; + break; + } + } + + if (base_index == e_data.context.bases_len) { + return false; + } + + *r_elem = elem_id; + + if (r_base_index) { + *r_base_index = base_index; + } + + if (r_elem_type) { + *r_elem_type = elem_type; + } + + return true; +} + +uint DRW_select_context_offset_for_object_elem(const uint base_index, char elem_type) +{ + struct BaseOffset *base_ofs = &e_data.context.base_array_index_offsets[base_index]; + + if (elem_type == SCE_SELECT_VERTEX) { + return base_ofs->vert_start - 1; + } + if (elem_type == SCE_SELECT_EDGE) { + return base_ofs->edge_start - 1; + } + if (elem_type == SCE_SELECT_FACE) { + return base_ofs->face_start - 1; + } + BLI_assert(0); + return 0; +} + +uint DRW_select_context_elem_len(void) +{ + return e_data.context.last_index_drawn; +} + +/* Read a block of pixels from the select frame buffer. */ +void DRW_framebuffer_select_id_read(const rcti *rect, uint *r_buf) +{ + /* clamp rect by texture */ + rcti r = { + .xmin = 0, + .xmax = GPU_texture_width(e_data.texture_u32), + .ymin = 0, + .ymax = GPU_texture_height(e_data.texture_u32), + }; + + rcti rect_clamp = *rect; + if (BLI_rcti_isect(&r, &rect_clamp, &rect_clamp)) { + DRW_opengl_context_enable(); + GPU_framebuffer_bind(e_data.framebuffer_select_id); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glReadPixels(rect_clamp.xmin, + rect_clamp.ymin, + BLI_rcti_size_x(&rect_clamp), + BLI_rcti_size_y(&rect_clamp), + GL_RED_INTEGER, + GL_UNSIGNED_INT, + r_buf); + + GPU_framebuffer_restore(); + DRW_opengl_context_disable(); + + if (!BLI_rcti_compare(rect, &rect_clamp)) { + GPU_select_buffer_stride_realign(rect, &rect_clamp, r_buf); + } + } + else { + size_t buf_size = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect) * sizeof(*r_buf); + + memset(r_buf, 0, buf_size); + } +} + +void DRW_select_context_create(Depsgraph *depsgraph, + Base **UNUSED(bases), + const uint bases_len, + short select_mode) +{ + e_data.context.depsgraph = depsgraph; + e_data.context.select_mode = select_mode; + e_data.context.bases_len = bases_len; + + MEM_SAFE_FREE(e_data.context.base_array_index_offsets); + e_data.context.base_array_index_offsets = MEM_mallocN( + sizeof(*e_data.context.base_array_index_offsets) * bases_len, __func__); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Legacy + * \{ */ + +void DRW_draw_select_id_object(Depsgraph *depsgraph, + ViewLayer *view_layer, + ARegion *ar, + View3D *v3d, + Object *ob, + short select_mode) +{ + Base *base = BKE_view_layer_base_find(view_layer, ob); + DRW_draw_select_id(depsgraph, ar, v3d, &base, 1, select_mode); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Engine Type + * \{ */ + +static const DrawEngineDataSize select_data_size = DRW_VIEWPORT_DATA_SIZE(SELECTID_Data); + +DrawEngineType draw_engine_select_type = { + NULL, + NULL, + N_("Select ID"), + &select_data_size, + &select_engine_init, + &select_engine_free, + &select_cache_init, + &select_cache_populate, + NULL, + NULL, + &select_draw_scene, + NULL, + NULL, + NULL, +}; + +/* Note: currently unused, we may want to register so we can see this when debugging the view. */ + +RenderEngineType DRW_engine_viewport_select_type = { + NULL, + NULL, + SELECT_ENGINE, + N_("Select ID"), + RE_INTERNAL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + &draw_engine_select_type, + {NULL, NULL, NULL}, +}; + +/** \} */ + +#undef SELECT_ENGINE diff --git a/source/blender/draw/engines/select/select_engine.h b/source/blender/draw/engines/select/select_engine.h new file mode 100644 index 00000000000..5b900ccaf27 --- /dev/null +++ b/source/blender/draw/engines/select/select_engine.h @@ -0,0 +1,29 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2019, Blender Foundation. + */ + +/** \file + * \ingroup draw_engine + */ + +#ifndef __SELECT_ENGINE_H__ +#define __SELECT_ENGINE_H__ + +extern DrawEngineType draw_engine_select_type; +extern RenderEngineType DRW_engine_viewport_select_type; + +#endif /* __SELECT_ID_ENGINE_H__ */ diff --git a/source/blender/draw/engines/select/shaders/selection_id_3D_vert.glsl b/source/blender/draw/engines/select/shaders/selection_id_3D_vert.glsl new file mode 100644 index 00000000000..9b0107cffdb --- /dev/null +++ b/source/blender/draw/engines/select/shaders/selection_id_3D_vert.glsl @@ -0,0 +1,26 @@ + +uniform float sizeVertex; + +in vec3 pos; + +#ifndef UNIFORM_ID +uniform int offset; +in uint color; + +flat out uint id; +#endif + +void main() +{ +#ifndef UNIFORM_ID + id = floatBitsToUint(intBitsToFloat(offset)) + color; +#endif + + vec3 world_pos = point_object_to_world(pos); + gl_Position = point_world_to_ndc(world_pos); + gl_PointSize = sizeVertex; + +#ifdef USE_WORLD_CLIP_PLANES + world_clip_planes_calc_clip_distance(world_pos); +#endif +} diff --git a/source/blender/draw/engines/select/shaders/selection_id_frag.glsl b/source/blender/draw/engines/select/shaders/selection_id_frag.glsl new file mode 100644 index 00000000000..ea86ddc7301 --- /dev/null +++ b/source/blender/draw/engines/select/shaders/selection_id_frag.glsl @@ -0,0 +1,14 @@ + +#ifdef UNIFORM_ID +uniform int id; +# define id floatBitsToUint(intBitsToFloat(id)) +#else +flat in uint id; +#endif + +out uint fragColor; + +void main() +{ + fragColor = id; +} diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 2841e017ef6..320a6f6aaaa 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -89,6 +89,7 @@ #include "engines/workbench/workbench_engine.h" #include "engines/external/external_engine.h" #include "engines/gpencil/gpencil_engine.h" +#include "engines/select/select_engine.h" #include "GPU_context.h" @@ -2136,16 +2137,13 @@ void DRW_custom_pipeline(DrawEngineType *draw_engine_type, static struct DRWSelectBuffer { 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_depth_only_setup(const int size[2]) { 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 ((g_select_buffer.texture_depth != NULL) && @@ -2162,32 +2160,7 @@ static void draw_select_framebuffer_depth_only_setup(const int size[2]) GPU_framebuffer_texture_attach( g_select_buffer.framebuffer_depth_only, g_select_buffer.texture_depth, 0, 0); - 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, NULL); - GPU_framebuffer_check_valid(g_select_buffer.framebuffer_select_id, NULL); - } -} - -static void draw_select_framebuffer_select_id_setup(const int size[2]) -{ - draw_select_framebuffer_depth_only_setup(size); - - 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, NULL); } } @@ -2575,6 +2548,78 @@ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph, DRW_opengl_context_disable(); } +void DRW_draw_select_id(Depsgraph *depsgraph, + ARegion *ar, + View3D *v3d, + Base **bases, + const uint bases_len, + short select_mode) +{ + Scene *scene = DEG_get_evaluated_scene(depsgraph); + ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); + + DRW_select_context_create(depsgraph, bases, bases_len, select_mode); + + DRW_opengl_context_enable(); + + /* Reset before using it. */ + drw_state_prepare_clean_for_draw(&DST); + DST.buffer_finish_called = true; + + /* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */ + DST.draw_ctx = (DRWContextState){ + .ar = ar, + .rv3d = ar->regiondata, + .v3d = v3d, + .scene = scene, + .view_layer = view_layer, + .obact = OBACT(view_layer), + .depsgraph = depsgraph, + }; + + use_drw_engine(&draw_engine_select_type); + drw_context_state_init(); + + /* Setup viewport */ + DST.viewport = WM_draw_region_get_viewport(ar, 0); + drw_viewport_var_init(); + + /* Update ubos */ + DRW_globals_update(); + + /* Init engines */ + drw_engines_init(); + + { + drw_engines_cache_init(); + + /* Keep `base_index` in sync with `e_data.context.last_base_drawn`. + * So don't skip objects. */ + for (uint base_index = 0; base_index < bases_len; base_index++) { + Object *obj_eval = DEG_get_evaluated_object(depsgraph, bases[base_index]->object); + drw_engines_cache_populate(obj_eval); + } + + drw_engines_cache_finish(); + } + + /* Start Drawing */ + DRW_state_reset(); + drw_engines_draw_scene(); + DRW_state_reset(); + + drw_engines_disable(); + +#ifdef DEBUG + /* Avoid accidental reuse. */ + drw_state_ensure_not_reused(&DST); +#endif + + /* Changin context */ + GPU_framebuffer_restore(); + DRW_opengl_context_disable(); +} + /** See #DRW_shgroup_world_clip_planes_from_rv3d. */ static void draw_world_clip_planes_from_rv3d(GPUBatch *batch, const float world_clip_planes[6][4]) { @@ -2646,294 +2691,6 @@ void DRW_draw_depth_object(ARegion *ar, GPUViewport *viewport, Object *object) DRW_opengl_context_disable(); } -static void draw_mesh_verts(GPUBatch *batch, uint offset, const float world_clip_planes[6][4]) -{ - GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE)); - - 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_FLAT_SELECT_ID, sh_cfg); - GPU_batch_uniform_1ui(batch, "offset", offset); - if (world_clip_planes != NULL) { - draw_world_clip_planes_from_rv3d(batch, world_clip_planes); - } - GPU_batch_draw(batch); -} - -static void draw_mesh_edges(GPUBatch *batch, uint offset, const float world_clip_planes[6][4]) -{ - GPU_line_width(1.0f); - glProvokingVertex(GL_FIRST_VERTEX_CONVENTION); - - 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_FLAT_SELECT_ID, sh_cfg); - GPU_batch_uniform_1ui(batch, "offset", offset); - if (world_clip_planes != NULL) { - draw_world_clip_planes_from_rv3d(batch, world_clip_planes); - } - GPU_batch_draw(batch); - - glProvokingVertex(GL_LAST_VERTEX_CONVENTION); -} - -/* two options, facecolors or black */ -static void draw_mesh_face(GPUBatch *batch, - uint offset, - const bool use_select, - const float world_clip_planes[6][4]) -{ - if (use_select) { - 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_FLAT_SELECT_ID, sh_cfg); - GPU_batch_uniform_1ui(batch, "offset", offset); - if (world_clip_planes != NULL) { - draw_world_clip_planes_from_rv3d(batch, world_clip_planes); - } - GPU_batch_draw(batch); - } - else { - 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_UNIFORM_SELECT_ID, sh_cfg); - GPU_batch_uniform_1ui(batch, "id", 0); - if (world_clip_planes != NULL) { - draw_world_clip_planes_from_rv3d(batch, world_clip_planes); - } - GPU_batch_draw(batch); - } -} - -static void draw_mesh_face_dot(GPUBatch *batch, uint offset, const float world_clip_planes[6][4]) -{ - 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_FLAT_SELECT_ID, sh_cfg); - GPU_batch_uniform_1ui(batch, "offset", offset); - if (world_clip_planes != NULL) { - draw_world_clip_planes_from_rv3d(batch, world_clip_planes); - } - GPU_batch_draw(batch); -} - -void DRW_draw_select_id_object(Scene *scene, - RegionView3D *rv3d, - Object *ob, - short select_mode, - bool draw_facedot, - uint initial_offset, - uint *r_vert_offset, - uint *r_edge_offset, - uint *r_face_offset) -{ - ToolSettings *ts = scene->toolsettings; - if (select_mode == -1) { - select_mode = ts->selectmode; - } - - /* Init the scene of the draw context. When using face dot selection on - * when the subsurf modifier is active on the cage, the scene needs to be - * valid. It is read from the context in the - * `DRW_mesh_batch_cache_create_requested` and used in the `isDisabled` - * method of the SubSurfModifier. */ - DRWContextState *draw_ctx = &DST.draw_ctx; - draw_ctx->scene = scene; - - GPU_matrix_mul(ob->obmat); - - 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; - } - - BLI_assert(initial_offset > 0); - - switch (ob->type) { - case OB_MESH: - if (ob->mode & OB_MODE_EDIT) { - Mesh *me = ob->data; - BMEditMesh *em = me->edit_mesh; - const bool use_faceselect = (select_mode & SCE_SELECT_FACE) != 0; - - DRW_mesh_batch_cache_validate(me); - - BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE); - - GPUBatch *geom_faces, *geom_edges, *geom_verts, *geom_facedots; - geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); - if (select_mode & SCE_SELECT_EDGE) { - geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me); - } - if (select_mode & SCE_SELECT_VERTEX) { - geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me); - } - if (use_faceselect && draw_facedot) { - geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me); - } - DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true); - - draw_mesh_face(geom_faces, initial_offset, use_faceselect, world_clip_planes); - - if (use_faceselect && draw_facedot) { - draw_mesh_face_dot(geom_facedots, initial_offset, world_clip_planes); - } - - if (select_mode & SCE_SELECT_FACE) { - *r_face_offset = initial_offset + em->bm->totface; - } - else { - *r_face_offset = initial_offset; - } - - ED_view3d_polygon_offset(rv3d, 1.0); - - /* Unlike faces, only draw edges if edge select mode. */ - if (select_mode & SCE_SELECT_EDGE) { - draw_mesh_edges(geom_edges, *r_face_offset, world_clip_planes); - *r_edge_offset = *r_face_offset + em->bm->totedge; - } - else { - /* Note that `r_vert_offset` is calculated from `r_edge_offset`. - * Otherwise the first vertex is never selected, see: T53512. */ - *r_edge_offset = *r_face_offset; - } - - ED_view3d_polygon_offset(rv3d, 1.1); - - /* Unlike faces, only verts if vert select mode. */ - if (select_mode & SCE_SELECT_VERTEX) { - draw_mesh_verts(geom_verts, *r_edge_offset, world_clip_planes); - *r_vert_offset = *r_edge_offset + em->bm->totvert; - } - else { - *r_vert_offset = *r_edge_offset; - } - - ED_view3d_polygon_offset(rv3d, 0.0); - } - else { - Mesh *me_orig = DEG_get_original_object(ob)->data; - Mesh *me_eval = ob->data; - - DRW_mesh_batch_cache_validate(me_eval); - GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me_eval); - if ((me_orig->editflag & ME_EDIT_PAINT_VERT_SEL) && - /* Currently vertex select supports weight paint and vertex paint. */ - ((ob->mode & OB_MODE_WEIGHT_PAINT) || (ob->mode & OB_MODE_VERTEX_PAINT))) { - - GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me_eval); - DRW_mesh_batch_cache_create_requested(ob, me_eval, NULL, false, true); - - /* Only draw faces to mask out verts, we don't want their selection ID's. */ - draw_mesh_face(geom_faces, 0, false, world_clip_planes); - draw_mesh_verts(geom_verts, 1, world_clip_planes); - - *r_face_offset = *r_edge_offset = initial_offset; - *r_vert_offset = me_eval->totvert + 1; - } - else { - const bool use_hide = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL); - DRW_mesh_batch_cache_create_requested(ob, me_eval, NULL, false, use_hide); - - draw_mesh_face(geom_faces, initial_offset, true, world_clip_planes); - - *r_face_offset = initial_offset + me_eval->totpoly; - *r_edge_offset = *r_vert_offset = *r_face_offset; - } - } - break; - case OB_CURVE: - case OB_SURF: - break; - } - - GPU_matrix_set(rv3d->viewmat); -} - -/* 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 */ - int viewport_size[2] = {ar->winx, ar->winy}; - draw_select_framebuffer_select_id_setup(viewport_size); - GPU_framebuffer_bind(g_select_buffer.framebuffer_select_id); - - /* dithering and AA break color coding, so disable */ - glDisable(GL_DITHER); - - GPU_depth_test(true); - GPU_program_point_size(false); - - 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_depth_test(false); - - GPU_framebuffer_restore(); - - 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) -{ - /* clamp rect by texture */ - rcti r = { - .xmin = 0, - .xmax = GPU_texture_width(g_select_buffer.texture_u32), - .ymin = 0, - .ymax = GPU_texture_height(g_select_buffer.texture_u32), - }; - - rcti rect_clamp = *rect; - if (BLI_rcti_isect(&r, &rect_clamp, &rect_clamp)) { - DRW_opengl_context_enable(); - GPU_framebuffer_bind(g_select_buffer.framebuffer_select_id); - glReadBuffer(GL_COLOR_ATTACHMENT0); - glReadPixels(rect_clamp.xmin, - rect_clamp.ymin, - BLI_rcti_size_x(&rect_clamp), - BLI_rcti_size_y(&rect_clamp), - GL_RED_INTEGER, - GL_UNSIGNED_INT, - r_buf); - - GPU_framebuffer_restore(); - DRW_opengl_context_disable(); - - if (!BLI_rcti_compare(rect, &rect_clamp)) { - GPU_select_buffer_stride_realign(rect, &rect_clamp, r_buf); - } - } - else { - size_t buf_size = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect) * sizeof(*r_buf); - - memset(r_buf, 0, buf_size); - } -} - /** \} */ /* -------------------------------------------------------------------- */ @@ -3089,6 +2846,7 @@ void DRW_engines_register(void) DRW_engine_register(&draw_engine_pose_type); DRW_engine_register(&draw_engine_sculpt_type); DRW_engine_register(&draw_engine_gpencil_type); + DRW_engine_register(&draw_engine_select_type); /* setup callbacks */ { @@ -3123,9 +2881,7 @@ 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_select_id); GPU_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer_depth_only); DRW_hair_free(); -- cgit v1.2.3 From b9718299ea509df2a3d563f0ac2639f01cad39ab Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 30 Jul 2019 21:40:42 +1000 Subject: Fix crash clicking in the 3D view on startup Setting the 3D view cursor on startup could crash because the viewport hasn't been assigned to the region. --- source/blender/draw/DRW_engine.h | 3 ++- source/blender/draw/intern/draw_manager.c | 11 ++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index 64a02f3931b..e31200ae82f 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -129,7 +129,8 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, void DRW_draw_depth_loop(struct Depsgraph *depsgraph, struct ARegion *ar, struct View3D *v3d, - struct GPUViewport *viewport); + struct GPUViewport *viewport, + bool use_opengl_context); void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph, struct ARegion *ar, struct View3D *v3d, diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 320a6f6aaaa..af61063335b 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -2452,14 +2452,17 @@ static void drw_draw_depth_loop_imp(void) void DRW_draw_depth_loop(struct Depsgraph *depsgraph, ARegion *ar, View3D *v3d, - GPUViewport *viewport) + GPUViewport *viewport, + bool use_opengl_context) { Scene *scene = DEG_get_evaluated_scene(depsgraph); RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type); ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); RegionView3D *rv3d = ar->regiondata; - DRW_opengl_context_enable(); + if (use_opengl_context) { + DRW_opengl_context_enable(); + } /* Reset before using it. */ drw_state_prepare_clean_for_draw(&DST); @@ -2498,7 +2501,9 @@ void DRW_draw_depth_loop(struct Depsgraph *depsgraph, #endif /* Changin context */ - DRW_opengl_context_disable(); + if (use_opengl_context) { + DRW_opengl_context_disable(); + } } /** -- cgit v1.2.3 From 7f29fc7415a49d5688efbe10fa0a81b174d49435 Mon Sep 17 00:00:00 2001 From: Antonioya Date: Sat, 20 Jul 2019 23:01:19 +0200 Subject: Fix T65691: GPencil Drawing long strokes turn invisible There was a fixed limit to the number of points available in a buffer stroke. Now, the array is expanded as needed using a predefined number of points for each expansion, instead to add one by one. This is done to reduce the number of times the memory allocation is required. As part of the fix, some variables have been renamed to reflect better their use. --- source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c | 6 +++--- source/blender/draw/engines/gpencil/gpencil_draw_utils.c | 6 +++--- source/blender/draw/engines/gpencil/gpencil_engine.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c index 18950f00823..d5f8d062593 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c @@ -375,7 +375,7 @@ GPUBatch *gpencil_get_buffer_stroke_geom(bGPdata *gpd, short thickness) Object *ob = draw_ctx->obact; tGPspoint *points = gpd->runtime.sbuffer; - int totpoints = gpd->runtime.sbuffer_size; + int totpoints = gpd->runtime.sbuffer_used; /* if cyclic needs more vertex */ int cyclic_add = (gpd->runtime.sbuffer_sflag & GP_STROKE_CYCLIC) ? 1 : 0; int totvertex = totpoints + cyclic_add + 2; @@ -477,7 +477,7 @@ GPUBatch *gpencil_get_buffer_point_geom(bGPdata *gpd, short thickness) Object *ob = draw_ctx->obact; tGPspoint *points = gpd->runtime.sbuffer; - int totpoints = gpd->runtime.sbuffer_size; + int totpoints = gpd->runtime.sbuffer_used; static GPUVertFormat format = {0}; static uint pos_id, color_id, thickness_id, uvdata_id, prev_pos_id; @@ -621,7 +621,7 @@ GPUBatch *gpencil_get_buffer_fill_geom(bGPdata *gpd) } const tGPspoint *points = gpd->runtime.sbuffer; - int totpoints = gpd->runtime.sbuffer_size; + int totpoints = gpd->runtime.sbuffer_used; if (totpoints < 3) { return NULL; } diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c index 181d2efbabb..9b755217946 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c @@ -1493,7 +1493,7 @@ void gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, /* Check if may need to draw the active stroke cache, only if this layer is the active layer * that is being edited. (Stroke buffer is currently stored in gp-data) */ - if (gpd->runtime.sbuffer_size > 0) { + if (gpd->runtime.sbuffer_used > 0) { if ((gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) { /* It should also be noted that sbuffer contains temporary point types * i.e. tGPspoints NOT bGPDspoints @@ -1506,7 +1506,7 @@ void gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, stl->storage->alignment_mode = (gp_style) ? gp_style->alignment_mode : GP_STYLE_FOLLOW_PATH; /* if only one point, don't need to draw buffer because the user has no time to see it */ - if (gpd->runtime.sbuffer_size > 1) { + if (gpd->runtime.sbuffer_used > 1) { if ((gp_style) && (gp_style->mode == GP_STYLE_MODE_LINE)) { stl->g_data->shgrps_drawing_stroke = gpencil_shgroup_stroke_create( vedata, @@ -1562,7 +1562,7 @@ void gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, DRW_shgroup_call( stl->g_data->shgrps_drawing_stroke, stl->g_data->batch_buffer_stroke, NULL); - if ((gpd->runtime.sbuffer_size >= 3) && + if ((gpd->runtime.sbuffer_used >= 3) && (gpd->runtime.sfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) && ((gpd->runtime.sbuffer_sflag & GP_STROKE_NOFILL) == 0) && ((brush->gpencil_settings->flag & GP_BRUSH_DISSABLE_LASSO) == 0) && diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index 5d7ec490fb6..16162645f3d 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -430,7 +430,7 @@ void GPENCIL_cache_init(void *vedata) /* need the original to avoid cow overhead while drawing */ bGPdata *gpd_orig = (bGPdata *)DEG_get_original_id(&obact_gpd->id); if (((gpd_orig->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) && - (gpd_orig->runtime.sbuffer_size > 0) && + (gpd_orig->runtime.sbuffer_used > 0) && ((gpd_orig->flag & GP_DATA_STROKE_POLYGON) == 0) && !DRW_state_is_depth() && (stl->storage->background_ready == true)) { stl->g_data->session_flag |= GP_DRW_PAINT_PAINTING; -- cgit v1.2.3 From fe47c7bf8435afee164896547067ee6092b4673a Mon Sep 17 00:00:00 2001 From: mano-wii Date: Tue, 30 Jul 2019 16:32:08 -0300 Subject: DRW manager: select engine: remove redundant calls --- source/blender/draw/engines/select/select_engine.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/select/select_engine.c b/source/blender/draw/engines/select/select_engine.c index f1fc9cbc0d6..260fe8793e6 100644 --- a/source/blender/draw/engines/select/select_engine.c +++ b/source/blender/draw/engines/select/select_engine.c @@ -196,7 +196,6 @@ static void draw_select_id_object(void *vedata, if (use_faceselect && draw_facedot) { geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me); } - DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true); DRWShadingGroup *face_shgrp; if (use_faceselect) { @@ -244,14 +243,12 @@ static void draw_select_id_object(void *vedata, Mesh *me_orig = DEG_get_original_object(ob)->data; Mesh *me_eval = ob->data; - DRW_mesh_batch_cache_validate(me_eval); struct GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me_eval); if ((me_orig->editflag & ME_EDIT_PAINT_VERT_SEL) && /* Currently vertex select supports weight paint and vertex paint. */ ((ob->mode & OB_MODE_WEIGHT_PAINT) || (ob->mode & OB_MODE_VERTEX_PAINT))) { struct GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me_eval); - DRW_mesh_batch_cache_create_requested(ob, me_eval, NULL, false, true); /* Only draw faces to mask out verts, we don't want their selection ID's. */ DRWShadingGroup *face_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_face_unif); @@ -266,9 +263,6 @@ static void draw_select_id_object(void *vedata, *r_vert_offset = me_eval->totvert + 1; } else { - const bool use_hide = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL); - DRW_mesh_batch_cache_create_requested(ob, me_eval, NULL, false, use_hide); - DRWShadingGroup *face_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_face_flat); DRW_shgroup_uniform_int_copy(face_shgrp, "offset", *(int *)&initial_offset); DRW_shgroup_call(face_shgrp, geom_faces, ob); -- cgit v1.2.3