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-09-29 20:42:09 +0300
committerClément Foucault <foucault.clem@gmail.com>2018-10-01 16:14:46 +0300
commit781995a09c0b52ad2fd073510c2f7dc52383d461 (patch)
treef821cce3fa5f69435a20e450d709fec37cb95b4a /source
parenta5101de6a95647d19821bde9f8d68776ce8881fa (diff)
Edit UVs: Refactor drawing Edit UV in Image Editor
NOTE: This commit only concern edit UVs and not the "shadow" mesh displayed when texture painting. This will be address in a future commit. We now cache the uv mesh in the mesh batch cache and only reupload data on changes. Update could be more granular (and a bit faster) but it's not our main concern ATM. This should fix problem caused by the IMM api used to draw large meshes. This makes performance skyrocket compared to previous implementation. There is still a big CPU bottleneck when not in sync selection mode but it is not related to the drawing function directly.
Diffstat (limited to 'source')
-rw-r--r--source/blender/draw/intern/draw_cache_impl.h15
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c461
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c779
-rw-r--r--source/blender/gpu/CMakeLists.txt7
-rw-r--r--source/blender/gpu/GPU_shader.h7
-rw-r--r--source/blender/gpu/intern/gpu_shader.c29
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_edituvs_edges_vert.glsl29
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_edituvs_facedots_vert.glsl17
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_edituvs_faces_vert.glsl24
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_edituvs_points_vert.glsl42
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_edituvs_stretch_vert.glsl49
-rw-r--r--source/blender/gpu/shaders/gpu_shader_point_varying_color_varying_outline_aa_frag.glsl30
12 files changed, 878 insertions, 611 deletions
diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h
index 4bd0046a48a..9ce994adbc0 100644
--- a/source/blender/draw/intern/draw_cache_impl.h
+++ b/source/blender/draw/intern/draw_cache_impl.h
@@ -36,6 +36,7 @@ struct ListBase;
struct ModifierData;
struct ParticleSystem;
struct PTCacheEdit;
+struct SpaceImage;
struct Curve;
struct Lattice;
@@ -156,6 +157,20 @@ void DRW_mesh_batch_cache_get_wireframes_face_texbuf(
void DRW_mesh_cache_sculpt_coords_ensure(struct Mesh *me);
+enum {
+ UVEDIT_EDGES = (1 << 0),
+ UVEDIT_DATA = (1 << 1),
+ UVEDIT_FACEDOTS = (1 << 2),
+ UVEDIT_FACES = (1 << 3),
+ UVEDIT_STRETCH_ANGLE = (1 << 4),
+ UVEDIT_STRETCH_AREA = (1 << 5),
+ UVEDIT_SYNC_SEL = (1 << 6),
+};
+
+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);
+
/* Edit mesh bitflags (is this the right place?) */
enum {
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index 6a324aa078f..9d3543a0d20 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -31,6 +31,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_buffer.h"
#include "BLI_utildefines.h"
#include "BLI_math_vector.h"
#include "BLI_math_bits.h"
@@ -42,6 +43,7 @@
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
+#include "DNA_space_types.h"
#include "BKE_customdata.h"
#include "BKE_deform.h"
@@ -60,6 +62,10 @@
#include "DRW_render.h"
+#include "ED_image.h"
+#include "ED_mesh.h"
+#include "ED_uvedit.h"
+
#include "draw_cache_impl.h" /* own include */
static void mesh_batch_cache_clear(Mesh *me);
@@ -1672,6 +1678,24 @@ typedef struct MeshBatchCache {
GPUBatch *overlay_weight_verts;
GPUBatch *overlay_paint_edges;
+ /* 2D/UV edit */
+ GPUVertBuf *edituv_pos;
+ GPUVertBuf *edituv_area;
+ GPUVertBuf *edituv_angle;
+ GPUVertBuf *edituv_data;
+
+ GPUIndexBuf *edituv_visible_faces;
+ GPUIndexBuf *edituv_visible_edges;
+
+ GPUBatch *edituv_faces_strech_area;
+ GPUBatch *edituv_faces_strech_angle;
+ GPUBatch *edituv_faces;
+ GPUBatch *edituv_edges;
+ GPUBatch *edituv_verts;
+ GPUBatch *edituv_facedots;
+
+ char edituv_state;
+
/* arrays of bool uniform names (and value) that will be use to
* set srgb conversion for auto attribs.*/
char *auto_layer_names;
@@ -1807,6 +1831,26 @@ static void mesh_batch_cache_discard_shaded_tri(MeshBatchCache *cache)
MEM_SAFE_FREE(cache->auto_layer_is_srgb);
}
+static void mesh_batch_cache_discard_uvedit(MeshBatchCache *cache)
+{
+ GPU_VERTBUF_DISCARD_SAFE(cache->edituv_pos);
+ GPU_VERTBUF_DISCARD_SAFE(cache->edituv_area);
+ GPU_VERTBUF_DISCARD_SAFE(cache->edituv_angle);
+ GPU_VERTBUF_DISCARD_SAFE(cache->edituv_data);
+
+ GPU_INDEXBUF_DISCARD_SAFE(cache->edituv_visible_faces);
+ GPU_INDEXBUF_DISCARD_SAFE(cache->edituv_visible_edges);
+
+ GPU_BATCH_DISCARD_SAFE(cache->edituv_faces_strech_area);
+ GPU_BATCH_DISCARD_SAFE(cache->edituv_faces_strech_angle);
+ GPU_BATCH_DISCARD_SAFE(cache->edituv_faces);
+ GPU_BATCH_DISCARD_SAFE(cache->edituv_edges);
+ GPU_BATCH_DISCARD_SAFE(cache->edituv_verts);
+ GPU_BATCH_DISCARD_SAFE(cache->edituv_facedots);
+
+ cache->edituv_state = 0;
+}
+
void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode)
{
MeshBatchCache *cache = me->runtime.batch_cache;
@@ -1833,12 +1877,15 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode)
GPU_BATCH_DISCARD_SAFE(cache->facedot_with_select_id);
GPU_BATCH_DISCARD_SAFE(cache->edges_with_select_id);
GPU_BATCH_DISCARD_SAFE(cache->verts_with_select_id);
+ /* Because visible UVs depends on edit mode selection, discard everything. */
+ mesh_batch_cache_discard_uvedit(cache);
break;
case BKE_MESH_BATCH_DIRTY_ALL:
cache->is_dirty = true;
break;
case BKE_MESH_BATCH_DIRTY_SHADING:
mesh_batch_cache_discard_shaded_tri(cache);
+ mesh_batch_cache_discard_uvedit(cache);
break;
case BKE_MESH_BATCH_DIRTY_SCULPT_COORDS:
cache->is_sculpt_points_tag = true;
@@ -1952,6 +1999,8 @@ static void mesh_batch_cache_clear(Mesh *me)
mesh_batch_cache_discard_shaded_tri(cache);
+ mesh_batch_cache_discard_uvedit(cache);
+
if (cache->texpaint_triangles) {
for (int i = 0; i < cache->mat_len; ++i) {
GPU_BATCH_DISCARD_SAFE(cache->texpaint_triangles[i]);
@@ -4528,4 +4577,416 @@ void DRW_mesh_cache_sculpt_coords_ensure(Mesh *me)
}
}
+static uchar mesh_batch_cache_validate_edituvs(MeshBatchCache *cache, uchar state)
+{
+ if ((cache->edituv_state & UVEDIT_SYNC_SEL) != (state & UVEDIT_SYNC_SEL)) {
+ mesh_batch_cache_discard_uvedit(cache);
+ return state;
+ }
+ else {
+ return ((cache->edituv_state & state) ^ state);
+ }
+}
+
+/* Compute 3D & 2D areas and their sum. */
+BLI_INLINE void edit_uv_preprocess_stretch_area(
+ float (*tf_uv)[2], BMFace *efa, const float asp[2], const int cd_loop_uv_offset, uint fidx,
+ float *totarea, float *totuvarea, float (*faces_areas)[2])
+{
+ BMLoop *l;
+ BMIter liter;
+ int i;
+ BM_ITER_ELEM_INDEX(l, &liter, efa, BM_LOOPS_OF_FACE, i) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ mul_v2_v2v2(tf_uv[i], luv->uv, asp);
+ }
+ faces_areas[fidx][0] = BM_face_calc_area(efa);
+ faces_areas[fidx][1] = area_poly_v2(tf_uv, efa->len);
+
+ *totarea += faces_areas[fidx][0];
+ *totuvarea += faces_areas[fidx][1];
+}
+
+BLI_INLINE float edit_uv_get_stretch_area(float area, float uvarea)
+{
+ if (area < FLT_EPSILON || uvarea < FLT_EPSILON) {
+ return 1.0f;
+ }
+ else if (area > uvarea) {
+ return 1.0f - (uvarea / area);
+ }
+ else {
+ return 1.0f - (area / uvarea);
+ }
+}
+
+/* Compute face's normalized contour vectors. */
+BLI_INLINE void edit_uv_preprocess_stretch_angle(
+ float (*auv)[2], float (*av)[3], const int cd_loop_uv_offset, BMFace *efa, float asp[2])
+{
+ BMLoop *l;
+ BMIter liter;
+ int i;
+ BM_ITER_ELEM_INDEX(l, &liter, efa, BM_LOOPS_OF_FACE, i) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_uv_offset);
+
+ sub_v2_v2v2(auv[i], luv_prev->uv, luv->uv);
+ mul_v2_v2(auv[i], asp);
+ normalize_v2(auv[i]);
+
+ sub_v3_v3v3(av[i], l->prev->v->co, l->v->co);
+ normalize_v3(av[i]);
+ }
+}
+
+BLI_INLINE float edit_uv_get_loop_stretch_angle(
+ const float auv0[2], const float auv1[2], const float av0[3], const float av1[3])
+{
+ float uvang = angle_normalized_v2v2(auv0, auv1);
+ float ang = angle_normalized_v3v3(av0, av1);
+ float stretch = fabsf(uvang - ang) / (float)M_PI;
+ return 1.0f - pow2f(1.0f - stretch);
+}
+
+#define VERTEX_SELECT (1 << 0)
+#define VERTEX_PINNED (1 << 1)
+#define FACE_SELECT (1 << 2)
+#define FACE_ACTIVE (1 << 3)
+#define EDGE_SELECT (1 << 4)
+
+BLI_INLINE uchar edit_uv_get_face_flag(BMFace *efa, BMFace *efa_act, const int cd_loop_uv_offset, Scene *scene)
+{
+ uchar flag = 0;
+ flag |= uvedit_face_select_test(scene, efa, cd_loop_uv_offset) ? FACE_SELECT : 0;
+ flag |= (efa == efa_act) ? FACE_ACTIVE : 0;
+ return flag;
+}
+
+BLI_INLINE uchar edit_uv_get_loop_flag(BMLoop *l, const int cd_loop_uv_offset, Scene *scene)
+{
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ uchar flag = 0;
+ flag |= uvedit_uv_select_test(scene, l, cd_loop_uv_offset) ? VERTEX_SELECT : 0;
+ flag |= uvedit_edge_select_test(scene, l, cd_loop_uv_offset) ? EDGE_SELECT : 0;
+ flag |= (luv->flag & MLOOPUV_PINNED) ? VERTEX_PINNED : 0;
+ return flag;
+}
+
+static struct EditUVFormatIndex {
+ uint uvs, area, angle, flag, fdots_uvs, fdots_flag;
+} uv_attr_id = {0};
+
+static void uvedit_fill_buffer_data(
+ Object *ob, struct SpaceImage *sima, Scene *scene, uchar state, MeshBatchCache *cache,
+ GPUIndexBufBuilder *elb_faces, GPUIndexBufBuilder *elb_edges, GPUVertBuf **facedots_vbo)
+{
+ Mesh *me = ob->data;
+ BMEditMesh *embm = me->edit_btmesh;
+ BMesh *bm = embm->bm;
+ BMIter iter, liter;
+ BMFace *efa;
+ BMLoop *l;
+ MLoopUV *luv;
+ uint vidx, fidx, i;
+ float (*faces_areas)[2] = NULL;
+ float asp[2];
+ float totarea = 0.0f, totuvarea = 0.0f;
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ Image *ima = sima->image;
+ BMFace *efa_act = EDBM_uv_active_face_get(embm, false, false); /* will be set to NULL if hidden */
+
+ if (state & (UVEDIT_STRETCH_AREA | UVEDIT_STRETCH_ANGLE)) {
+ ED_space_image_get_uv_aspect(sima, &asp[0], &asp[1]);
+ }
+
+ BLI_buffer_declare_static(vec3f, vec3_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
+ BLI_buffer_declare_static(vec2f, vec2_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
+
+ if (state & UVEDIT_STRETCH_AREA) {
+ faces_areas = MEM_mallocN(sizeof(float) * 2 * bm->totface, "EDITUV faces areas");
+ }
+
+ /* Preprocess */
+ fidx = 0;
+ BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
+ /* Tag hidden faces */
+ BM_elem_flag_set(efa, BM_ELEM_TAG, uvedit_face_visible_test(scene, ob, ima, efa));
+
+ if ((state & UVEDIT_STRETCH_AREA) &&
+ BM_elem_flag_test(efa, BM_ELEM_TAG))
+ {
+ const int efa_len = efa->len;
+ float (*tf_uv)[2] = (float (*)[2])BLI_buffer_reinit_data(&vec2_buf, vec2f, efa_len);
+ edit_uv_preprocess_stretch_area(tf_uv, efa, asp, cd_loop_uv_offset, fidx++,
+ &totarea, &totuvarea, faces_areas);
+ }
+ }
+
+ vidx = 0;
+ fidx = 0;
+ BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
+ const int efa_len = efa->len;
+ float fdot[2] = {0.0f, 0.0f};
+ float (*av)[3], (*auv)[2];
+ ushort area_stretch;
+ /* Skip hidden faces. */
+ if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
+ continue;
+
+ uchar face_flag = edit_uv_get_face_flag(efa, efa_act, cd_loop_uv_offset, scene);
+ /* Face preprocess */
+ if (state & UVEDIT_STRETCH_AREA) {
+ area_stretch = edit_uv_get_stretch_area(faces_areas[fidx][0] / totarea,
+ faces_areas[fidx][1] / totuvarea) * 65534.0f;
+ }
+ if (state & UVEDIT_STRETCH_ANGLE) {
+ av = (float (*)[3])BLI_buffer_reinit_data(&vec3_buf, vec3f, efa_len);
+ auv = (float (*)[2])BLI_buffer_reinit_data(&vec2_buf, vec2f, efa_len);
+ edit_uv_preprocess_stretch_angle(auv, av, cd_loop_uv_offset, efa, asp);
+ }
+
+ BM_ITER_ELEM_INDEX(l, &liter, efa, BM_LOOPS_OF_FACE, i) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ uchar flag = face_flag | edit_uv_get_loop_flag(l, cd_loop_uv_offset, scene);
+
+ if (state & UVEDIT_STRETCH_AREA) {
+ GPU_vertbuf_attr_set(cache->edituv_area, uv_attr_id.area, vidx, &area_stretch);
+ }
+ if (state & UVEDIT_STRETCH_ANGLE) {
+ ushort angle = 65534.0f * edit_uv_get_loop_stretch_angle(auv[i], auv[(i + 1) % efa_len],
+ av[i], av[(i + 1) % efa_len]);
+ GPU_vertbuf_attr_set(cache->edituv_angle, uv_attr_id.angle, vidx, &angle);
+ }
+ if (state & UVEDIT_EDGES) {
+ GPU_vertbuf_attr_set(cache->edituv_pos, uv_attr_id.uvs, vidx, luv->uv);
+ }
+ if (state & UVEDIT_DATA) {
+ GPU_vertbuf_attr_set(cache->edituv_data, uv_attr_id.flag, vidx, &flag);
+ }
+ if (state & UVEDIT_FACES) {
+ GPU_indexbuf_add_generic_vert(elb_faces, vidx);
+ }
+ if (state & UVEDIT_EDGES) {
+ GPU_indexbuf_add_generic_vert(elb_edges, vidx);
+ }
+
+ if (state & UVEDIT_FACEDOTS) {
+ add_v2_v2(fdot, luv->uv);
+ }
+ vidx++;
+ }
+
+ if (state & UVEDIT_FACES) {
+ GPU_indexbuf_add_primitive_restart(elb_faces);
+ }
+ if (state & UVEDIT_EDGES) {
+ GPU_indexbuf_add_primitive_restart(elb_edges);
+ }
+
+ if (state & UVEDIT_FACEDOTS) {
+ mul_v2_fl(fdot, 1.0f / (float)efa->len);
+ GPU_vertbuf_attr_set(*facedots_vbo, uv_attr_id.fdots_uvs, fidx, fdot);
+ GPU_vertbuf_attr_set(*facedots_vbo, uv_attr_id.fdots_flag, fidx, &face_flag);
+ }
+ fidx++;
+ }
+
+ if (faces_areas) {
+ MEM_freeN(faces_areas);
+ }
+
+ BLI_buffer_free(&vec3_buf);
+ BLI_buffer_free(&vec2_buf);
+
+ if (vidx == 0) {
+ GPU_VERTBUF_DISCARD_SAFE(cache->edituv_area);
+ GPU_VERTBUF_DISCARD_SAFE(cache->edituv_angle);
+ GPU_VERTBUF_DISCARD_SAFE(cache->edituv_pos);
+ GPU_VERTBUF_DISCARD_SAFE(cache->edituv_data);
+ GPU_VERTBUF_DISCARD_SAFE(*facedots_vbo);
+ }
+
+ if (vidx < bm->totloop) {
+ if (cache->edituv_area && (state & UVEDIT_STRETCH_AREA)) {
+ GPU_vertbuf_data_resize(cache->edituv_area, vidx);
+ }
+ if (cache->edituv_angle && (state & UVEDIT_STRETCH_ANGLE)) {
+ GPU_vertbuf_data_resize(cache->edituv_angle, vidx);
+ }
+ if (cache->edituv_pos && (state & UVEDIT_EDGES)) {
+ GPU_vertbuf_data_resize(cache->edituv_pos, vidx);
+ }
+ if (cache->edituv_data && (state & UVEDIT_DATA)) {
+ GPU_vertbuf_data_resize(cache->edituv_data, vidx);
+ }
+ }
+ if (fidx < bm->totface) {
+ if (*facedots_vbo) {
+ GPU_vertbuf_data_resize(*facedots_vbo, fidx);
+ }
+ }
+}
+
+static void mesh_batch_cache_create_uvedit_buffers(
+ Object *ob, struct SpaceImage *sima, Scene *scene, MeshBatchCache *cache, uchar state)
+{
+ GPUVertBuf *facedots_vbo = NULL;
+
+ if (state == 0) {
+ return;
+ }
+
+ Mesh *me = ob->data;
+ BMEditMesh *embm = me->edit_btmesh;
+ BMesh *bm = embm->bm;
+
+ static GPUVertFormat format_pos = { 0 };
+ static GPUVertFormat format_area = { 0 };
+ static GPUVertFormat format_angle = { 0 };
+ static GPUVertFormat format_flag = { 0 };
+ static GPUVertFormat format_facedots = { 0 };
+
+ if (format_pos.attr_len == 0) {
+ uv_attr_id.uvs = GPU_vertformat_attr_add(&format_pos, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uv_attr_id.area = GPU_vertformat_attr_add(&format_area, "stretch", GPU_COMP_U16, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ uv_attr_id.angle = GPU_vertformat_attr_add(&format_angle, "stretch", GPU_COMP_U16, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ uv_attr_id.flag = GPU_vertformat_attr_add(&format_flag, "flag", GPU_COMP_U8, 1, GPU_FETCH_INT);
+
+ uv_attr_id.fdots_uvs = GPU_vertformat_attr_add(&format_facedots, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uv_attr_id.fdots_flag = GPU_vertformat_attr_add(&format_facedots, "flag", GPU_COMP_U8, 1, GPU_FETCH_INT);
+ }
+
+ const uint vert_len = bm->totloop;
+ const uint idx_len = bm->totloop + bm->totface;
+ const uint face_len = bm->totface;
+
+ if (state & UVEDIT_EDGES) {
+ cache->edituv_pos = GPU_vertbuf_create_with_format(&format_pos);
+ GPU_vertbuf_data_alloc(cache->edituv_pos, vert_len);
+ }
+ if (state & UVEDIT_DATA) {
+ cache->edituv_data = GPU_vertbuf_create_with_format(&format_flag);
+ GPU_vertbuf_data_alloc(cache->edituv_data, vert_len);
+ }
+ if (state & UVEDIT_STRETCH_AREA) {
+ cache->edituv_area = GPU_vertbuf_create_with_format(&format_area);
+ GPU_vertbuf_data_alloc(cache->edituv_area, vert_len);
+ }
+ if (state & UVEDIT_STRETCH_ANGLE) {
+ cache->edituv_angle = GPU_vertbuf_create_with_format(&format_angle);
+ GPU_vertbuf_data_alloc(cache->edituv_angle, vert_len);
+ }
+ if (state & UVEDIT_FACEDOTS) {
+ facedots_vbo = GPU_vertbuf_create_with_format(&format_facedots);
+ GPU_vertbuf_data_alloc(facedots_vbo, face_len);
+ }
+
+ /* NOTE: we could use the same index buffer for both primitive type (it's the same indices)
+ * but since GPU_PRIM_LINE_LOOP does not exist in vulkan, make it future proof. */
+ GPUIndexBufBuilder elb_faces, elb_edges;
+ if (state & UVEDIT_EDGES) {
+ GPU_indexbuf_init_ex(&elb_edges, GPU_PRIM_LINE_LOOP, idx_len, vert_len, true);
+ }
+ if (state & UVEDIT_FACES) {
+ GPU_indexbuf_init_ex(&elb_faces, GPU_PRIM_TRI_FAN, idx_len, vert_len, true);
+ }
+
+ uvedit_fill_buffer_data(ob, sima, scene, state, cache, &elb_faces, &elb_edges, &facedots_vbo);
+
+ if (state & UVEDIT_EDGES) {
+ cache->edituv_visible_edges = GPU_indexbuf_build(&elb_edges);
+ }
+ if (state & UVEDIT_FACES) {
+ cache->edituv_visible_faces = GPU_indexbuf_build(&elb_faces);
+ }
+ if ((state & UVEDIT_FACEDOTS) && facedots_vbo) {
+ cache->edituv_facedots = GPU_batch_create_ex(GPU_PRIM_POINTS, facedots_vbo, NULL, GPU_BATCH_OWNS_VBO);
+ }
+
+ cache->edituv_state |= state;
+}
+
+void DRW_mesh_cache_uvedit(
+ Object *ob, struct SpaceImage *sima, Scene *scene, uchar state,
+ GPUBatch **faces, GPUBatch **edges, GPUBatch **verts, GPUBatch **facedots)
+{
+ Mesh *me = ob->data;
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ uchar missing_state = mesh_batch_cache_validate_edituvs(cache, state);
+
+ mesh_batch_cache_create_uvedit_buffers(ob, sima, scene, cache, missing_state);
+
+ /* Bail out if there is nothing to draw. */
+ if (cache->edituv_data == NULL) {
+ *faces = *edges = *verts = *facedots = NULL;
+ return;
+ }
+
+ /* Faces */
+ if (state & UVEDIT_STRETCH_AREA) {
+ if (cache->edituv_faces_strech_area == NULL) {
+ cache->edituv_faces_strech_area = GPU_batch_create(GPU_PRIM_TRI_FAN,
+ cache->edituv_pos,
+ cache->edituv_visible_faces);
+ GPU_batch_vertbuf_add_ex(cache->edituv_faces_strech_area,
+ cache->edituv_area, false);
+ }
+ *faces = cache->edituv_faces_strech_area;
+ }
+ else if (state & UVEDIT_STRETCH_ANGLE) {
+ if (cache->edituv_faces_strech_angle == NULL) {
+ cache->edituv_faces_strech_angle = GPU_batch_create(GPU_PRIM_TRI_FAN,
+ cache->edituv_pos,
+ cache->edituv_visible_faces);
+ GPU_batch_vertbuf_add_ex(cache->edituv_faces_strech_angle,
+ cache->edituv_angle, false);
+ }
+ *faces = cache->edituv_faces_strech_angle;
+ }
+ else if (state & UVEDIT_FACES) {
+ if (cache->edituv_faces == NULL) {
+ cache->edituv_faces = GPU_batch_create(GPU_PRIM_TRI_FAN,
+ cache->edituv_pos,
+ cache->edituv_visible_faces);
+ GPU_batch_vertbuf_add_ex(cache->edituv_faces,
+ cache->edituv_data, false);
+ }
+ *faces = cache->edituv_faces;
+ }
+ else {
+ *faces = NULL;
+ }
+
+ {
+ if (cache->edituv_edges == NULL) {
+ cache->edituv_edges = GPU_batch_create(GPU_PRIM_LINE_LOOP,
+ cache->edituv_pos,
+ cache->edituv_visible_edges);
+ GPU_batch_vertbuf_add_ex(cache->edituv_edges,
+ cache->edituv_data, false);
+ }
+ *edges = cache->edituv_edges;
+ }
+
+ {
+ if (cache->edituv_verts == NULL) {
+ cache->edituv_verts = GPU_batch_create(GPU_PRIM_POINTS,
+ cache->edituv_pos,
+ NULL);
+ GPU_batch_vertbuf_add_ex(cache->edituv_verts,
+ cache->edituv_data, false);
+ }
+ *verts = cache->edituv_verts;
+ }
+
+ if (state & UVEDIT_FACEDOTS) {
+ *facedots = cache->edituv_facedots;
+ }
+ else {
+ *facedots = NULL;
+ }
+}
+
/** \} */
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index 57fed0b860f..ee3afdd5772 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -43,6 +43,8 @@
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
+#include "../../draw/intern/draw_cache_impl.h"
+
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_buffer.h"
@@ -65,6 +67,7 @@
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
#include "GPU_state.h"
+#include "GPU_draw.h"
#include "ED_image.h"
#include "ED_mesh.h"
@@ -184,211 +187,6 @@ static void draw_uvs_shadow(Object *obedit)
immUnbindProgram();
}
-static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, Object *obedit, BMEditMesh *em, const BMFace *efa_act)
-{
- BMesh *bm = em->bm;
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
- Image *ima = sima->image;
- float aspx, aspy, col[4];
- int i;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
-
- BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
- BLI_buffer_declare_static(vec2f, tf_uvorig_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
-
- ED_space_image_get_uv_aspect(sima, &aspx, &aspy);
-
- switch (sima->dt_uvstretch) {
- case SI_UVDT_STRETCH_AREA:
- {
- float totarea = 0.0f, totuvarea = 0.0f, areadiff, uvarea, area;
-
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- const int efa_len = efa->len;
- float (*tf_uv)[2] = (float (*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, efa_len);
- float (*tf_uvorig)[2] = (float (*)[2])BLI_buffer_reinit_data(&tf_uvorig_buf, vec2f, efa_len);
-
- BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- copy_v2_v2(tf_uvorig[i], luv->uv);
- }
-
- uv_poly_copy_aspect(tf_uvorig, tf_uv, aspx, aspy, efa->len);
-
- totarea += BM_face_calc_area(efa);
- totuvarea += area_poly_v2(tf_uv, efa->len);
-
- if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
- BM_elem_flag_enable(efa, BM_ELEM_TAG);
- }
- else {
- if (efa == efa_act) {
- efa_act = NULL;
- }
- BM_elem_flag_disable(efa, BM_ELEM_TAG);
- }
- }
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- if (totarea < FLT_EPSILON || totuvarea < FLT_EPSILON) {
- col[0] = 1.0;
- col[1] = col[2] = 0.0;
-
- immUniformColor3fv(col);
-
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
- immBegin(GPU_PRIM_TRI_FAN, efa->len);
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- immVertex2fv(pos, luv->uv);
- }
-
- immEnd();
- }
- }
- }
- else {
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
- const int efa_len = efa->len;
- float (*tf_uv)[2] = (float (*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, efa_len);
- float (*tf_uvorig)[2] = (float (*)[2])BLI_buffer_reinit_data(&tf_uvorig_buf, vec2f, efa_len);
-
- area = BM_face_calc_area(efa) / totarea;
-
- BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- copy_v2_v2(tf_uvorig[i], luv->uv);
- }
-
- uv_poly_copy_aspect(tf_uvorig, tf_uv, aspx, aspy, efa->len);
-
- uvarea = area_poly_v2(tf_uv, efa->len) / totuvarea;
-
- if (area < FLT_EPSILON || uvarea < FLT_EPSILON)
- areadiff = 1.0f;
- else if (area > uvarea)
- areadiff = 1.0f - (uvarea / area);
- else
- areadiff = 1.0f - (area / uvarea);
-
- BKE_defvert_weight_to_rgb(col, areadiff);
- immUniformColor3fv(col);
-
- /* TODO: use editmesh tessface */
- immBegin(GPU_PRIM_TRI_FAN, efa->len);
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- immVertex2fv(pos, luv->uv);
- }
-
- immEnd();
- }
- }
- }
-
- immUnbindProgram();
-
- break;
- }
- case SI_UVDT_STRETCH_ANGLE:
- {
- float a;
-
- BLI_buffer_declare_static(float, uvang_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
- BLI_buffer_declare_static(float, ang_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
- BLI_buffer_declare_static(vec3f, av_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
- BLI_buffer_declare_static(vec2f, auv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
-
- col[3] = 0.5f; /* hard coded alpha, not that nice */
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
-
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
- const int efa_len = efa->len;
- float (*tf_uv)[2] = (float (*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, efa_len);
- float (*tf_uvorig)[2] = (float (*)[2])BLI_buffer_reinit_data(&tf_uvorig_buf, vec2f, efa_len);
- float *uvang = BLI_buffer_reinit_data(&uvang_buf, float, efa_len);
- float *ang = BLI_buffer_reinit_data(&ang_buf, float, efa_len);
- float (*av)[3] = (float (*)[3])BLI_buffer_reinit_data(&av_buf, vec3f, efa_len);
- float (*auv)[2] = (float (*)[2])BLI_buffer_reinit_data(&auv_buf, vec2f, efa_len);
- int j;
-
- BM_elem_flag_enable(efa, BM_ELEM_TAG);
-
- BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- copy_v2_v2(tf_uvorig[i], luv->uv);
- }
-
- uv_poly_copy_aspect(tf_uvorig, tf_uv, aspx, aspy, efa_len);
-
- j = efa_len - 1;
- BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
- sub_v2_v2v2(auv[i], tf_uv[j], tf_uv[i]); normalize_v2(auv[i]);
- sub_v3_v3v3(av[i], l->prev->v->co, l->v->co); normalize_v3(av[i]);
- j = i;
- }
-
- for (i = 0; i < efa_len; i++) {
-#if 0
- /* Simple but slow, better reuse normalized vectors
- * (Not ported to bmesh, copied for reference) */
- uvang1 = RAD2DEG(angle_v2v2v2(tf_uv[3], tf_uv[0], tf_uv[1]));
- ang1 = RAD2DEG(angle_v3v3v3(efa->v4->co, efa->v1->co, efa->v2->co));
-#endif
- uvang[i] = angle_normalized_v2v2(auv[i], auv[(i + 1) % efa_len]);
- ang[i] = angle_normalized_v3v3(av[i], av[(i + 1) % efa_len]);
- }
-
- /* TODO: use editmesh tessface */
- immBegin(GPU_PRIM_TRI_FAN, efa->len);
- BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- a = fabsf(uvang[i] - ang[i]) / (float)M_PI;
- BKE_defvert_weight_to_rgb(col, 1.0f - pow2f(1.0f - a));
- immAttrib3fv(color, col);
- immVertex2fv(pos, luv->uv);
- }
- immEnd();
- }
- else {
- if (efa == efa_act)
- efa_act = NULL;
- BM_elem_flag_disable(efa, BM_ELEM_TAG);
- }
- }
-
- immUnbindProgram();
-
- BLI_buffer_free(&uvang_buf);
- BLI_buffer_free(&ang_buf);
- BLI_buffer_free(&av_buf);
- BLI_buffer_free(&auv_buf);
-
- break;
- }
- }
-
- BLI_buffer_free(&tf_uv_buf);
- BLI_buffer_free(&tf_uvorig_buf);
-}
-
static void draw_uvs_lineloop_bmfaces(BMesh *bm, const int cd_loop_uv_offset, const uint shdr_pos)
{
BMIter iter, liter;
@@ -467,459 +265,218 @@ static void draw_uvs_texpaint(Scene *scene, Object *ob)
}
}
-static void draw_uvs_looptri(BMEditMesh *em, unsigned int *r_loop_index, const int cd_loop_uv_offset, unsigned int pos)
+static uchar get_state(SpaceImage *sima, Scene *scene)
{
- unsigned int i = *r_loop_index;
- BMFace *f = em->looptris[i][0]->f;
- do {
- unsigned int j;
- for (j = 0; j < 3; j++) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(em->looptris[i][j], cd_loop_uv_offset);
- immVertex2fv(pos, luv->uv);
+ 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;
+ }
}
- i++;
- } while (i != em->tottri && (f == em->looptris[i][0]->f));
- *r_loop_index = i - 1;
+ }
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ state |= UVEDIT_SYNC_SEL;
+ }
+ return state;
}
/* draws uv's in the image space */
static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit, Depsgraph *depsgraph)
{
- ToolSettings *ts;
- Mesh *me = obedit->data;
- BMEditMesh *em = me->edit_btmesh;
- BMesh *bm = em->bm;
- BMFace *efa, *efa_act;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
- float col1[4], col2[4];
- float pointsize;
- int drawfaces, interpedges;
- Image *ima = sima->image;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
-
- unsigned int pos, color;
-
- efa_act = EDBM_uv_active_face_get(em, false, false); /* will be set to NULL if hidden */
- ts = scene->toolsettings;
-
- drawfaces = draw_uvs_face_check(scene);
- if (ts->uv_flag & UV_SYNC_SELECTION)
- interpedges = (ts->selectmode & SCE_SELECT_VERTEX);
- else
- interpedges = (ts->uv_selectmode == UV_SELECT_VERTEX);
-
- /* 1. draw shadow mesh */
+ GPUBatch *faces, *edges, *verts, *facedots;
+ Object *eval_ob = DEG_get_evaluated_object(depsgraph, obedit);
+ ToolSettings *ts = scene->toolsettings;
+ float col1[4], col2[4], col3[4], transparent[4] = {0.0f, 0.0f, 0.0f, 0.0f};
if (sima->flag & SI_DRAWSHADOW) {
- Object *ob_cage_eval = DEG_get_evaluated_object(depsgraph, obedit);
/* XXX TODO: Need to check if shadow mesh is different than original mesh. */
- bool is_cage_like_final_meshes = (ob_cage_eval == obedit);
+ bool is_cage_like_final_meshes = true;
/* 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) == 0) || is_cage_like_final_meshes) {
- draw_uvs_shadow(ob_cage_eval);
+ if (!((ts->uv_flag & UV_SYNC_SELECTION) && is_cage_like_final_meshes)) {
+ draw_uvs_shadow(eval_ob);
}
}
- if (bm->totloop == 0) {
- return;
- }
+ uchar state = get_state(sima, scene);
- /* 2. draw colored faces */
+ DRW_mesh_cache_uvedit(
+ eval_ob, sima, scene, state,
+ &faces, &edges, &verts, &facedots);
- if (sima->flag & SI_DRAW_STRETCH) {
- draw_uvs_stretch(sima, scene, obedit, em, efa_act);
+ bool interpedges;
+ bool do_elem_order_fix = (ts->uv_flag & UV_SYNC_SELECTION) && (ts->selectmode & SCE_SELECT_FACE);
+ bool do_selected_edges = ((sima->flag & SI_NO_DRAWEDGES) == 0);
+ bool draw_stretch = (state & (UVEDIT_STRETCH_AREA | UVEDIT_STRETCH_ANGLE)) != 0;
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ interpedges = (ts->selectmode & SCE_SELECT_VERTEX) != 0;
}
else {
- unsigned int tri_count = 0;
- BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
- if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
- BM_elem_flag_enable(efa, BM_ELEM_TAG);
- tri_count += efa->len - 2;
- }
- else {
- BM_elem_flag_disable(efa, BM_ELEM_TAG);
- }
- }
-
- if (tri_count && !(sima->flag & SI_NO_DRAWFACES)) {
- /* draw transparent faces */
- UI_GetThemeColor4fv(TH_FACE, col1);
- UI_GetThemeColor4fv(TH_FACE_SELECT, col2);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- GPU_blend(true);
-
- GPUVertFormat *format = immVertexFormat();
- pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
-
- GPUBatch *face_batch = immBeginBatch(GPU_PRIM_TRIS, tri_count * 3);
- for (unsigned int i = 0; i < em->tottri; i++) {
- efa = em->looptris[i][0]->f;
- if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
- const bool is_select = uvedit_face_select_test(scene, efa, cd_loop_uv_offset);
-
- if (efa == efa_act) {
- /* only once */
- float tmp_col[4];
- UI_GetThemeColor4fv(TH_EDITMESH_ACTIVE, tmp_col);
- immAttrib4fv(color, tmp_col);
- }
- else {
- immAttrib4fv(color, is_select ? col2 : col1);
- }
-
- draw_uvs_looptri(em, &i, cd_loop_uv_offset, pos);
- }
- }
- immEnd();
-
- /* XXX performance: we should not create and throw away result. */
- GPU_batch_draw(face_batch);
- GPU_batch_program_use_end(face_batch);
- GPU_batch_discard(face_batch);
-
- immUnbindProgram();
-
- GPU_blend(false);
- }
- else {
- if (efa_act && !uvedit_face_visible_test(scene, obedit, ima, efa_act)) {
- efa_act = NULL;
- }
- }
- }
-
- /* 3. draw active face stippled */
- /* (removed during OpenGL upgrade, reimplement if needed) */
-
- /* 4. draw edges */
-
- if (sima->flag & SI_SMOOTH_UV) {
- GPU_line_smooth(true);
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ interpedges = (ts->uv_selectmode == UV_SELECT_VERTEX);
}
- pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- switch (sima->dt_uv) {
- case SI_UVDT_DASH:
- {
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ if (faces) {
+ GPU_batch_program_set_builtin(faces, (draw_stretch)
+ ? GPU_SHADER_2D_UV_FACES_STRETCH
+ : GPU_SHADER_2D_UV_FACES);
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
-
- immUniform1i("colors_len", 2); /* "advanced" mode */
- immUniformArray4fv("colors", (float *)(float[][4]){{0.56f, 0.56f, 0.56f, 1.0f}, {0.07f, 0.07f, 0.07f, 1.0f}}, 2);
- immUniform1f("dash_width", 4.0f);
- GPU_line_width(1.0f);
+ if (!draw_stretch) {
+ GPU_blend(true);
- break;
+ UI_GetThemeColor4fv(TH_FACE, col1);
+ 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);
}
- case SI_UVDT_BLACK: /* black/white */
- case SI_UVDT_WHITE:
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- if (sima->dt_uv == SI_UVDT_WHITE) {
- immUniformColor3f(1.0f, 1.0f, 1.0f);
- }
- else {
- immUniformColor3f(0.0f, 0.0f, 0.0f);
- }
- GPU_line_width(1.0f);
-
- break;
- case SI_UVDT_OUTLINE:
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- imm_cpack(0x0);
- GPU_line_width(3.0f);
- break;
- }
+ GPU_batch_draw(faces);
- /* For more efficiency first transfer the entire buffer to vram. */
- GPUBatch *loop_batch = immBeginBatchAtMost(GPU_PRIM_LINE_LOOP, bm->totloop);
- GPUVertBuf *loop_vbo = loop_batch->verts[0];
- 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(pos, luv->uv);
+ if (!draw_stretch) {
+ GPU_blend(false);
}
}
- immEnd();
-
- /* Then draw each face contour separately. */
- if (loop_vbo->vertex_len != 0) {
- GPU_batch_program_use_begin(loop_batch);
- unsigned int index = 0, loop_vbo_count;
- 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;
+ if (edges) {
+ if (sima->flag & SI_SMOOTH_UV) {
+ GPU_line_smooth(true);
+ GPU_blend(true);
}
- loop_vbo_count = index;
- GPU_batch_program_use_end(loop_batch);
- immUnbindProgram();
-
-
- if (sima->dt_uv == SI_UVDT_OUTLINE) {
- GPU_line_width(1.0f);
- UI_GetThemeColor4fv(TH_WIRE_EDIT, col2);
-
- if ((sima->flag & SI_NO_DRAWEDGES) == 0) {
- int sel;
- UI_GetThemeColor4fv(TH_EDGE_SELECT, col1);
-
- if (interpedges) {
- /* Create a color buffer. */
- static GPUVertFormat format = { 0 };
- static uint shdr_col;
- if (format.attr_len == 0) {
- shdr_col = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- }
-
- GPUVertBuf *vbo_col = GPU_vertbuf_create_with_format(&format);
- GPU_vertbuf_data_alloc(vbo_col, loop_vbo_count);
-
- index = 0;
- 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) {
- sel = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
- GPU_vertbuf_attr_set(vbo_col, shdr_col, index++, sel ? col1 : col2);
- }
- }
- /* Reuse the UV buffer and add the color buffer. */
- GPU_batch_vertbuf_add_ex(loop_batch, vbo_col, true);
-
- /* Now draw each face contour separately with another builtin program. */
- GPU_batch_program_set_builtin(loop_batch, GPU_SHADER_2D_SMOOTH_COLOR);
- GPU_matrix_bind(loop_batch->interface);
-
- GPU_batch_program_use_begin(loop_batch);
- 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);
+ switch (sima->dt_uv) {
+ case SI_UVDT_DASH:
+ {
+ float dash_colors[2][4] = {{0.56f, 0.56f, 0.56f, 1.0f}, {0.07f, 0.07f, 0.07f, 1.0f}};
+ float viewport_size[4];
+ 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_draw(edges);
+ break;
+ }
+ case SI_UVDT_BLACK:
+ case SI_UVDT_WHITE:
+ {
+ GPU_line_width(1.0f);
+ GPU_batch_program_set_builtin(edges, GPU_SHADER_2D_UNIFORM_COLOR);
+ if (sima->dt_uv == SI_UVDT_WHITE) {
+ GPU_batch_uniform_4f(edges, "color", 1.0f, 1.0f, 1.0f, 1.0f);
}
else {
- GPUVertFormat *format = immVertexFormat();
- pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
-
- /* Use batch here to avoid problems with `IMM_BUFFER_SIZE`. */
- GPUBatch *flat_edges_batch = immBeginBatchAtMost(GPU_PRIM_LINES, loop_vbo_count * 2);
- 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) {
- sel = uvedit_edge_select_test(scene, l, cd_loop_uv_offset);
- immAttrib4fv(color, sel ? col1 : col2);
-
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- immVertex2fv(pos, luv->uv);
- luv = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
- immVertex2fv(pos, luv->uv);
- }
- }
- immEnd();
-
- GPU_batch_draw(flat_edges_batch);
- GPU_batch_discard(flat_edges_batch);
-
- immUnbindProgram();
- }
- }
- else {
- GPU_batch_uniform_4fv(loop_batch, "color", col2);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- /* no nice edges */
- GPU_batch_program_use_begin(loop_batch);
- 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_uniform_4f(edges, "color", 0.0f, 0.0f, 0.0f, 1.0f);
}
- GPU_batch_program_use_end(loop_batch);
- immUnbindProgram();
+ GPU_batch_draw(edges);
+ break;
}
- }
- }
- else {
- immUnbindProgram();
- }
-
- GPU_batch_discard(loop_batch);
-
- if (sima->flag & SI_SMOOTH_UV) {
- GPU_line_smooth(false);
- GPU_blend(false);
- }
-
- /* 5. draw face centers */
-
- if (drawfaces) {
- float cent[2];
- bool col_set = false;
-
- GPUVertFormat *format = immVertexFormat();
- pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
-
- pointsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
- GPU_point_size(pointsize);
-
- immBeginAtMost(GPU_PRIM_POINTS, bm->totface);
-
- /* unselected faces */
-
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
- continue;
-
- if (!uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) {
- /* Only set color for the first face */
- if (!col_set) {
- UI_GetThemeColor3fv(TH_WIRE, col1);
- immAttrib3fv(color, col1);
-
- col_set = true;
+ case SI_UVDT_OUTLINE:
+ {
+ GPU_line_width(3.0f);
+ GPU_batch_program_set_builtin(edges, GPU_SHADER_2D_UNIFORM_COLOR);
+ GPU_batch_uniform_4f(edges, "color", 0.0f, 0.0f, 0.0f, 1.0f);
+ GPU_batch_draw(edges);
+
+ UI_GetThemeColor4fv(TH_WIRE_EDIT, col1);
+ UI_GetThemeColor4fv(TH_EDGE_SELECT, col2);
+
+ /* We could modify the vbo's data filling instead of modifying the provoking vert. */
+ glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);
+
+ GPU_line_width(1.0f);
+ GPU_batch_program_set_builtin(edges, (interpedges)
+ ? GPU_SHADER_2D_UV_EDGES_SMOOTH
+ : GPU_SHADER_2D_UV_EDGES);
+ GPU_batch_uniform_4fv(edges, "edgeColor", col1);
+ GPU_batch_uniform_4fv(edges, "selectColor", do_selected_edges ? col2 : col1);
+ GPU_batch_draw(edges);
+
+ if (do_elem_order_fix && do_selected_edges) {
+ /* We have problem in this mode when face order make some edges
+ * appear unselected because an adjacent face is not selected and
+ * render after the selected face.
+ * So, to avoid sorting edges by state we just render selected edges
+ * on top. A bit overkill but it's simple. */
+ GPU_blend(true);
+ GPU_batch_uniform_4fv(edges, "edgeColor", transparent);
+ GPU_batch_uniform_4fv(edges, "selectColor", col2);
+ GPU_batch_draw(edges);
+ GPU_blend(false);
}
-
- uv_poly_center(efa, cent, cd_loop_uv_offset);
- immVertex2fv(pos, cent);
+ glProvokingVertex(GL_LAST_VERTEX_CONVENTION);
+ break;
}
}
-
- col_set = false;
-
- /* selected faces */
-
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
- continue;
-
- if (uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) {
- /* Only set color for the first face */
- if (!col_set) {
- UI_GetThemeColor3fv(TH_FACE_DOT, col1);
- immAttrib3fv(color, col1);
-
- col_set = true;
- }
-
- uv_poly_center(efa, cent, cd_loop_uv_offset);
- immVertex2fv(pos, cent);
- }
+ if (sima->flag & SI_SMOOTH_UV) {
+ GPU_line_smooth(false);
+ GPU_blend(false);
}
-
- immEnd();
-
- immUnbindProgram();
}
-
- /* 6. draw uv vertices */
-
- if (drawfaces != 2) { /* 2 means Mesh Face Mode */
- pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- /* unselected uvs */
- immUniformThemeColor(TH_VERTEX);
- pointsize = UI_GetThemeValuef(TH_VERTEX_SIZE);
- GPU_point_size(pointsize);
-
- immBeginAtMost(GPU_PRIM_POINTS, 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);
- if (!uvedit_uv_select_test(scene, l, cd_loop_uv_offset))
- immVertex2fv(pos, luv->uv);
+ if (verts || facedots) {
+ float pointsize = UI_GetThemeValuef(TH_VERTEX_SIZE);
+ UI_GetThemeColor4fv(TH_VERTEX_SELECT, col2);
+ if (verts) {
+ float pinned_col[4] = {1.0f, 0.0f, 0.0f, 1.0f}; /* TODO Theme? */
+ UI_GetThemeColor4fv(TH_VERTEX, col1);
+ GPU_blend(true);
+ GPU_enable_program_point_size();
+
+ 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", (do_elem_order_fix) ? transparent : col2);
+ GPU_batch_uniform_4fv(verts, "pinnedColor", pinned_col);
+ GPU_batch_uniform_1f(verts, "pointSize", (pointsize + 1.5f) * M_SQRT2);
+ GPU_batch_uniform_1f(verts, "outlineWidth", 0.75f);
+ GPU_batch_draw(verts);
+
+ if (do_elem_order_fix) {
+ /* 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_uniform_4fv(verts, "pinnedColor", pinned_col);
+ GPU_batch_uniform_1f(verts, "pointSize", (pointsize + 1.5f) * M_SQRT2);
+ GPU_batch_uniform_1f(verts, "outlineWidth", 0.75f);
+ GPU_batch_draw(verts);
}
- }
-
- immEnd();
- /* pinned uvs */
- /* give odd pointsizes odd pin pointsizes */
- GPU_point_size(pointsize * 2 + (((int)pointsize % 2) ? (-1) : 0));
- imm_cpack(0xFF);
-
- immBeginAtMost(GPU_PRIM_POINTS, 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);
-
- if (luv->flag & MLOOPUV_PINNED)
- immVertex2fv(pos, luv->uv);
- }
+ GPU_blend(false);
+ GPU_disable_program_point_size();
}
-
- immEnd();
-
- /* selected uvs */
- immUniformThemeColor(TH_VERTEX_SELECT);
- GPU_point_size(pointsize);
-
- immBeginAtMost(GPU_PRIM_POINTS, 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);
-
- if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))
- immVertex2fv(pos, luv->uv);
- }
+ if (facedots) {
+ GPU_point_size(pointsize);
+
+ 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);
}
-
- immEnd();
-
- immUnbindProgram();
}
}
-
static void draw_uv_shadows_get(
SpaceImage *sima, Object *ob, Object *obedit,
bool *show_shadow, bool *show_texpaint)
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 5c010a58137..e8ed5de82cb 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -205,6 +205,7 @@ data_to_c_simple(shaders/gpu_shader_point_uniform_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_point_uniform_color_aa_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_point_uniform_color_outline_aa_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_point_varying_color_outline_aa_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_point_varying_color_varying_outline_aa_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_point_varying_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_point_fixed_size_varying_color_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_point_varying_size_vert.glsl SRC)
@@ -216,6 +217,12 @@ data_to_c_simple(shaders/gpu_shader_2D_point_uniform_size_aa_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_2D_point_uniform_size_outline_aa_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_edituvs_points_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_edituvs_facedots_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_edituvs_edges_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_edituvs_faces_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_edituvs_stretch_vert.glsl SRC)
+
data_to_c_simple(shaders/gpu_shader_edges_front_back_persp_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_edges_front_back_persp_geom.glsl SRC)
data_to_c_simple(shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl SRC)
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index 1a1d40b32c2..86d68ebfc58 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -352,6 +352,13 @@ typedef enum GPUBuiltinShader {
GPU_SHADER_2D_WIDGET_SHADOW,
GPU_SHADER_2D_NODELINK,
GPU_SHADER_2D_NODELINK_INST,
+ /* specialized for edituv drawing */
+ GPU_SHADER_2D_UV_VERTS,
+ GPU_SHADER_2D_UV_FACEDOTS,
+ GPU_SHADER_2D_UV_EDGES,
+ GPU_SHADER_2D_UV_EDGES_SMOOTH,
+ GPU_SHADER_2D_UV_FACES,
+ GPU_SHADER_2D_UV_FACES_STRETCH,
GPU_NUM_BUILTIN_SHADERS /* (not an actual shader) */
} GPUBuiltinShader;
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
index e0172579b3c..4fa0fae4c87 100644
--- a/source/blender/gpu/intern/gpu_shader.c
+++ b/source/blender/gpu/intern/gpu_shader.c
@@ -128,6 +128,7 @@ extern char datatoc_gpu_shader_point_uniform_color_frag_glsl[];
extern char datatoc_gpu_shader_point_uniform_color_aa_frag_glsl[];
extern char datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl[];
extern char datatoc_gpu_shader_point_varying_color_outline_aa_frag_glsl[];
+extern char datatoc_gpu_shader_point_varying_color_varying_outline_aa_frag_glsl[];
extern char datatoc_gpu_shader_point_varying_color_frag_glsl[];
extern char datatoc_gpu_shader_3D_point_fixed_size_varying_color_vert_glsl[];
extern char datatoc_gpu_shader_3D_point_varying_size_vert_glsl[];
@@ -139,6 +140,12 @@ extern char datatoc_gpu_shader_2D_point_uniform_size_aa_vert_glsl[];
extern char datatoc_gpu_shader_2D_point_uniform_size_outline_aa_vert_glsl[];
extern char datatoc_gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert_glsl[];
+extern char datatoc_gpu_shader_2D_edituvs_points_vert_glsl[];
+extern char datatoc_gpu_shader_2D_edituvs_facedots_vert_glsl[];
+extern char datatoc_gpu_shader_2D_edituvs_edges_vert_glsl[];
+extern char datatoc_gpu_shader_2D_edituvs_faces_vert_glsl[];
+extern char datatoc_gpu_shader_2D_edituvs_stretch_vert_glsl[];
+
extern char datatoc_gpu_shader_2D_line_dashed_uniform_color_vert_glsl[];
extern char datatoc_gpu_shader_2D_line_dashed_frag_glsl[];
extern char datatoc_gpu_shader_2D_line_dashed_geom_glsl[];
@@ -928,6 +935,25 @@ static const GPUShaderStages builtin_shader_stages[GPU_NUM_BUILTIN_SHADERS] = {
{ datatoc_gpu_shader_2D_nodelink_vert_glsl,
datatoc_gpu_shader_2D_nodelink_frag_glsl },
+ [GPU_SHADER_2D_UV_VERTS] =
+ { datatoc_gpu_shader_2D_edituvs_points_vert_glsl,
+ datatoc_gpu_shader_point_varying_color_varying_outline_aa_frag_glsl },
+ [GPU_SHADER_2D_UV_FACEDOTS] =
+ { datatoc_gpu_shader_2D_edituvs_facedots_vert_glsl,
+ datatoc_gpu_shader_point_varying_color_frag_glsl },
+ [GPU_SHADER_2D_UV_EDGES] =
+ { datatoc_gpu_shader_2D_edituvs_edges_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl },
+ [GPU_SHADER_2D_UV_EDGES_SMOOTH] =
+ { datatoc_gpu_shader_2D_edituvs_edges_vert_glsl,
+ datatoc_gpu_shader_2D_smooth_color_frag_glsl },
+ [GPU_SHADER_2D_UV_FACES] =
+ { datatoc_gpu_shader_2D_edituvs_faces_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl },
+ [GPU_SHADER_2D_UV_FACES_STRETCH] =
+ { datatoc_gpu_shader_2D_edituvs_stretch_vert_glsl,
+ datatoc_gpu_shader_2D_smooth_color_frag_glsl },
+
[GPU_SHADER_GPENCIL_STROKE] =
{ datatoc_gpu_shader_gpencil_stroke_vert_glsl,
datatoc_gpu_shader_gpencil_stroke_frag_glsl,
@@ -995,6 +1021,9 @@ static const char *gpu_shader_get_builtin_shader_defines(
case GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR:
return "#define USE_FLAT_NORMAL\n";
+ case GPU_SHADER_2D_UV_EDGES_SMOOTH:
+ return "#define SMOOTH_COLOR\n";
+
default:
return NULL;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_edituvs_edges_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_edituvs_edges_vert.glsl
new file mode 100644
index 00000000000..76e9c066103
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_edituvs_edges_vert.glsl
@@ -0,0 +1,29 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform vec4 edgeColor;
+uniform vec4 selectColor;
+
+in vec2 pos;
+in int flag;
+
+#ifdef SMOOTH_COLOR
+noperspective out vec4 finalColor;
+#else
+flat out vec4 finalColor;
+#endif
+
+#define VERTEX_SELECT (1 << 0)
+#define EDGE_SELECT (1 << 4)
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+
+#ifdef SMOOTH_COLOR
+ bool is_select = (flag & VERTEX_SELECT) != 0;
+#else
+ bool is_select = (flag & EDGE_SELECT) != 0;
+#endif
+
+ finalColor = (is_select) ? selectColor : edgeColor;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_edituvs_facedots_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_edituvs_facedots_vert.glsl
new file mode 100644
index 00000000000..4f3f8917286
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_edituvs_facedots_vert.glsl
@@ -0,0 +1,17 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform vec4 vertColor;
+uniform vec4 selectColor;
+
+in vec2 pos;
+in int flag;
+
+out vec4 finalColor;
+
+#define FACE_SELECT (1 << 2)
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+ finalColor = ((flag & FACE_SELECT) != 0) ? selectColor : vertColor;
+} \ No newline at end of file
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_edituvs_faces_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_edituvs_faces_vert.glsl
new file mode 100644
index 00000000000..82c8d3f0c4a
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_edituvs_faces_vert.glsl
@@ -0,0 +1,24 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform vec4 faceColor;
+uniform vec4 selectColor;
+uniform vec4 activeColor;
+
+in vec2 pos;
+in int flag;
+
+flat out vec4 finalColor;
+
+#define FACE_SELECT (1 << 2)
+#define FACE_ACTIVE (1 << 3)
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+
+ bool is_selected = (flag & FACE_SELECT) != 0;
+ bool is_active = (flag & FACE_ACTIVE) != 0;
+
+ finalColor = (is_selected) ? selectColor : faceColor;
+ finalColor = (is_active) ? activeColor : finalColor;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_edituvs_points_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_edituvs_points_vert.glsl
new file mode 100644
index 00000000000..d59e15a8f63
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_edituvs_points_vert.glsl
@@ -0,0 +1,42 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform vec4 vertColor;
+uniform vec4 selectColor;
+uniform vec4 pinnedColor;
+uniform float pointSize;
+uniform float outlineWidth;
+
+in vec2 pos;
+in int flag;
+
+out vec4 fillColor;
+out vec4 outlineColor;
+out vec4 radii;
+
+#define VERTEX_SELECT (1 << 0)
+#define VERTEX_PINNED (1 << 1)
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+ gl_PointSize = pointSize;
+
+ bool is_selected = (flag & VERTEX_SELECT) != 0;
+ bool is_pinned = (flag & VERTEX_PINNED) != 0;
+
+ vec4 deselect_col = (is_pinned) ? pinnedColor : vertColor;
+ fillColor = (is_selected) ? selectColor : deselect_col;
+ outlineColor = (is_pinned) ? pinnedColor : vec4(fillColor.rgb, 0.0);
+
+ // calculate concentric radii in pixels
+ float radius = 0.5 * pointSize;
+
+ // start at the outside and progress toward the center
+ radii[0] = radius;
+ radii[1] = radius - 1.0;
+ radii[2] = radius - outlineWidth;
+ radii[3] = radius - outlineWidth - 1.0;
+
+ // convert to PointCoord units
+ radii /= pointSize;
+} \ No newline at end of file
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
new file mode 100644
index 00000000000..4588e41573b
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_edituvs_stretch_vert.glsl
@@ -0,0 +1,49 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec2 pos;
+in float stretch;
+
+noperspective out vec4 finalColor;
+
+vec3 weight_to_rgb(float weight)
+{
+ vec3 r_rgb;
+ float blend = ((weight / 2.0) + 0.5);
+
+ if (weight <= 0.25) { /* blue->cyan */
+ r_rgb[0] = 0.0;
+ r_rgb[1] = blend * weight * 4.0;
+ r_rgb[2] = blend;
+ }
+ else if (weight <= 0.50) { /* cyan->green */
+ r_rgb[0] = 0.0;
+ r_rgb[1] = blend;
+ r_rgb[2] = blend * (1.0 - ((weight - 0.25) * 4.0));
+ }
+ else if (weight <= 0.75) { /* green->yellow */
+ r_rgb[0] = blend * ((weight - 0.50) * 4.0);
+ r_rgb[1] = blend;
+ r_rgb[2] = 0.0;
+ }
+ else if (weight <= 1.0) { /* yellow->red */
+ r_rgb[0] = blend;
+ r_rgb[1] = blend * (1.0 - ((weight - 0.75) * 4.0));
+ r_rgb[2] = 0.0;
+ }
+ else {
+ /* exceptional value, unclamped or nan,
+ * avoid uninitialized memory use */
+ r_rgb[0] = 1.0;
+ r_rgb[1] = 0.0;
+ r_rgb[2] = 1.0;
+ }
+
+ return r_rgb;
+}
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+ finalColor = vec4(weight_to_rgb(stretch), 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_point_varying_color_varying_outline_aa_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_varying_color_varying_outline_aa_frag.glsl
new file mode 100644
index 00000000000..e1f8203cb26
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_point_varying_color_varying_outline_aa_frag.glsl
@@ -0,0 +1,30 @@
+
+in vec4 radii;
+in vec4 fillColor;
+in vec4 outlineColor;
+out vec4 fragColor;
+
+void main() {
+ float dist = length(gl_PointCoord - vec2(0.5));
+
+// transparent outside of point
+// --- 0 ---
+// smooth transition
+// --- 1 ---
+// pure outline color
+// --- 2 ---
+// smooth transition
+// --- 3 ---
+// pure fill color
+// ...
+// dist = 0 at center of point
+
+ float midStroke = 0.5 * (radii[1] + radii[2]);
+
+ if (dist > midStroke) {
+ fragColor.rgb = outlineColor.rgb;
+ fragColor.a = mix(outlineColor.a, 0.0, smoothstep(radii[1], radii[0], dist));
+ }
+ else
+ fragColor = mix(fillColor, outlineColor, smoothstep(radii[3], radii[2], dist));
+}