diff options
-rw-r--r-- | source/blender/draw/intern/draw_cache_extract.h | 16 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_extract_mesh.c | 26 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl.h | 6 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_mesh.c | 67 | ||||
-rw-r--r-- | source/blender/editors/uvedit/uvedit_draw.c | 164 | ||||
-rw-r--r-- | source/blender/gpu/shaders/gpu_shader_2D_edituvs_stretch_vert.glsl | 20 |
6 files changed, 187 insertions, 112 deletions
diff --git a/source/blender/draw/intern/draw_cache_extract.h b/source/blender/draw/intern/draw_cache_extract.h index 9305dc6eef7..70778ca6014 100644 --- a/source/blender/draw/intern/draw_cache_extract.h +++ b/source/blender/draw/intern/draw_cache_extract.h @@ -136,8 +136,8 @@ typedef enum DRWBatchFlag { MBC_EDIT_LNOR = (1 << 6), MBC_EDIT_FACEDOTS = (1 << 7), MBC_EDIT_MESH_ANALYSIS = (1 << 8), - MBC_EDITUV_FACES_STRECH_AREA = (1 << 9), - MBC_EDITUV_FACES_STRECH_ANGLE = (1 << 10), + MBC_EDITUV_FACES_STRETCH_AREA = (1 << 9), + MBC_EDITUV_FACES_STRETCH_ANGLE = (1 << 10), MBC_EDITUV_FACES = (1 << 11), MBC_EDITUV_EDGES = (1 << 12), MBC_EDITUV_VERTS = (1 << 13), @@ -157,7 +157,7 @@ typedef enum DRWBatchFlag { } DRWBatchFlag; #define MBC_EDITUV \ - (MBC_EDITUV_FACES_STRECH_AREA | MBC_EDITUV_FACES_STRECH_ANGLE | MBC_EDITUV_FACES | \ + (MBC_EDITUV_FACES_STRETCH_AREA | MBC_EDITUV_FACES_STRETCH_ANGLE | MBC_EDITUV_FACES | \ MBC_EDITUV_EDGES | MBC_EDITUV_VERTS | MBC_EDITUV_FACEDOTS | MBC_WIRE_LOOPS_UVS) #define FOREACH_MESH_BUFFER_CACHE(batch_cache, mbc) \ @@ -183,8 +183,8 @@ typedef struct MeshBatchCache { GPUBatch *edit_fdots; GPUBatch *edit_mesh_analysis; /* Edit UVs */ - GPUBatch *edituv_faces_strech_area; - GPUBatch *edituv_faces_strech_angle; + GPUBatch *edituv_faces_stretch_area; + GPUBatch *edituv_faces_stretch_angle; GPUBatch *edituv_faces; GPUBatch *edituv_edges; GPUBatch *edituv_verts; @@ -234,6 +234,12 @@ typedef struct MeshBatchCache { /* Valid only if edge_detection is up to date. */ bool is_manifold; + /* Total areas for drawing UV Stretching. Contains the summed area in mesh + * space (`tot_area`) and the summed area in uv space (`tot_uvarea`). + * + * Only valid after `DRW_mesh_batch_cache_create_requested` has been called. */ + float tot_area, tot_uv_area; + bool no_loose_wire; } MeshBatchCache; diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh.c index d952965de35..8bca2ad2c45 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.c +++ b/source/blender/draw/intern/draw_cache_extract_mesh.c @@ -2676,7 +2676,7 @@ static void *extract_stretch_area_init(const MeshRenderData *mr, void *buf) { static GPUVertFormat format = {0}; if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "stretch", GPU_COMP_U16, 1, GPU_FETCH_INT_TO_FLOAT_UNIT); + GPU_vertformat_attr_add(&format, "ratio", GPU_COMP_U16, 1, GPU_FETCH_INT_TO_FLOAT_UNIT); } GPUVertBuf *vbo = buf; @@ -2703,7 +2703,7 @@ BLI_INLINE float area_ratio_to_stretch(float ratio, float tot_ratio, float inv_t static void mesh_stretch_area_finish(const MeshRenderData *mr, void *buf, void *UNUSED(data)) { - float totarea = 0, totuvarea = 0; + float tot_area = 0.0f, tot_uv_area = 0.0f; float *area_ratio = MEM_mallocN(sizeof(float) * mr->poly_len, __func__); if (mr->extract_type == MR_EXTRACT_BMESH) { @@ -2716,8 +2716,8 @@ static void mesh_stretch_area_finish(const MeshRenderData *mr, void *buf, void * BM_ITER_MESH_INDEX (efa, &f_iter, mr->bm, BM_FACES_OF_MESH, f) { float area = BM_face_calc_area(efa); float uvarea = BM_face_calc_area_uv(efa, uv_ofs); - totarea += area; - totuvarea += uvarea; + tot_area += area; + tot_uv_area += uvarea; area_ratio[f] = area_ratio_get(area, uvarea); } } @@ -2727,8 +2727,8 @@ static void mesh_stretch_area_finish(const MeshRenderData *mr, void *buf, void * for (int p = 0; p < mr->poly_len; p++, mpoly++) { float area = BKE_mesh_calc_poly_area(mpoly, &mr->mloop[mpoly->loopstart], mr->mvert); float uvarea = BKE_mesh_calc_poly_uv_area(mpoly, uv_data); - totarea += area; - totuvarea += uvarea; + tot_area += area; + tot_uv_area += uvarea; area_ratio[p] = area_ratio_get(area, uvarea); } } @@ -2737,21 +2737,13 @@ static void mesh_stretch_area_finish(const MeshRenderData *mr, void *buf, void * BLI_assert(0); } - float tot_ratio, inv_tot_ratio; - if (totarea < FLT_EPSILON || totuvarea < FLT_EPSILON) { - tot_ratio = 0.0f; - inv_tot_ratio = 0.0f; - } - else { - tot_ratio = totarea / totuvarea; - inv_tot_ratio = totuvarea / totarea; - } + mr->cache->tot_area = tot_area; + mr->cache->tot_uv_area = tot_uv_area; /* Convert in place to avoid an extra allocation */ uint16_t *poly_stretch = (uint16_t *)area_ratio; for (int p = 0; p < mr->poly_len; p++) { - float stretch = area_ratio_to_stretch(area_ratio[p], tot_ratio, inv_tot_ratio); - poly_stretch[p] = (1.0f - stretch) * 65534.0f; + poly_stretch[p] = area_ratio[p] * 65534.0f; } /* Copy face data for each loop. */ diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index 3e33346c7d8..970b6053cf9 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -150,8 +150,10 @@ struct GPUBatch *DRW_mesh_batch_cache_get_verts_with_select_id(struct Mesh *me); /* Object mode Wireframe overlays */ struct GPUBatch *DRW_mesh_batch_cache_get_wireframes_face(struct Mesh *me); /* edit-mesh UV editor */ -struct GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_strech_area(struct Mesh *me); -struct GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_strech_angle(struct Mesh *me); +struct GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_stretch_area(struct Mesh *me, + float *tot_area, + float *tot_uv_area); +struct GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_stretch_angle(struct Mesh *me); struct GPUBatch *DRW_mesh_batch_cache_get_edituv_faces(struct Mesh *me); struct GPUBatch *DRW_mesh_batch_cache_get_edituv_edges(struct Mesh *me); struct GPUBatch *DRW_mesh_batch_cache_get_edituv_verts(struct Mesh *me); diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index 456e21db6ed..96c677dc184 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -502,14 +502,17 @@ static void mesh_batch_cache_discard_uvedit(MeshBatchCache *cache) GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.edituv_points); GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.edituv_fdots); } - GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces_strech_area); - GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces_strech_angle); + GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces_stretch_area); + GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces_stretch_angle); GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces); GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_edges); GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_verts); GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_fdots); GPU_BATCH_DISCARD_SAFE(cache->batch.wire_loops_uvs); + cache->tot_area = 0.0f; + cache->tot_uv_area = 0.0f; + cache->batch_ready &= ~MBC_EDITUV; } @@ -577,8 +580,8 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode) GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.edituv_data); GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.fdots_edituv_data); } - GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces_strech_area); - GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces_strech_angle); + GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces_stretch_area); + GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces_stretch_angle); GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces); GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_edges); GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_verts); @@ -874,20 +877,34 @@ GPUBatch *DRW_mesh_batch_cache_get_verts_with_select_id(Mesh *me) /** \name UV Image editor API * \{ */ -GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_strech_area(Mesh *me) +/* Creates the GPUBatch for drawing the UV Stretching Area Overlay. + * Optional retrieves the total area or total uv area of the mesh. + * + * The `cache->tot_area` and cache->tot_uv_area` update are calculation are + * only valid after calling `DRW_mesh_batch_cache_create_requested`. */ +GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_stretch_area(Mesh *me, + float *tot_area, + float *tot_uv_area) { MeshBatchCache *cache = mesh_batch_cache_get(me); texpaint_request_active_uv(cache, me); - mesh_batch_cache_add_request(cache, MBC_EDITUV_FACES_STRECH_AREA); - return DRW_batch_request(&cache->batch.edituv_faces_strech_area); + mesh_batch_cache_add_request(cache, MBC_EDITUV_FACES_STRETCH_AREA); + + if (tot_area != NULL) { + *tot_area = cache->tot_area; + } + if (tot_uv_area != NULL) { + *tot_uv_area = cache->tot_uv_area; + } + return DRW_batch_request(&cache->batch.edituv_faces_stretch_area); } -GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_strech_angle(Mesh *me) +GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_stretch_angle(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); texpaint_request_active_uv(cache, me); - mesh_batch_cache_add_request(cache, MBC_EDITUV_FACES_STRECH_ANGLE); - return DRW_batch_request(&cache->batch.edituv_faces_strech_angle); + mesh_batch_cache_add_request(cache, MBC_EDITUV_FACES_STRETCH_ANGLE); + return DRW_batch_request(&cache->batch.edituv_faces_stretch_angle); } GPUBatch *DRW_mesh_batch_cache_get_edituv_faces(Mesh *me) @@ -1001,8 +1018,8 @@ void DRW_mesh_batch_cache_create_requested( } if (batch_requested & - (MBC_SURFACE | MBC_SURF_PER_MAT | MBC_WIRE_LOOPS_UVS | MBC_EDITUV_FACES_STRECH_AREA | - MBC_EDITUV_FACES_STRECH_ANGLE | MBC_EDITUV_FACES | MBC_EDITUV_EDGES | MBC_EDITUV_VERTS)) { + (MBC_SURFACE | MBC_SURF_PER_MAT | MBC_WIRE_LOOPS_UVS | MBC_EDITUV_FACES_STRETCH_AREA | + MBC_EDITUV_FACES_STRETCH_ANGLE | MBC_EDITUV_FACES | MBC_EDITUV_EDGES | MBC_EDITUV_VERTS)) { /* Modifiers will only generate an orco layer if the mesh is deformed. */ if (cache->cd_needed.orco != 0) { if (CustomData_get_layer(&me->vdata, CD_ORCO) == NULL) { @@ -1078,8 +1095,8 @@ void DRW_mesh_batch_cache_create_requested( /* We only clear the batches as they may already have been * referenced. */ GPU_BATCH_CLEAR_SAFE(cache->batch.wire_loops_uvs); - GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces_strech_area); - GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces_strech_angle); + GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces_stretch_area); + GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces_stretch_angle); GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces); GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_edges); GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_verts); @@ -1261,17 +1278,17 @@ void DRW_mesh_batch_cache_create_requested( DRW_vbo_request(cache->batch.edituv_faces, &mbufcache->vbo.uv); DRW_vbo_request(cache->batch.edituv_faces, &mbufcache->vbo.edituv_data); } - if (DRW_batch_requested(cache->batch.edituv_faces_strech_area, GPU_PRIM_TRIS)) { - DRW_ibo_request(cache->batch.edituv_faces_strech_area, &mbufcache->ibo.edituv_tris); - DRW_vbo_request(cache->batch.edituv_faces_strech_area, &mbufcache->vbo.uv); - DRW_vbo_request(cache->batch.edituv_faces_strech_area, &mbufcache->vbo.edituv_data); - DRW_vbo_request(cache->batch.edituv_faces_strech_area, &mbufcache->vbo.stretch_area); - } - if (DRW_batch_requested(cache->batch.edituv_faces_strech_angle, GPU_PRIM_TRIS)) { - DRW_ibo_request(cache->batch.edituv_faces_strech_angle, &mbufcache->ibo.edituv_tris); - DRW_vbo_request(cache->batch.edituv_faces_strech_angle, &mbufcache->vbo.uv); - DRW_vbo_request(cache->batch.edituv_faces_strech_angle, &mbufcache->vbo.edituv_data); - DRW_vbo_request(cache->batch.edituv_faces_strech_angle, &mbufcache->vbo.stretch_angle); + if (DRW_batch_requested(cache->batch.edituv_faces_stretch_area, GPU_PRIM_TRIS)) { + DRW_ibo_request(cache->batch.edituv_faces_stretch_area, &mbufcache->ibo.edituv_tris); + DRW_vbo_request(cache->batch.edituv_faces_stretch_area, &mbufcache->vbo.uv); + DRW_vbo_request(cache->batch.edituv_faces_stretch_area, &mbufcache->vbo.edituv_data); + DRW_vbo_request(cache->batch.edituv_faces_stretch_area, &mbufcache->vbo.stretch_area); + } + if (DRW_batch_requested(cache->batch.edituv_faces_stretch_angle, GPU_PRIM_TRIS)) { + DRW_ibo_request(cache->batch.edituv_faces_stretch_angle, &mbufcache->ibo.edituv_tris); + DRW_vbo_request(cache->batch.edituv_faces_stretch_angle, &mbufcache->vbo.uv); + DRW_vbo_request(cache->batch.edituv_faces_stretch_angle, &mbufcache->vbo.edituv_data); + DRW_vbo_request(cache->batch.edituv_faces_stretch_angle, &mbufcache->vbo.stretch_angle); } if (DRW_batch_requested(cache->batch.edituv_edges, GPU_PRIM_LINES)) { DRW_ibo_request(cache->batch.edituv_edges, &mbufcache->ibo.edituv_lines); diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index fe761f65702..89d3b155171 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -69,6 +69,17 @@ #include "uvedit_intern.h" +/* Struct containing the needed batches per object. + * this optimizes the way how data is requested from + * the draw manager. */ +typedef struct UVEditGPUBatches { + Object *ob_eval; + GPUBatch *faces; + GPUBatch *edges; + GPUBatch *verts; + GPUBatch *facedots; +} UVEditGPUBatches; + static int draw_uvs_face_check(const ToolSettings *ts) { /* checks if we are selecting only faces */ @@ -164,40 +175,45 @@ void ED_image_draw_cursor(ARegion *ar, const float cursor[2]) static void uvedit_get_batches(Object *ob, SpaceImage *sima, const Scene *scene, - GPUBatch **faces, - GPUBatch **edges, - GPUBatch **verts, - GPUBatch **facedots) + UVEditGPUBatches *batches, + float *tot_area, + float *tot_area_uv) { int drawfaces = draw_uvs_face_check(scene->toolsettings); const bool draw_stretch = (sima->flag & SI_DRAW_STRETCH) != 0; const bool draw_faces = (sima->flag & SI_NO_DRAWFACES) == 0; DRW_mesh_batch_cache_validate(ob->data); - *edges = DRW_mesh_batch_cache_get_edituv_edges(ob->data); - *verts = DRW_mesh_batch_cache_get_edituv_verts(ob->data); + batches->edges = DRW_mesh_batch_cache_get_edituv_edges(ob->data); + batches->verts = DRW_mesh_batch_cache_get_edituv_verts(ob->data); if (drawfaces) { - *facedots = DRW_mesh_batch_cache_get_edituv_facedots(ob->data); + batches->facedots = DRW_mesh_batch_cache_get_edituv_facedots(ob->data); } else { - *facedots = NULL; + batches->facedots = NULL; } if (draw_stretch && (sima->dt_uvstretch == SI_UVDT_STRETCH_AREA)) { - *faces = DRW_mesh_batch_cache_get_edituv_faces_strech_area(ob->data); + batches->faces = DRW_mesh_batch_cache_get_edituv_faces_stretch_area(ob->data, NULL, NULL); } else if (draw_stretch) { - *faces = DRW_mesh_batch_cache_get_edituv_faces_strech_angle(ob->data); + batches->faces = DRW_mesh_batch_cache_get_edituv_faces_stretch_angle(ob->data); } else if (draw_faces) { - *faces = DRW_mesh_batch_cache_get_edituv_faces(ob->data); + batches->faces = DRW_mesh_batch_cache_get_edituv_faces(ob->data); } else { - *faces = NULL; + batches->faces = NULL; } DRW_mesh_batch_cache_create_requested(ob, ob->data, scene, false, false); + + /* after create_requested we can load the actual areas */ + float tmp_tot_area, tmp_tot_area_uv; + DRW_mesh_batch_cache_get_edituv_faces_stretch_area(ob->data, &tmp_tot_area, &tmp_tot_area_uv); + *tot_area += tmp_tot_area; + *tot_area_uv += tmp_tot_area_uv; } static void draw_uvs_shadow(SpaceImage *UNUSED(sima), @@ -279,10 +295,14 @@ static void draw_uvs_texpaint(Scene *scene, Object *ob, Depsgraph *depsgraph) } /* draws uv's in the image space */ -static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit, Depsgraph *depsgraph) +static void draw_uvs(SpaceImage *sima, + Scene *scene, + Depsgraph *depsgraph, + UVEditGPUBatches *batch, + float tot_area_ratio, + float tot_area_ratio_inv) { - GPUBatch *faces, *edges, *verts, *facedots; - Object *ob_eval = DEG_get_evaluated_object(depsgraph, obedit); + Object *ob_eval = batch->ob_eval; const ToolSettings *ts = scene->toolsettings; float col1[4], col2[4], col3[4], transparent[4] = {0.0f, 0.0f, 0.0f, 0.0f}; @@ -296,12 +316,10 @@ 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(sima, scene, obedit, depsgraph); + draw_uvs_shadow(sima, scene, ob_eval, depsgraph); } } - uvedit_get_batches(ob_eval, sima, scene, &faces, &edges, &verts, &facedots); - bool interpedges; bool draw_stretch = (sima->flag & SI_DRAW_STRETCH) != 0; if (ts->uv_flag & UV_SYNC_SELECTION) { @@ -314,8 +332,8 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit, Depsgraph * GPU_blend_set_func_separate( GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - if (faces) { - GPU_batch_program_set_builtin(faces, + if (batch->faces) { + GPU_batch_program_set_builtin(batch->faces, (draw_stretch) ? (sima->dt_uvstretch == SI_UVDT_STRETCH_AREA) ? GPU_SHADER_2D_UV_FACES_STRETCH_AREA : GPU_SHADER_2D_UV_FACES_STRETCH_ANGLE : @@ -328,23 +346,27 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit, Depsgraph * UI_GetThemeColor4fv(TH_FACE_SELECT, col2); UI_GetThemeColor4fv(TH_EDITMESH_ACTIVE, col3); col3[3] *= 0.2; /* Simulate dithering */ - GPU_batch_uniform_4fv(faces, "faceColor", col1); - GPU_batch_uniform_4fv(faces, "selectColor", col2); - GPU_batch_uniform_4fv(faces, "activeColor", col3); + GPU_batch_uniform_4fv(batch->faces, "faceColor", col1); + GPU_batch_uniform_4fv(batch->faces, "selectColor", col2); + GPU_batch_uniform_4fv(batch->faces, "activeColor", col3); } else if (sima->dt_uvstretch == SI_UVDT_STRETCH_ANGLE) { float asp[2]; ED_space_image_get_uv_aspect(sima, &asp[0], &asp[1]); - GPU_batch_uniform_2fv(faces, "aspect", asp); + GPU_batch_uniform_2fv(batch->faces, "aspect", asp); + } + else if (sima->dt_uvstretch == SI_UVDT_STRETCH_AREA) { + GPU_batch_uniform_1f(batch->faces, "totalAreaRatio", tot_area_ratio); + GPU_batch_uniform_1f(batch->faces, "totalAreaRatioInv", tot_area_ratio_inv); } - GPU_batch_draw(faces); + GPU_batch_draw(batch->faces); if (!draw_stretch) { GPU_blend(false); } } - if (edges) { + if (batch->edges) { if (sima->flag & SI_SMOOTH_UV) { GPU_line_smooth(true); GPU_blend(true); @@ -356,14 +378,16 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit, Depsgraph * GPU_viewport_size_get_f(viewport_size); GPU_line_width(1.0f); - GPU_batch_program_set_builtin(edges, GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); - GPU_batch_uniform_4fv_array(edges, "colors", 2, (float *)dash_colors); - GPU_batch_uniform_2f( - edges, "viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); - GPU_batch_uniform_1i(edges, "colors_len", 2); /* "advanced" mode */ - GPU_batch_uniform_1f(edges, "dash_width", 4.0f); - GPU_batch_uniform_1f(edges, "dash_factor", 0.5f); - GPU_batch_draw(edges); + GPU_batch_program_set_builtin(batch->edges, GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + GPU_batch_uniform_4fv_array(batch->edges, "colors", 2, (float *)dash_colors); + GPU_batch_uniform_2f(batch->edges, + "viewport_size", + viewport_size[2] / UI_DPI_FAC, + viewport_size[3] / UI_DPI_FAC); + GPU_batch_uniform_1i(batch->edges, "colors_len", 2); /* "advanced" mode */ + GPU_batch_uniform_1f(batch->edges, "dash_width", 4.0f); + GPU_batch_uniform_1f(batch->edges, "dash_factor", 0.5f); + GPU_batch_draw(batch->edges); break; } case SI_UVDT_BLACK: @@ -376,14 +400,14 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit, Depsgraph * UI_GetThemeColor4fv(TH_EDGE_SELECT, col2); GPU_batch_program_set_builtin( - edges, (interpedges) ? GPU_SHADER_2D_UV_EDGES_SMOOTH : GPU_SHADER_2D_UV_EDGES); + batch->edges, (interpedges) ? GPU_SHADER_2D_UV_EDGES_SMOOTH : GPU_SHADER_2D_UV_EDGES); if (sima->dt_uv == SI_UVDT_OUTLINE) { /* Black Outline. */ GPU_line_width(3.0f); - GPU_batch_uniform_4f(edges, "edgeColor", 0.0f, 0.0f, 0.0f, 1.0f); - GPU_batch_uniform_4f(edges, "selectColor", 0.0f, 0.0f, 0.0f, 1.0f); - GPU_batch_draw(edges); + GPU_batch_uniform_4f(batch->edges, "edgeColor", 0.0f, 0.0f, 0.0f, 1.0f); + GPU_batch_uniform_4f(batch->edges, "selectColor", 0.0f, 0.0f, 0.0f, 1.0f); + GPU_batch_draw(batch->edges); UI_GetThemeColor4fv(TH_WIRE_EDIT, col1); } @@ -397,9 +421,9 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit, Depsgraph * /* Inner Line. Use depth test to insure selection is drawn on top. */ GPU_depth_test(true); GPU_line_width(1.0f); - GPU_batch_uniform_4fv(edges, "edgeColor", col1); - GPU_batch_uniform_4fv(edges, "selectColor", col2); - GPU_batch_draw(edges); + GPU_batch_uniform_4fv(batch->edges, "edgeColor", col1); + GPU_batch_uniform_4fv(batch->edges, "selectColor", col2); + GPU_batch_draw(batch->edges); GPU_depth_test(false); glProvokingVertex(GL_LAST_VERTEX_CONVENTION); @@ -411,44 +435,44 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit, Depsgraph * GPU_blend(false); } } - if (verts || facedots) { + if (batch->verts || batch->facedots) { UI_GetThemeColor4fv(TH_VERTEX_SELECT, col2); - if (verts) { + if (batch->verts) { const float point_size = UI_GetThemeValuef(TH_VERTEX_SIZE); const float pinned_col[4] = {1.0f, 0.0f, 0.0f, 1.0f}; /* TODO Theme? */ UI_GetThemeColor4fv(TH_VERTEX, col1); GPU_blend(true); GPU_program_point_size(true); - GPU_batch_program_set_builtin(verts, GPU_SHADER_2D_UV_VERTS); - GPU_batch_uniform_4f(verts, "vertColor", col1[0], col1[1], col1[2], 1.0f); - GPU_batch_uniform_4fv(verts, "selectColor", transparent); - GPU_batch_uniform_4fv(verts, "pinnedColor", pinned_col); - GPU_batch_uniform_1f(verts, "pointSize", (point_size + 1.5f) * M_SQRT2); - GPU_batch_uniform_1f(verts, "outlineWidth", 0.75f); - GPU_batch_draw(verts); + GPU_batch_program_set_builtin(batch->verts, GPU_SHADER_2D_UV_VERTS); + GPU_batch_uniform_4f(batch->verts, "vertColor", col1[0], col1[1], col1[2], 1.0f); + GPU_batch_uniform_4fv(batch->verts, "selectColor", transparent); + GPU_batch_uniform_4fv(batch->verts, "pinnedColor", pinned_col); + GPU_batch_uniform_1f(batch->verts, "pointSize", (point_size + 1.5f) * M_SQRT2); + GPU_batch_uniform_1f(batch->verts, "outlineWidth", 0.75f); + GPU_batch_draw(batch->verts); /* We have problem in this mode when face order make some verts * appear unselected because an adjacent face is not selected and * render after the selected face. * So, to avoid sorting verts by state we just render selected verts * on top. A bit overkill but it's simple. */ - GPU_batch_uniform_4fv(verts, "vertColor", transparent); - GPU_batch_uniform_4fv(verts, "selectColor", col2); - GPU_batch_draw(verts); + GPU_batch_uniform_4fv(batch->verts, "vertColor", transparent); + GPU_batch_uniform_4fv(batch->verts, "selectColor", col2); + GPU_batch_draw(batch->verts); GPU_blend(false); GPU_program_point_size(false); } - if (facedots) { + if (batch->facedots) { const float point_size = UI_GetThemeValuef(TH_FACEDOT_SIZE); GPU_point_size(point_size); UI_GetThemeColor4fv(TH_WIRE, col1); - GPU_batch_program_set_builtin(facedots, GPU_SHADER_2D_UV_FACEDOTS); - GPU_batch_uniform_4fv(facedots, "vertColor", col1); - GPU_batch_uniform_4fv(facedots, "selectColor", col2); - GPU_batch_draw(facedots); + GPU_batch_program_set_builtin(batch->facedots, GPU_SHADER_2D_UV_FACEDOTS); + GPU_batch_uniform_4fv(batch->facedots, "vertColor", col1); + GPU_batch_uniform_4fv(batch->facedots, "selectColor", col2); + GPU_batch_draw(batch->facedots); } } } @@ -495,10 +519,32 @@ void ED_uvedit_draw_main(SpaceImage *sima, GPU_clear_depth(1.0f); GPU_clear(GPU_DEPTH_BIT); } + + /* go over all objects and create the batches + add their areas to the total */ + UVEditGPUBatches *batches = MEM_mallocN(sizeof(UVEditGPUBatches) * objects_len, __func__); + float tot_area = 0.0f; + float tot_area_uv = 0.0f; + float tot_area_ratio = 0.0f; + float tot_area_ratio_inv = 0.0f; + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob_iter = objects[ob_index]; - draw_uvs(sima, scene, ob_iter, depsgraph); + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob_iter); + batches[ob_index].ob_eval = ob_eval; + uvedit_get_batches(ob_eval, sima, scene, &batches[ob_index], &tot_area, &tot_area_uv); + } + + if (tot_area > FLT_EPSILON && tot_area_uv > FLT_EPSILON) { + tot_area_ratio = tot_area / tot_area_uv; + tot_area_ratio_inv = tot_area_uv / tot_area; + } + + /* go over all batches created in the previous loop and draw them */ + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + UVEditGPUBatches *batch = &batches[ob_index]; + draw_uvs(sima, scene, depsgraph, batch, tot_area_ratio, tot_area_ratio_inv); } + MEM_freeN(batches); MEM_freeN(objects); } else { diff --git a/source/blender/gpu/shaders/gpu_shader_2D_edituvs_stretch_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_edituvs_stretch_vert.glsl index 0ce5504dfa8..b0fa9eaed21 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_edituvs_stretch_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_edituvs_stretch_vert.glsl @@ -4,12 +4,15 @@ uniform vec2 aspect; in vec2 pos; -#ifndef STRETCH_ANGLE -in float stretch; -#else - +#ifdef STRETCH_ANGLE in vec2 uv_angles; in float angle; + +#else +in float ratio; +uniform float totalAreaRatio; +uniform float totalAreaRatioInv; + #endif noperspective out vec4 finalColor; @@ -69,6 +72,12 @@ float angle_normalized_v2v2(vec2 v1, vec2 v2) return (q) ? a : M_PI - a; } +float area_ratio_to_stretch(float ratio, float tot_ratio, float inv_tot_ratio) +{ + ratio *= (ratio > 0.0f) ? tot_ratio : -inv_tot_ratio; + return (ratio > 1.0f) ? (1.0f / ratio) : ratio; +} + void main() { gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); @@ -80,6 +89,9 @@ void main() float stretch = 1.0 - abs(uv_angle - angle); stretch = stretch; stretch = 1.0 - stretch * stretch; +#else + float stretch = 1.0 - area_ratio_to_stretch(ratio, totalAreaRatio, -totalAreaRatioInv); + #endif finalColor = vec4(weight_to_rgb(stretch), 1.0); |