Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/draw/intern/draw_cache_impl.h2
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c57
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c234
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))