diff options
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl.h | 2 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_mesh.c | 57 | ||||
-rw-r--r-- | source/blender/editors/uvedit/uvedit_draw.c | 234 |
3 files changed, 160 insertions, 133 deletions
diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index 9ce994adbc0..1aaedd39c85 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -167,6 +167,8 @@ enum { UVEDIT_SYNC_SEL = (1 << 6), }; +/* For Image UV editor. */ +struct GPUBatch *DRW_mesh_batch_cache_get_texpaint_loop_wire(struct Mesh *me); void DRW_mesh_cache_uvedit( struct Object *me, struct SpaceImage *sima, struct Scene *scene, uchar state, struct GPUBatch **faces, struct GPUBatch **edges, struct GPUBatch **verts, struct GPUBatch **facedots); diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index 9d3543a0d20..a10138c8e5b 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -939,7 +939,7 @@ static int mesh_render_data_mat_len_get(const MeshRenderData *rdata) return rdata->mat_len; } -static int UNUSED_FUNCTION(mesh_render_data_loops_len_get)(const MeshRenderData *rdata) +static int mesh_render_data_loops_len_get(const MeshRenderData *rdata) { BLI_assert(rdata->types & MR_DATATYPE_LOOP); return rdata->loop_len; @@ -1687,6 +1687,8 @@ typedef struct MeshBatchCache { GPUIndexBuf *edituv_visible_faces; GPUIndexBuf *edituv_visible_edges; + GPUBatch *texpaint_uv_loops; + GPUBatch *edituv_faces_strech_area; GPUBatch *edituv_faces_strech_angle; GPUBatch *edituv_faces; @@ -1997,6 +1999,8 @@ static void mesh_batch_cache_clear(Mesh *me) GPU_VERTBUF_DISCARD_SAFE(cache->edges_face_overlay); DRW_TEXTURE_FREE_SAFE(cache->edges_face_overlay_tx); + GPU_BATCH_DISCARD_SAFE(cache->texpaint_uv_loops); + mesh_batch_cache_discard_shaded_tri(cache); mesh_batch_cache_discard_uvedit(cache); @@ -4503,6 +4507,57 @@ GPUBatch *DRW_mesh_batch_cache_get_surface_texpaint_single(Mesh *me) return cache->texpaint_triangles_single; } +GPUBatch *DRW_mesh_batch_cache_get_texpaint_loop_wire(Mesh *me) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->texpaint_uv_loops == NULL) { + /* create batch from DM */ + const int datatype = MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPUV; + MeshRenderData *rdata = mesh_render_data_create(me, datatype); + + const MLoopUV *mloopuv_base = rdata->mloopuv; + if (mloopuv_base == NULL) { + return NULL; + } + + uint vidx = 0; + + static GPUVertFormat format = { 0 }; + static struct { uint uv; } attr_id; + if (format.attr_len == 0) { + attr_id.uv = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + } + + const uint vert_len = mesh_render_data_loops_len_get(rdata); + const uint poly_len = mesh_render_data_polys_len_get(rdata); + const uint idx_len = vert_len + poly_len; + + GPUIndexBufBuilder elb; + GPU_indexbuf_init_ex(&elb, GPU_PRIM_LINE_LOOP, idx_len, vert_len, true); + + GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); + GPU_vertbuf_data_alloc(vbo, vert_len); + + MPoly *mpoly = rdata->mpoly; + for (int a = 0; a < poly_len; a++, mpoly++) { + const MLoopUV *mloopuv = mloopuv_base + mpoly->loopstart; + for (int b = 0; b < mpoly->totloop; b++, mloopuv++) { + GPU_vertbuf_attr_set(vbo, attr_id.uv, vidx, mloopuv->uv); + GPU_indexbuf_add_generic_vert(&elb, vidx++); + } + GPU_indexbuf_add_primitive_restart(&elb); + } + + cache->texpaint_uv_loops = GPU_batch_create_ex(GPU_PRIM_LINE_LOOP, + vbo, GPU_indexbuf_build(&elb), + GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX); + + mesh_render_data_free(rdata); + } + return cache->texpaint_uv_loops; +} + GPUBatch *DRW_mesh_batch_cache_get_weight_overlay_edges(Mesh *me, bool use_wire, bool use_sel) { MeshBatchCache *cache = mesh_batch_cache_get(me); diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index ee3afdd5772..d9805214964 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -79,7 +79,52 @@ #include "uvedit_intern.h" -static void draw_uvs_lineloop_bmfaces(BMesh *bm, const int cd_loop_uv_offset, const uint shdr_pos); +static int draw_uvs_face_check(Scene *scene) +{ + ToolSettings *ts = scene->toolsettings; + + /* checks if we are selecting only faces */ + if (ts->uv_flag & UV_SYNC_SELECTION) { + if (ts->selectmode == SCE_SELECT_FACE) + return 2; + else if (ts->selectmode & SCE_SELECT_FACE) + return 1; + else + return 0; + } + else + return (ts->uv_selectmode == UV_SELECT_FACE); +} + +static uchar get_state(SpaceImage *sima, Scene *scene) +{ + ToolSettings *ts = scene->toolsettings; + int drawfaces = draw_uvs_face_check(scene); + const bool draw_stretch = (sima->flag & SI_DRAW_STRETCH) != 0; + uchar state = UVEDIT_EDGES | UVEDIT_DATA; + + if (drawfaces) { + state |= UVEDIT_FACEDOTS; + } + if (draw_stretch || !(sima->flag & SI_NO_DRAWFACES)) { + state |= UVEDIT_FACES; + + if (draw_stretch) { + if (sima->dt_uvstretch == SI_UVDT_STRETCH_AREA) { + state |= UVEDIT_STRETCH_AREA; + } + else { + state |= UVEDIT_STRETCH_ANGLE; + } + } + } + if (ts->uv_flag & UV_SYNC_SELECTION) { + state |= UVEDIT_SYNC_SEL; + } + return state; +} + +/* ------------------------- */ void ED_image_draw_cursor(ARegion *ar, const float cursor[2]) { @@ -147,150 +192,75 @@ void ED_image_draw_cursor(ARegion *ar, const float cursor[2]) GPU_matrix_translate_2f(-cursor[0], -cursor[1]); } -static int draw_uvs_face_check(Scene *scene) +static void draw_uvs_shadow(SpaceImage *sima, Scene *scene, Object *obedit, Depsgraph *depsgraph) { - ToolSettings *ts = scene->toolsettings; - - /* checks if we are selecting only faces */ - if (ts->uv_flag & UV_SYNC_SELECTION) { - if (ts->selectmode == SCE_SELECT_FACE) - return 2; - else if (ts->selectmode & SCE_SELECT_FACE) - return 1; - else - return 0; - } - else - return (ts->uv_selectmode == UV_SELECT_FACE); -} + Object *eval_ob = DEG_get_evaluated_object(depsgraph, obedit); + GPUBatch *faces, *edges, *verts, *facedots; + uchar state = UVEDIT_EDGES | UVEDIT_DATA; + float col[4]; + UI_GetThemeColor4fv(TH_UV_SHADOW, col); -static void draw_uvs_shadow(Object *obedit) -{ - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMesh *bm = em->bm; + DRW_mesh_cache_uvedit( + eval_ob, sima, scene, state, + &faces, &edges, &verts, &facedots); - if (bm->totloop == 0) { - return; + if (edges) { + GPU_batch_program_set_builtin(edges, GPU_SHADER_2D_UNIFORM_COLOR); + GPU_batch_uniform_4fv(edges, "color", col); + GPU_batch_draw(edges); } - - const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); - - uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - - /* draws the mesh when painting */ - immUniformThemeColor(TH_UV_SHADOW); - - draw_uvs_lineloop_bmfaces(bm, cd_loop_uv_offset, pos); - - immUnbindProgram(); } -static void draw_uvs_lineloop_bmfaces(BMesh *bm, const int cd_loop_uv_offset, const uint shdr_pos) +static void draw_uvs_texpaint(Scene *scene, Object *ob, Depsgraph *depsgraph) { - BMIter iter, liter; - BMFace *efa; - BMLoop *l; - MLoopUV *luv; - - /* For more efficiency first transfer the entire buffer to vram. */ - GPUBatch *loop_batch = immBeginBatchAtMost(GPU_PRIM_LINE_LOOP, bm->totloop); - - BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) { - if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) - continue; - - BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - immVertex2fv(shdr_pos, luv->uv); - } - } - immEnd(); - - /* Then draw each face contour separately. */ - GPU_batch_program_use_begin(loop_batch); - unsigned int index = 0; - BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) { - if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) - continue; - - GPU_batch_draw_range_ex(loop_batch, index, efa->len, false); - index += efa->len; - } - GPU_batch_program_use_end(loop_batch); - GPU_batch_discard(loop_batch); -} + Object *eval_ob = DEG_get_evaluated_object(depsgraph, ob); + Mesh *me = eval_ob->data; + ToolSettings *ts = scene->toolsettings; + GPUBatch *geom = DRW_mesh_batch_cache_get_texpaint_loop_wire(me); + float col[4]; + UI_GetThemeColor4fv(TH_UV_SHADOW, col); -static void draw_uvs_texpaint(Scene *scene, Object *ob) -{ - Mesh *me = ob->data; - Material *ma; + if (!geom) + return; - ma = give_current_material(ob, ob->actcol); + GPU_batch_program_set_builtin(geom, GPU_SHADER_2D_UNIFORM_COLOR); + GPU_batch_uniform_4fv(geom, "color", col); - if (me->mloopuv) { + const bool do_material_masking = (ts->uv_flag & UV_SHOW_SAME_IMAGE); + if (do_material_masking && me->mloopuv) { + /* Render loops that have the active material. Minize draw calls. */ MPoly *mpoly = me->mpoly; - MLoopUV *mloopuv, *mloopuv_base; - int a, b; - if (!(ma && ma->texpaintslot && ma->texpaintslot[ma->paint_active_slot].uvname && - (mloopuv = CustomData_get_layer_named(&me->ldata, CD_MLOOPUV, ma->texpaintslot[ma->paint_active_slot].uvname)))) - { - mloopuv = me->mloopuv; - } - - uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - - immUniformThemeColor(TH_UV_SHADOW); - - mloopuv_base = mloopuv; - - for (a = me->totpoly; a > 0; a--, mpoly++) { - if ((scene->toolsettings->uv_flag & UV_SHOW_SAME_IMAGE) && mpoly->mat_nr != ob->actcol - 1) - continue; - - immBegin(GPU_PRIM_LINE_LOOP, mpoly->totloop); - - mloopuv = mloopuv_base + mpoly->loopstart; - for (b = 0; b < mpoly->totloop; b++, mloopuv++) { - immVertex2fv(pos, mloopuv->uv); + uint draw_start = 0; + uint idx = 0; + bool prev_ma_match = (mpoly->mat_nr == (eval_ob->actcol - 1)); + + GPU_matrix_bind(geom->interface); + + /* TODO(fclem): If drawcall count becomes a problem in the future + * we can use multi draw indirect drawcalls for this. + * (not implemented in GPU module at the time of writing). */ + for (int a = 0; a < me->totpoly; a++, mpoly++) { + bool ma_match = (mpoly->mat_nr == (eval_ob->actcol - 1)); + if (ma_match != prev_ma_match) { + if (ma_match == false) { + GPU_batch_draw_range_ex(geom, draw_start, idx - draw_start, false); + } + else { + draw_start = idx; + } } - - immEnd(); + idx += mpoly->totloop + 1; + prev_ma_match = ma_match; } - - immUnbindProgram(); - } -} - -static uchar get_state(SpaceImage *sima, Scene *scene) -{ - ToolSettings *ts = scene->toolsettings; - int drawfaces = draw_uvs_face_check(scene); - const bool draw_stretch = (sima->flag & SI_DRAW_STRETCH) != 0; - uchar state = UVEDIT_EDGES | UVEDIT_DATA; - - if (drawfaces) { - state |= UVEDIT_FACEDOTS; - } - if (draw_stretch || !(sima->flag & SI_NO_DRAWFACES)) { - state |= UVEDIT_FACES; - - if (draw_stretch) { - if (sima->dt_uvstretch == SI_UVDT_STRETCH_AREA) { - state |= UVEDIT_STRETCH_AREA; - } - else { - state |= UVEDIT_STRETCH_ANGLE; - } + if (prev_ma_match == true) { + GPU_batch_draw_range_ex(geom, draw_start, idx - draw_start, false); } + + GPU_batch_program_use_end(geom); } - if (ts->uv_flag & UV_SYNC_SELECTION) { - state |= UVEDIT_SYNC_SEL; + else { + GPU_batch_draw(geom); } - return state; } /* draws uv's in the image space */ @@ -308,7 +278,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit, Depsgraph * /* When sync selection is enabled, all faces are drawn (except for hidden) * so if cage is the same as the final, there is no point in drawing this. */ if (!((ts->uv_flag & UV_SYNC_SELECTION) && is_cage_like_final_meshes)) { - draw_uvs_shadow(eval_ob); + draw_uvs_shadow(sima, scene, obedit, depsgraph); } } @@ -507,7 +477,7 @@ void ED_uvedit_draw_main( if (show_uvedit || show_uvshadow || show_texpaint_uvshadow) { if (show_uvshadow) { - draw_uvs_shadow(obedit); + draw_uvs_shadow(sima, scene, obedit, depsgraph); } else if (show_uvedit) { uint objects_len = 0; @@ -519,7 +489,7 @@ void ED_uvedit_draw_main( MEM_freeN(objects); } else { - draw_uvs_texpaint(scene, obact); + draw_uvs_texpaint(scene, obact, depsgraph); } if (show_uvedit && !(toolsettings->use_uv_sculpt)) |