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
path: root/source
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2018-10-01 15:55:35 +0300
committerClément Foucault <foucault.clem@gmail.com>2018-10-01 16:14:46 +0300
commit283f0ae9afe7ceceb0ad21010a8cc9006838f2b7 (patch)
tree44c802c326f6ab67a9ad02e6c584623c86d25892 /source
parent3a9ee33328a48278290af429b8b0e18fd36de1c0 (diff)
Edit UVs: Refactor drawing Shadow UV in Image Editor
Currently it's not showing the subdivided mesh (if there is a subdiv mod) and there is some sync issue if there is multiple uv image space opened. But thoses will be tackled later on. The purpose of this commit is to fix the overflow issue of IMM and speed issue.
Diffstat (limited to 'source')
-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))