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

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