Edit Mode overlays: separate multiple shaders for loose edges and verts
This commit is contained in:
parent
3baa186724
commit
26fc6c71c4
|
@ -40,6 +40,8 @@ struct Batch *BKE_mesh_batch_cache_get_all_triangles(struct Mesh *me);
|
|||
struct Batch *BKE_mesh_batch_cache_get_triangles_with_normals(struct Mesh *me);
|
||||
struct Batch *BKE_mesh_batch_cache_get_all_verts(struct Mesh *me);
|
||||
struct Batch *BKE_mesh_batch_cache_get_fancy_edges(struct Mesh *me);
|
||||
struct Batch *BKE_mesh_batch_cache_get_overlay_edges(struct Mesh *me);
|
||||
struct Batch *BKE_mesh_batch_cache_get_overlay_triangles(struct Mesh *me);
|
||||
struct Batch *BKE_mesh_batch_cache_get_overlay_loose_edges(struct Mesh *me);
|
||||
struct Batch *BKE_mesh_batch_cache_get_overlay_loose_verts(struct Mesh *me);
|
||||
|
||||
#endif /* __BKE_MESH_RENDER_H__ */
|
||||
|
|
|
@ -123,15 +123,11 @@ typedef struct MeshRenderData {
|
|||
|
||||
enum {
|
||||
MR_DATATYPE_VERT = 1 << 0,
|
||||
MR_DATATYPE_LOOSE_VERT = 1 << 1,
|
||||
MR_DATATYPE_EDGE = 1 << 2,
|
||||
MR_DATATYPE_LOOSE_EDGE = 1 << 3,
|
||||
MR_DATATYPE_LOOPTRI = 1 << 4,
|
||||
MR_DATATYPE_LOOP = 1 << 5,
|
||||
MR_DATATYPE_POLY = 1 << 6,
|
||||
MR_DATATYPE_ACTIVE = 1 << 7,
|
||||
MR_DATATYPE_CREASE = 1 << 8,
|
||||
MR_DATATYPE_BWEIGHT = 1 << 9,
|
||||
MR_DATATYPE_EDGE = 1 << 1,
|
||||
MR_DATATYPE_LOOPTRI = 1 << 2,
|
||||
MR_DATATYPE_LOOP = 1 << 3,
|
||||
MR_DATATYPE_POLY = 1 << 4,
|
||||
MR_DATATYPE_OVERLAY = 1 << 5,
|
||||
};
|
||||
|
||||
static MeshRenderData *mesh_render_data_create(Mesh *me, const int types)
|
||||
|
@ -146,11 +142,11 @@ static MeshRenderData *mesh_render_data_create(Mesh *me, const int types)
|
|||
mrdata->edit_bmesh = embm;
|
||||
|
||||
int bm_ensure_types = 0;
|
||||
if (types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOSE_VERT)) {
|
||||
if (types & (MR_DATATYPE_VERT)) {
|
||||
mrdata->totvert = bm->totvert;
|
||||
bm_ensure_types |= BM_VERT;
|
||||
}
|
||||
if (types & (MR_DATATYPE_EDGE | MR_DATATYPE_LOOSE_EDGE)) {
|
||||
if (types & (MR_DATATYPE_EDGE)) {
|
||||
mrdata->totedge = bm->totedge;
|
||||
bm_ensure_types |= BM_EDGE;
|
||||
}
|
||||
|
@ -166,72 +162,56 @@ static MeshRenderData *mesh_render_data_create(Mesh *me, const int types)
|
|||
mrdata->totpoly = bm->totface;
|
||||
bm_ensure_types |= BM_FACE;
|
||||
}
|
||||
if (types & MR_DATATYPE_ACTIVE) {
|
||||
if (types & MR_DATATYPE_OVERLAY) {
|
||||
mrdata->efa_act = BM_mesh_active_face_get(bm, false, true);
|
||||
mrdata->eed_act = BM_mesh_active_edge_get(bm);
|
||||
mrdata->eve_act = BM_mesh_active_vert_get(bm);
|
||||
}
|
||||
if (types & MR_DATATYPE_CREASE) {
|
||||
mrdata->crease_ofs = CustomData_get_offset(&bm->edata, CD_CREASE);
|
||||
}
|
||||
if (types & MR_DATATYPE_BWEIGHT) {
|
||||
mrdata->bweight_ofs = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
|
||||
}
|
||||
BM_mesh_elem_index_ensure(bm, bm_ensure_types);
|
||||
BM_mesh_elem_table_ensure(bm, bm_ensure_types & ~BM_LOOP);
|
||||
if (types & MR_DATATYPE_LOOSE_VERT) {
|
||||
mrdata->types |= MR_DATATYPE_VERT;
|
||||
mrdata->totlvert = 0;
|
||||
/* XXX slow, looping twice */
|
||||
if (types & MR_DATATYPE_OVERLAY) {
|
||||
mrdata->totlvert = mrdata->totledge = 0;
|
||||
|
||||
int *lverts = mrdata->loose_verts = MEM_mallocN(mrdata->totvert * sizeof(int), "Loose Vert");
|
||||
int *ledges = mrdata->loose_edges = MEM_mallocN(mrdata->totedge * sizeof(int), "Loose Edges");
|
||||
|
||||
for (int i = 0; i < mrdata->totvert; ++i) {
|
||||
BMVert *bv = BM_vert_at_index(bm, i);
|
||||
if (BM_vert_edge_count_ex(bv, 1) == 0) {
|
||||
|
||||
/* Loose vert */
|
||||
if (bv->e == NULL) {
|
||||
lverts[mrdata->totlvert] = BM_elem_index_get(bv);
|
||||
mrdata->totlvert++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
int *lverts = mrdata->loose_verts = MEM_mallocN(mrdata->totlvert * sizeof(int), "Loose Vert");
|
||||
/* Find Loose Edges */
|
||||
BMEdge *e_iter, *e_first;
|
||||
e_first = e_iter = bv->e;
|
||||
do {
|
||||
if (e_iter->l == NULL) {
|
||||
BMVert *other_vert = BM_edge_other_vert(e_iter, bv);
|
||||
|
||||
int li = 0;
|
||||
if (mrdata->totlvert > 0) {
|
||||
for (int i = 0; i < mrdata->totvert; ++i) {
|
||||
BMVert *bv = BM_vert_at_index(bm, i);
|
||||
if (BM_vert_edge_count_ex(bv, 1) == 0) {
|
||||
lverts[li++] = i;
|
||||
/* Verify we do not add the same edge twice */
|
||||
if (BM_elem_index_get(other_vert) > i) {
|
||||
ledges[mrdata->totledge] = BM_elem_index_get(e_iter);
|
||||
mrdata->totledge++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (types & MR_DATATYPE_LOOSE_EDGE) {
|
||||
mrdata->types |= MR_DATATYPE_EDGE;
|
||||
mrdata->totledge = 0;
|
||||
/* XXX slow, looping twice */
|
||||
for (int i = 0; i < mrdata->totedge; ++i) {
|
||||
BMEdge *bv = BM_edge_at_index(bm, i);
|
||||
if (BM_edge_is_wire(bv)) {
|
||||
mrdata->totledge++;
|
||||
}
|
||||
}
|
||||
|
||||
int *ledges = mrdata->loose_edges = MEM_mallocN(mrdata->totledge * sizeof(int), "Loose Egde");
|
||||
|
||||
int li = 0;
|
||||
if (mrdata->totledge > 0) {
|
||||
for (int i = 0; i < mrdata->totedge; ++i) {
|
||||
BMEdge *bv = BM_edge_at_index(bm, i);
|
||||
if (BM_edge_is_wire(bv)) {
|
||||
ledges[li++] = i;
|
||||
}
|
||||
}
|
||||
} while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, bv)) != e_first);
|
||||
}
|
||||
mrdata->loose_verts = MEM_reallocN(mrdata->loose_verts, mrdata->totlvert * sizeof(int));
|
||||
mrdata->loose_edges = MEM_reallocN(mrdata->loose_edges, mrdata->totledge * sizeof(int));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOSE_VERT)) {
|
||||
if (types & (MR_DATATYPE_VERT)) {
|
||||
mrdata->totvert = me->totvert;
|
||||
mrdata->mvert = CustomData_get_layer(&me->vdata, CD_MVERT);
|
||||
}
|
||||
if (types & (MR_DATATYPE_EDGE | MR_DATATYPE_LOOSE_EDGE)) {
|
||||
if (types & (MR_DATATYPE_EDGE)) {
|
||||
mrdata->totedge = me->totedge;
|
||||
mrdata->medge = CustomData_get_layer(&me->edata, CD_MEDGE);
|
||||
}
|
||||
|
@ -248,16 +228,6 @@ static MeshRenderData *mesh_render_data_create(Mesh *me, const int types)
|
|||
mrdata->totpoly = me->totpoly;
|
||||
mrdata->mpoly = CustomData_get_layer(&me->pdata, CD_MPOLY);
|
||||
}
|
||||
if (types & MR_DATATYPE_LOOSE_VERT) {
|
||||
mrdata->types |= MR_DATATYPE_VERT;
|
||||
mrdata->totlvert = 0;
|
||||
/* TODO */
|
||||
}
|
||||
if (types & MR_DATATYPE_LOOSE_EDGE) {
|
||||
mrdata->types |= MR_DATATYPE_EDGE;
|
||||
mrdata->totledge = 0;
|
||||
/* TODO */
|
||||
}
|
||||
}
|
||||
|
||||
return mrdata;
|
||||
|
@ -300,7 +270,7 @@ static int mesh_render_data_verts_num_get(const MeshRenderData *mrdata)
|
|||
|
||||
static int mesh_render_data_loose_verts_num_get(const MeshRenderData *mrdata)
|
||||
{
|
||||
BLI_assert(mrdata->types & MR_DATATYPE_LOOSE_VERT);
|
||||
BLI_assert(mrdata->types & MR_DATATYPE_OVERLAY);
|
||||
return mrdata->totlvert;
|
||||
}
|
||||
|
||||
|
@ -312,7 +282,7 @@ static int mesh_render_data_edges_num_get(const MeshRenderData *mrdata)
|
|||
|
||||
static int mesh_render_data_loose_edges_num_get(const MeshRenderData *mrdata)
|
||||
{
|
||||
BLI_assert(mrdata->types & MR_DATATYPE_LOOSE_EDGE);
|
||||
BLI_assert(mrdata->types & MR_DATATYPE_OVERLAY);
|
||||
return mrdata->totledge;
|
||||
}
|
||||
|
||||
|
@ -547,6 +517,171 @@ static bool mesh_render_data_looptri_cos_nors_smooth_get(
|
|||
}
|
||||
}
|
||||
|
||||
/* First 2 bytes are bit flags
|
||||
* 3rd is for sharp edges
|
||||
* 4rd is for creased edges */
|
||||
enum {
|
||||
VFLAG_VERTEX_ACTIVE = 1 << 0,
|
||||
VFLAG_VERTEX_SELECTED = 1 << 1,
|
||||
VFLAG_FACE_ACTIVE = 1 << 2,
|
||||
VFLAG_FACE_SELECTED = 1 << 3,
|
||||
};
|
||||
|
||||
enum {
|
||||
VFLAG_EDGE_EXISTS = 1 << 0,
|
||||
VFLAG_EDGE_ACTIVE = 1 << 1,
|
||||
VFLAG_EDGE_SELECTED = 1 << 2,
|
||||
VFLAG_EDGE_SEAM = 1 << 3,
|
||||
VFLAG_EDGE_SHARP = 1 << 4,
|
||||
/* Beware to not go over 1 << 7
|
||||
* (see gpu_shader_edit_overlay_geom.glsl) */
|
||||
};
|
||||
|
||||
static unsigned char mesh_render_data_looptri_flag(MeshRenderData *mrdata, const int f)
|
||||
{
|
||||
unsigned char fflag = 0;
|
||||
|
||||
if (mrdata->edit_bmesh) {
|
||||
BMFace *bf = mrdata->edit_bmesh->looptris[f][0]->f;
|
||||
|
||||
if (bf == mrdata->efa_act)
|
||||
fflag |= VFLAG_FACE_ACTIVE;
|
||||
|
||||
if (BM_elem_flag_test(bf, BM_ELEM_SELECT))
|
||||
fflag |= VFLAG_FACE_SELECTED;
|
||||
}
|
||||
|
||||
return fflag;
|
||||
}
|
||||
|
||||
static unsigned char *mesh_render_data_edge_flag(
|
||||
MeshRenderData *mrdata, const int v1, const int v2, const int e)
|
||||
{
|
||||
static unsigned char eflag[4];
|
||||
memset(eflag, 0, sizeof(char) * 4);
|
||||
|
||||
/* if edge exists */
|
||||
if (mrdata->edit_bmesh) {
|
||||
BMesh *bm = mrdata->edit_bmesh->bm;
|
||||
BMEdge *be = NULL;
|
||||
|
||||
if (e != -1) be = BM_edge_at_index(bm, e);
|
||||
else be = BM_edge_exists(BM_vert_at_index(bm, v1),
|
||||
BM_vert_at_index(bm, v2));
|
||||
|
||||
if (be != NULL) {
|
||||
|
||||
eflag[1] |= VFLAG_EDGE_EXISTS;
|
||||
|
||||
if (be == mrdata->eed_act)
|
||||
eflag[1] |= VFLAG_EDGE_ACTIVE;
|
||||
|
||||
if (BM_elem_flag_test(be, BM_ELEM_SELECT))
|
||||
eflag[1] |= VFLAG_EDGE_SELECTED;
|
||||
|
||||
if (BM_elem_flag_test(be, BM_ELEM_SEAM))
|
||||
eflag[1] |= VFLAG_EDGE_SEAM;
|
||||
|
||||
if (!BM_elem_flag_test(be, BM_ELEM_SMOOTH))
|
||||
eflag[1] |= VFLAG_EDGE_SHARP;
|
||||
|
||||
/* Use a byte for value range */
|
||||
if (mrdata->crease_ofs != -1) {
|
||||
float crease = BM_ELEM_CD_GET_FLOAT(be, mrdata->crease_ofs);
|
||||
if (crease > 0) {
|
||||
eflag[2] = (char)(crease * 255.0f);
|
||||
}
|
||||
}
|
||||
|
||||
/* Use a byte for value range */
|
||||
if (mrdata->bweight_ofs != -1) {
|
||||
float bweight = BM_ELEM_CD_GET_FLOAT(be, mrdata->bweight_ofs);
|
||||
if (bweight > 0) {
|
||||
eflag[3] = (char)(bweight * 255.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((e == -1) && mesh_render_data_edge_exists(mrdata, v1, v2)) {
|
||||
eflag[1] |= VFLAG_EDGE_EXISTS;
|
||||
}
|
||||
|
||||
return eflag;
|
||||
}
|
||||
|
||||
static unsigned char mesh_render_data_vertex_flag(MeshRenderData *mrdata, const int v)
|
||||
{
|
||||
|
||||
unsigned char vflag = 0;
|
||||
|
||||
if (mrdata->edit_bmesh) {
|
||||
BMesh *bm = mrdata->edit_bmesh->bm;
|
||||
BMVert *bv = BM_vert_at_index(bm, v);
|
||||
|
||||
/* Current vertex */
|
||||
if (bv == mrdata->eve_act)
|
||||
vflag |= VFLAG_VERTEX_ACTIVE;
|
||||
|
||||
if (BM_elem_flag_test(bv, BM_ELEM_SELECT))
|
||||
vflag |= VFLAG_VERTEX_SELECTED;
|
||||
}
|
||||
|
||||
return vflag;
|
||||
}
|
||||
|
||||
static void add_overlay_tri(
|
||||
MeshRenderData *mrdata, VertexBuffer *vbo, const unsigned int pos_id, const unsigned int edgeMod_id,
|
||||
const int v1, const int v2, const int v3, const int f, const int base_vert_idx)
|
||||
{
|
||||
const float *pos = mesh_render_data_vert_co(mrdata, v1);
|
||||
unsigned char *eflag = mesh_render_data_edge_flag(mrdata, v2, v3, -1);
|
||||
unsigned char fflag = mesh_render_data_looptri_flag(mrdata, f);
|
||||
unsigned char vflag = mesh_render_data_vertex_flag(mrdata, v1);
|
||||
eflag[0] = fflag | vflag;
|
||||
setAttrib(vbo, pos_id, base_vert_idx + 0, pos);
|
||||
setAttrib(vbo, edgeMod_id, base_vert_idx + 0, eflag);
|
||||
|
||||
pos = mesh_render_data_vert_co(mrdata, v2);
|
||||
eflag = mesh_render_data_edge_flag(mrdata, v1, v3, -1);
|
||||
vflag = mesh_render_data_vertex_flag(mrdata, v2);
|
||||
eflag[0] = fflag | vflag;
|
||||
setAttrib(vbo, pos_id, base_vert_idx + 1, pos);
|
||||
setAttrib(vbo, edgeMod_id, base_vert_idx + 1, eflag);
|
||||
|
||||
pos = mesh_render_data_vert_co(mrdata, v3);
|
||||
eflag = mesh_render_data_edge_flag(mrdata, v1, v2, -1);
|
||||
vflag = mesh_render_data_vertex_flag(mrdata, v3);
|
||||
eflag[0] = fflag | vflag;
|
||||
setAttrib(vbo, pos_id, base_vert_idx + 2, pos);
|
||||
setAttrib(vbo, edgeMod_id, base_vert_idx + 2, eflag);
|
||||
}
|
||||
|
||||
static void add_overlay_loose_edge(
|
||||
MeshRenderData *mrdata, VertexBuffer *vbo, const unsigned int pos_id, const unsigned int edgeMod_id,
|
||||
const int v1, const int v2, const int e, const int base_vert_idx)
|
||||
{
|
||||
unsigned char *eflag = mesh_render_data_edge_flag(mrdata, 0, 0, e);
|
||||
const float *pos = mesh_render_data_vert_co(mrdata, v1);
|
||||
eflag[0] = mesh_render_data_vertex_flag(mrdata, v1);
|
||||
setAttrib(vbo, pos_id, base_vert_idx + 0, pos);
|
||||
setAttrib(vbo, edgeMod_id, base_vert_idx + 0, eflag);
|
||||
|
||||
pos = mesh_render_data_vert_co(mrdata, v2);
|
||||
eflag[0] = mesh_render_data_vertex_flag(mrdata, v2);
|
||||
setAttrib(vbo, pos_id, base_vert_idx + 1, pos);
|
||||
setAttrib(vbo, edgeMod_id, base_vert_idx + 1, eflag);
|
||||
}
|
||||
|
||||
static void add_overlay_loose_vert(
|
||||
MeshRenderData *mrdata, VertexBuffer *vbo, const unsigned int pos_id, const unsigned int edgeMod_id,
|
||||
const int v, const int base_vert_idx)
|
||||
{
|
||||
unsigned char vflag[4] = {0, 0, 0, 0};
|
||||
const float *pos = mesh_render_data_vert_co(mrdata, v);
|
||||
vflag[0] = mesh_render_data_vertex_flag(mrdata, v);
|
||||
setAttrib(vbo, pos_id, base_vert_idx + 0, pos);
|
||||
setAttrib(vbo, edgeMod_id, base_vert_idx + 0, vflag);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Mesh Batch Cache */
|
||||
|
@ -562,7 +697,14 @@ typedef struct MeshBatchCache {
|
|||
|
||||
Batch *triangles_with_normals; /* owns its vertex buffer */
|
||||
Batch *fancy_edges; /* owns its vertex buffer (not shared) */
|
||||
Batch *overlay_edges; /* owns its vertex buffer */
|
||||
|
||||
/* TODO : split in 2 buffers to avoid unnecessary
|
||||
* data transfer when selecting/deselecting
|
||||
* and combine into one batch and use offsets to render
|
||||
* Tri / edges / verts separately */
|
||||
Batch *overlay_triangles;
|
||||
Batch *overlay_loose_verts;
|
||||
Batch *overlay_loose_edges;
|
||||
|
||||
/* settings to determine if cache is invalid */
|
||||
bool is_dirty;
|
||||
|
@ -661,6 +803,10 @@ void BKE_mesh_batch_cache_clear(Mesh *me)
|
|||
if (cache->edges_in_order) ElementList_discard(cache->edges_in_order);
|
||||
if (cache->triangles_in_order) ElementList_discard(cache->triangles_in_order);
|
||||
|
||||
if (cache->overlay_triangles) Batch_discard(cache->overlay_triangles);
|
||||
if (cache->overlay_loose_verts) Batch_discard(cache->overlay_loose_verts);
|
||||
if (cache->overlay_loose_edges) Batch_discard(cache->overlay_loose_edges);
|
||||
|
||||
if (cache->triangles_with_normals) {
|
||||
Batch_discard_all(cache->triangles_with_normals);
|
||||
}
|
||||
|
@ -668,10 +814,6 @@ void BKE_mesh_batch_cache_clear(Mesh *me)
|
|||
if (cache->fancy_edges) {
|
||||
Batch_discard_all(cache->fancy_edges);
|
||||
}
|
||||
|
||||
if (cache->overlay_edges) {
|
||||
Batch_discard_all(cache->overlay_edges);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_mesh_batch_cache_free(Mesh *me)
|
||||
|
@ -921,217 +1063,104 @@ Batch *BKE_mesh_batch_cache_get_fancy_edges(Mesh *me)
|
|||
return cache->fancy_edges;
|
||||
}
|
||||
|
||||
enum {
|
||||
VFLAG_VERTEX_ACTIVE = 1 << 0,
|
||||
VFLAG_VERTEX_SELECTED = 1 << 1,
|
||||
VFLAG_VERTEX_LOOSE = 1 << 2,
|
||||
VFLAG_FACE_ACTIVE = 1 << 3,
|
||||
VFLAG_FACE_SELECTED = 1 << 4,
|
||||
};
|
||||
|
||||
enum {
|
||||
VFLAG_EDGE_EXISTS = 1 << 0,
|
||||
VFLAG_EDGE_ACTIVE = 1 << 1,
|
||||
VFLAG_EDGE_SELECTED = 1 << 2,
|
||||
VFLAG_EDGE_SEAM = 1 << 3,
|
||||
VFLAG_EDGE_SHARP = 1 << 4,
|
||||
};
|
||||
|
||||
static unsigned char *get_vertex_flag(
|
||||
MeshRenderData *mrdata, const int v1, const int v2, const int v3, const int tri_idx, const int edge_idx)
|
||||
static void mesh_batch_cache_create_overlay_batches(Mesh *me)
|
||||
{
|
||||
/* This is really not efficient
|
||||
* some operation are repeated accross all vertices
|
||||
* but are constant overt the triangle / entire mesh */
|
||||
/* Since MR_DATATYPE_OVERLAY is slow to generate, generate them all at once */
|
||||
int options = MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOPTRI | MR_DATATYPE_OVERLAY;
|
||||
|
||||
/* First 2 bytes are bit flags
|
||||
* 3rd is for sharp edges
|
||||
* 4rd is for creased edges */
|
||||
static unsigned char vflag[4];
|
||||
memset(vflag, 0, sizeof(unsigned char) * 4);
|
||||
|
||||
/* if edit mode */
|
||||
if (mrdata->edit_bmesh) {
|
||||
BMesh *bm = mrdata->edit_bmesh->bm;
|
||||
BMVert *bv1 = BM_vert_at_index(bm, v1);
|
||||
BMEdge *edge = NULL;
|
||||
|
||||
/* Current vertex */
|
||||
if (bv1 == mrdata->eve_act)
|
||||
vflag[0] |= VFLAG_VERTEX_ACTIVE;
|
||||
|
||||
if (BM_elem_flag_test(bv1, BM_ELEM_SELECT))
|
||||
vflag[0] |= VFLAG_VERTEX_SELECTED;
|
||||
|
||||
/* Current face */
|
||||
if (tri_idx > -1) {
|
||||
BMFace *face = mrdata->edit_bmesh->looptris[tri_idx][0]->f;
|
||||
if (face == mrdata->efa_act)
|
||||
vflag[0] |= VFLAG_FACE_ACTIVE;
|
||||
|
||||
if (BM_elem_flag_test(face, BM_ELEM_SELECT))
|
||||
vflag[0] |= VFLAG_FACE_SELECTED;
|
||||
|
||||
/* Oposite edge */
|
||||
BMVert *bv2 = BM_vert_at_index(bm, v2);
|
||||
BMVert *bv3 = BM_vert_at_index(bm, v3);
|
||||
edge = BM_edge_exists(bv2, bv3);
|
||||
}
|
||||
else if (edge_idx > -1) {
|
||||
/* Loose edge */
|
||||
edge = BM_edge_at_index(bm, edge_idx);
|
||||
}
|
||||
else {
|
||||
/* Loose Vertex */
|
||||
vflag[0] |= VFLAG_VERTEX_LOOSE;
|
||||
}
|
||||
|
||||
/* if edge exists */
|
||||
if (edge != NULL) {
|
||||
|
||||
vflag[1] |= VFLAG_EDGE_EXISTS;
|
||||
|
||||
if (edge == mrdata->eed_act)
|
||||
vflag[1] |= VFLAG_EDGE_ACTIVE;
|
||||
|
||||
if (BM_elem_flag_test(edge, BM_ELEM_SELECT))
|
||||
vflag[1] |= VFLAG_EDGE_SELECTED;
|
||||
|
||||
if (BM_elem_flag_test(edge, BM_ELEM_SEAM))
|
||||
vflag[1] |= VFLAG_EDGE_SEAM;
|
||||
|
||||
if (!BM_elem_flag_test(edge, BM_ELEM_SMOOTH))
|
||||
vflag[1] |= VFLAG_EDGE_SHARP;
|
||||
|
||||
/* Use a byte for value range */
|
||||
if (mrdata->crease_ofs != -1) {
|
||||
float crease = BM_ELEM_CD_GET_FLOAT(edge, mrdata->crease_ofs);
|
||||
if (crease > 0) {
|
||||
vflag[2] = (char)(crease * 255.0f);
|
||||
}
|
||||
}
|
||||
|
||||
/* Use a byte for value range */
|
||||
if (mrdata->bweight_ofs != -1) {
|
||||
float bweight = BM_ELEM_CD_GET_FLOAT(edge, mrdata->bweight_ofs);
|
||||
if (bweight > 0) {
|
||||
vflag[2] = (char)(bweight * 255.0f);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
/* Object mode */
|
||||
else {
|
||||
|
||||
/* Oposite edge */
|
||||
if (mesh_render_data_edge_exists(mrdata, v2, v3)) {
|
||||
vflag[1] |= VFLAG_EDGE_EXISTS;
|
||||
}
|
||||
}
|
||||
|
||||
return vflag;
|
||||
}
|
||||
|
||||
static void add_overlay_tri(
|
||||
MeshRenderData *mrdata, VertexBuffer *vbo, const unsigned int pos_id, const unsigned int edgeMod_id,
|
||||
const int v1, const int v2, const int v3, const int tri_idx, const int base_vert_idx)
|
||||
{
|
||||
const float *pos = mesh_render_data_vert_co(mrdata, v1);
|
||||
unsigned char *vflag = get_vertex_flag(mrdata, v1, v2, v3, tri_idx, -1);
|
||||
setAttrib(vbo, pos_id, base_vert_idx + 0, pos);
|
||||
setAttrib(vbo, edgeMod_id, base_vert_idx + 0, vflag);
|
||||
|
||||
pos = mesh_render_data_vert_co(mrdata, v2);
|
||||
vflag = get_vertex_flag(mrdata, v2, v1, v3, tri_idx, -1);
|
||||
setAttrib(vbo, pos_id, base_vert_idx + 1, pos);
|
||||
setAttrib(vbo, edgeMod_id, base_vert_idx + 1, vflag);
|
||||
|
||||
pos = mesh_render_data_vert_co(mrdata, v3);
|
||||
vflag = get_vertex_flag(mrdata, v3, v2, v1, tri_idx, -1);
|
||||
setAttrib(vbo, pos_id, base_vert_idx + 2, pos);
|
||||
setAttrib(vbo, edgeMod_id, base_vert_idx + 2, vflag);
|
||||
}
|
||||
|
||||
static void add_overlay_loose_edge(
|
||||
MeshRenderData *mrdata, VertexBuffer *vbo, const unsigned int pos_id, const unsigned int edgeMod_id,
|
||||
const int v1, const int v2, const int edge_idx, const int base_vert_idx)
|
||||
{
|
||||
const float *pos = mesh_render_data_vert_co(mrdata, v1);
|
||||
unsigned char *vflag = get_vertex_flag(mrdata, v1, v2, v2, -1, edge_idx);
|
||||
setAttrib(vbo, pos_id, base_vert_idx + 0, pos);
|
||||
setAttrib(vbo, edgeMod_id, base_vert_idx + 0, vflag);
|
||||
|
||||
pos = mesh_render_data_vert_co(mrdata, v2);
|
||||
vflag = get_vertex_flag(mrdata, v2, v1, v1, -1, edge_idx);
|
||||
setAttrib(vbo, pos_id, base_vert_idx + 1, pos);
|
||||
setAttrib(vbo, edgeMod_id, base_vert_idx + 1, vflag);
|
||||
|
||||
setAttrib(vbo, pos_id, base_vert_idx + 2, pos);
|
||||
setAttrib(vbo, edgeMod_id, base_vert_idx + 2, vflag);
|
||||
}
|
||||
|
||||
Batch *BKE_mesh_batch_cache_get_overlay_edges(Mesh *me)
|
||||
{
|
||||
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
||||
MeshRenderData *mrdata = mesh_render_data_create(me, options);
|
||||
|
||||
if (cache->overlay_edges == NULL) {
|
||||
/* create batch from mesh */
|
||||
static VertexFormat format = { 0 };
|
||||
static unsigned int pos_id, edgeMod_id;
|
||||
static VertexFormat format = { 0 };
|
||||
static unsigned pos_id, data_id;
|
||||
if (format.attrib_ct == 0) {
|
||||
/* initialize vertex format */
|
||||
pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
|
||||
data_id = add_attrib(&format, "data", GL_UNSIGNED_BYTE, 4, KEEP_INT);
|
||||
}
|
||||
|
||||
if (format.attrib_ct == 0) {
|
||||
/* initialize vertex format */
|
||||
pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
|
||||
edgeMod_id = add_attrib(&format, "data", GL_UNSIGNED_BYTE, 4, KEEP_INT);
|
||||
}
|
||||
const int tri_ct = mesh_render_data_looptri_num_get(mrdata);
|
||||
const int ledge_ct = mesh_render_data_loose_edges_num_get(mrdata);
|
||||
const int lvert_ct = mesh_render_data_loose_verts_num_get(mrdata);
|
||||
|
||||
if (cache->overlay_triangles == NULL) {
|
||||
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
|
||||
|
||||
MeshRenderData *mrdata = mesh_render_data_create(me, MR_DATATYPE_LOOSE_VERT | MR_DATATYPE_LOOSE_EDGE |
|
||||
MR_DATATYPE_LOOPTRI | MR_DATATYPE_ACTIVE |
|
||||
MR_DATATYPE_CREASE | MR_DATATYPE_BWEIGHT);
|
||||
const int tri_ct = mesh_render_data_looptri_num_get(mrdata);
|
||||
const int ledge_ct = mesh_render_data_loose_edges_num_get(mrdata);
|
||||
const int lvert_ct = mesh_render_data_loose_verts_num_get(mrdata);
|
||||
const int lvert_tri_ct = (int)ceil(((float)lvert_ct) / 3.0f);
|
||||
|
||||
|
||||
VertexBuffer_allocate_data(vbo, (tri_ct + ledge_ct + lvert_tri_ct) * 3);
|
||||
VertexBuffer_allocate_data(vbo, tri_ct * 3);
|
||||
|
||||
int gpu_vert_idx = 0;
|
||||
for (int i = 0; i < tri_ct; ++i) {
|
||||
int tri_vert_idx[3];
|
||||
mesh_render_data_looptri_verts_indices_get(mrdata, i, tri_vert_idx);
|
||||
add_overlay_tri(mrdata, vbo, pos_id, edgeMod_id, tri_vert_idx[0], tri_vert_idx[1], tri_vert_idx[2], i, gpu_vert_idx);
|
||||
add_overlay_tri(mrdata, vbo, pos_id, data_id,
|
||||
tri_vert_idx[0], tri_vert_idx[1], tri_vert_idx[2], i, gpu_vert_idx);
|
||||
gpu_vert_idx += 3;
|
||||
}
|
||||
|
||||
for (int i = 0; i < ledge_ct; ++i) {
|
||||
int vert_idx[2];
|
||||
|
||||
mesh_render_data_edge_verts_indices_get(mrdata, mrdata->loose_edges[i], vert_idx);
|
||||
add_overlay_loose_edge(mrdata, vbo, pos_id, edgeMod_id, vert_idx[0], vert_idx[1], i, gpu_vert_idx);
|
||||
gpu_vert_idx += 3;
|
||||
}
|
||||
|
||||
int v = 0;
|
||||
for (int i = 0; i < lvert_tri_ct; ++i) {
|
||||
int vert_idx[3];
|
||||
|
||||
vert_idx[0] = mrdata->loose_verts[MIN2(v, lvert_ct-1)]; v++;
|
||||
vert_idx[1] = mrdata->loose_verts[MIN2(v, lvert_ct-1)]; v++;
|
||||
vert_idx[2] = mrdata->loose_verts[MIN2(v, lvert_ct-1)]; v++;
|
||||
|
||||
add_overlay_tri(mrdata, vbo, pos_id, edgeMod_id, vert_idx[0], vert_idx[1], vert_idx[2], -1, gpu_vert_idx);
|
||||
gpu_vert_idx += 3;
|
||||
}
|
||||
|
||||
cache->overlay_edges = Batch_create(GL_TRIANGLES, vbo, NULL);
|
||||
|
||||
mesh_render_data_free(mrdata);
|
||||
cache->overlay_triangles = Batch_create(GL_TRIANGLES, vbo, NULL);
|
||||
}
|
||||
|
||||
return cache->overlay_edges;
|
||||
if (cache->overlay_loose_edges == NULL) {
|
||||
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
|
||||
VertexBuffer_allocate_data(vbo, ledge_ct * 2);
|
||||
|
||||
int gpu_vert_idx = 0;
|
||||
for (int i = 0; i < ledge_ct; ++i) {
|
||||
int vert_idx[2];
|
||||
mesh_render_data_edge_verts_indices_get(mrdata, mrdata->loose_edges[i], vert_idx);
|
||||
add_overlay_loose_edge(mrdata, vbo, pos_id, data_id,
|
||||
vert_idx[0], vert_idx[1], mrdata->loose_edges[i], gpu_vert_idx);
|
||||
gpu_vert_idx += 2;
|
||||
}
|
||||
cache->overlay_loose_edges = Batch_create(GL_LINES, vbo, NULL);
|
||||
}
|
||||
|
||||
if (cache->overlay_loose_verts == NULL) {
|
||||
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
|
||||
VertexBuffer_allocate_data(vbo, lvert_ct);
|
||||
|
||||
int gpu_vert_idx = 0;
|
||||
for (int i = 0; i < lvert_ct; ++i) {
|
||||
add_overlay_loose_vert(mrdata, vbo, pos_id, data_id,
|
||||
mrdata->loose_verts[i], gpu_vert_idx);
|
||||
gpu_vert_idx += 1;
|
||||
}
|
||||
cache->overlay_loose_verts = Batch_create(GL_POINTS, vbo, NULL);
|
||||
}
|
||||
|
||||
mesh_render_data_free(mrdata);
|
||||
}
|
||||
|
||||
Batch *BKE_mesh_batch_cache_get_overlay_triangles(Mesh *me)
|
||||
{
|
||||
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
||||
|
||||
if (cache->overlay_triangles == NULL) {
|
||||
mesh_batch_cache_create_overlay_batches(me);
|
||||
}
|
||||
|
||||
return cache->overlay_triangles;
|
||||
}
|
||||
|
||||
Batch *BKE_mesh_batch_cache_get_overlay_loose_edges(Mesh *me)
|
||||
{
|
||||
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
||||
|
||||
if (cache->overlay_loose_edges == NULL) {
|
||||
mesh_batch_cache_create_overlay_batches(me);
|
||||
}
|
||||
|
||||
return cache->overlay_loose_edges;
|
||||
}
|
||||
|
||||
Batch *BKE_mesh_batch_cache_get_overlay_loose_verts(Mesh *me)
|
||||
{
|
||||
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
||||
|
||||
if (cache->overlay_loose_verts == NULL) {
|
||||
mesh_batch_cache_create_overlay_batches(me);
|
||||
}
|
||||
|
||||
return cache->overlay_loose_verts;
|
||||
}
|
||||
|
||||
#undef MESH_RENDER_FUNCTION
|
||||
|
|
|
@ -866,18 +866,18 @@ Batch *DRW_cache_single_vert_get(void)
|
|||
}
|
||||
|
||||
/* Meshes */
|
||||
Batch *DRW_cache_wire_overlay_get(Object *ob)
|
||||
void DRW_cache_wire_overlay_get(Object *ob, Batch **tris, Batch **ledges, Batch **lverts)
|
||||
{
|
||||
Batch *overlay_wire = NULL;
|
||||
|
||||
BLI_assert(ob->type == OB_MESH);
|
||||
|
||||
Mesh *me = ob->data;
|
||||
#if 1 /* new version not working */
|
||||
overlay_wire = BKE_mesh_batch_cache_get_overlay_edges(me);
|
||||
#else
|
||||
overlay_wire = BKE_mesh_batch_cache_get_all_edges(me);
|
||||
#endif
|
||||
|
||||
*tris = BKE_mesh_batch_cache_get_overlay_triangles(me);
|
||||
*ledges = BKE_mesh_batch_cache_get_overlay_loose_edges(me);
|
||||
*lverts = BKE_mesh_batch_cache_get_overlay_loose_verts(me);
|
||||
|
||||
return overlay_wire;
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,8 @@ struct Batch *DRW_cache_bone_point_wire_outline_get(void);
|
|||
struct Batch *DRW_cache_bone_arrows_get(void);
|
||||
|
||||
/* Meshes */
|
||||
struct Batch *DRW_cache_wire_overlay_get(struct Object *ob);
|
||||
void DRW_cache_wire_overlay_get(
|
||||
struct Object *ob, struct Batch **tris, struct Batch **ledges, struct Batch **lverts);
|
||||
struct Batch *DRW_cache_wire_outline_get(struct Object *ob);
|
||||
struct Batch *DRW_cache_surface_get(struct Object *ob);
|
||||
|
||||
|
|
|
@ -433,28 +433,6 @@ static int draw_object_wire_theme(Object *ob, float **color)
|
|||
return theme_id;
|
||||
}
|
||||
|
||||
void DRW_shgroup_wire_overlay(Object *ob)
|
||||
{
|
||||
#if 1
|
||||
struct Batch *geom = DRW_cache_wire_overlay_get(ob);
|
||||
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_EDGES_OVERLAY);
|
||||
|
||||
DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_overlay);
|
||||
DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1);
|
||||
|
||||
DRW_shgroup_call_add(grp, geom, ob->obmat);
|
||||
#else
|
||||
static float col[4] = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
struct Batch *geom = DRW_cache_wire_overlay_get(ob);
|
||||
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
|
||||
|
||||
DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_overlay);
|
||||
DRW_shgroup_uniform_vec4(grp, "color", col, 1);
|
||||
|
||||
DRW_shgroup_call_add(grp, geom, ob->obmat);
|
||||
#endif
|
||||
}
|
||||
|
||||
void DRW_shgroup_wire_outline(Object *ob, const bool do_front, const bool do_back, const bool do_outline)
|
||||
{
|
||||
GPUShader *sh;
|
||||
|
|
|
@ -38,7 +38,6 @@ void DRW_mode_passes_setup(struct DRWPass **psl_wire_overlay,
|
|||
struct DRWPass **psl_bone_solid,
|
||||
struct DRWPass **psl_bone_wire);
|
||||
|
||||
void DRW_shgroup_wire_overlay(struct Object *ob);
|
||||
void DRW_shgroup_wire_outline(struct Object *ob, const bool do_front, const bool do_back, const bool do_outline);
|
||||
void DRW_shgroup_lamp(struct Object *ob);
|
||||
void DRW_shgroup_empty(struct Object *ob);
|
||||
|
|
|
@ -43,27 +43,34 @@ typedef struct EDIT_MESH_PassList {
|
|||
|
||||
static DRWShadingGroup *depth_shgrp_hidden_wire;
|
||||
static DRWShadingGroup *face_overlay_shgrp;
|
||||
static DRWShadingGroup *ledges_overlay_shgrp;
|
||||
static DRWShadingGroup *lverts_overlay_shgrp;
|
||||
|
||||
void EDIT_MESH_cache_init(void)
|
||||
{
|
||||
EDIT_MESH_PassList *psl = DRW_mode_pass_list_get();
|
||||
static struct GPUShader *depth_sh;
|
||||
static struct GPUShader *overlay_sh;
|
||||
static struct GPUShader *over_tri_sh, *over_vert_sh, *over_edge_sh;
|
||||
|
||||
if (!depth_sh) {
|
||||
if (!depth_sh)
|
||||
depth_sh = DRW_shader_create_3D_depth_only();
|
||||
}
|
||||
|
||||
if (!overlay_sh) {
|
||||
overlay_sh = GPU_shader_get_builtin_shader(GPU_SHADER_EDGES_OVERLAY_EDIT);
|
||||
}
|
||||
if (!over_tri_sh)
|
||||
over_tri_sh = GPU_shader_get_builtin_shader(GPU_SHADER_EDGES_OVERLAY_EDIT_TRI);
|
||||
if (!over_edge_sh)
|
||||
over_edge_sh = GPU_shader_get_builtin_shader(GPU_SHADER_EDGES_OVERLAY_EDIT_EDGE);
|
||||
if (!over_vert_sh)
|
||||
over_vert_sh = GPU_shader_get_builtin_shader(GPU_SHADER_EDGES_OVERLAY_EDIT_VERT);
|
||||
|
||||
psl->depth_pass_hidden_wire = DRW_pass_create("Depth Pass Hidden Wire", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_CULL_BACK);
|
||||
depth_shgrp_hidden_wire = DRW_shgroup_create(depth_sh, psl->depth_pass_hidden_wire);
|
||||
|
||||
psl->edit_face_overlay_pass = DRW_pass_create("Edit Mesh Face Overlay Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND);
|
||||
face_overlay_shgrp = DRW_shgroup_create(overlay_sh, psl->edit_face_overlay_pass);
|
||||
psl->edit_face_overlay_pass = DRW_pass_create("Edit Mesh Face Overlay Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND);
|
||||
face_overlay_shgrp = DRW_shgroup_create(over_tri_sh, psl->edit_face_overlay_pass);
|
||||
ledges_overlay_shgrp = DRW_shgroup_create(over_edge_sh, psl->edit_face_overlay_pass);
|
||||
lverts_overlay_shgrp = DRW_shgroup_create(over_vert_sh, psl->edit_face_overlay_pass);
|
||||
DRW_shgroup_uniform_vec2(face_overlay_shgrp, "viewportSize", DRW_viewport_size_get(), 1);
|
||||
DRW_shgroup_uniform_vec2(ledges_overlay_shgrp, "viewportSize", DRW_viewport_size_get(), 1);
|
||||
DRW_shgroup_uniform_vec2(lverts_overlay_shgrp, "viewportSize", DRW_viewport_size_get(), 1);
|
||||
|
||||
DRW_mode_passes_setup(NULL,
|
||||
NULL,
|
||||
|
@ -76,7 +83,8 @@ void EDIT_MESH_cache_init(void)
|
|||
|
||||
void EDIT_MESH_cache_populate(Object *ob)
|
||||
{
|
||||
struct Batch *geom, *geom_overlay;
|
||||
struct Batch *geom;
|
||||
struct Batch *geo_ovl_tris, *geo_ovl_ledges, *geo_ovl_lverts;
|
||||
const struct bContext *C = DRW_get_context();
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Object *obedit = scene->obedit;
|
||||
|
@ -88,8 +96,10 @@ void EDIT_MESH_cache_populate(Object *ob)
|
|||
case OB_MESH:
|
||||
geom = DRW_cache_surface_get(ob);
|
||||
if (ob == obedit) {
|
||||
geom_overlay = DRW_cache_wire_overlay_get(ob);
|
||||
DRW_shgroup_call_add(face_overlay_shgrp, geom_overlay, ob->obmat);
|
||||
DRW_cache_wire_overlay_get(ob, &geo_ovl_tris, &geo_ovl_ledges, &geo_ovl_lverts);
|
||||
DRW_shgroup_call_add(face_overlay_shgrp, geo_ovl_tris, ob->obmat);
|
||||
DRW_shgroup_call_add(ledges_overlay_shgrp, geo_ovl_ledges, ob->obmat);
|
||||
DRW_shgroup_call_add(lverts_overlay_shgrp, geo_ovl_lverts, ob->obmat);
|
||||
}
|
||||
if (do_occlude_wire) {
|
||||
DRW_shgroup_call_add(depth_shgrp_hidden_wire, geom, ob->obmat);
|
||||
|
|
|
@ -4049,7 +4049,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
|
|||
#endif
|
||||
}
|
||||
|
||||
static void draw_em_fancy_new(Scene *UNUSED(scene), ARegion *ar, View3D *UNUSED(v3d),
|
||||
static void draw_em_fancy_new(Scene *UNUSED(scene), ARegion *UNUSED(ar), View3D *UNUSED(v3d),
|
||||
Object *UNUSED(ob), Mesh *me, BMEditMesh *UNUSED(em), DerivedMesh *UNUSED(cageDM), DerivedMesh *UNUSED(finalDM), const char UNUSED(dt))
|
||||
{
|
||||
/* for now... something simple! */
|
||||
|
@ -4087,10 +4087,12 @@ static void draw_em_fancy_new(Scene *UNUSED(scene), ARegion *ar, View3D *UNUSED(
|
|||
Batch_draw(surface);
|
||||
|
||||
if (GLEW_VERSION_3_2) {
|
||||
#if 0
|
||||
Batch *overlay = BKE_mesh_batch_cache_get_overlay_edges(me);
|
||||
Batch_set_builtin_program(overlay, GPU_SHADER_EDGES_OVERLAY);
|
||||
Batch_Uniform2f(overlay, "viewportSize", ar->winx, ar->winy);
|
||||
Batch_draw(overlay);
|
||||
#endif
|
||||
|
||||
#if 0 /* TODO: use this SIMPLE variant for pure triangle meshes */
|
||||
Batch_set_builtin_program(surface, GPU_SHADER_EDGES_OVERLAY_SIMPLE);
|
||||
|
|
|
@ -192,7 +192,9 @@ data_to_c_simple(shaders/gpu_shader_edges_overlay_geom.glsl SRC)
|
|||
data_to_c_simple(shaders/gpu_shader_edges_overlay_simple_geom.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_edges_overlay_frag.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_edit_overlay_frag.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_edit_overlay_geom.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_edit_overlay_geom_tri.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_edit_overlay_geom_edge.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_edit_overlay_geom_vert.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_edit_overlay_vert.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_text_vert.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_text_frag.glsl SRC)
|
||||
|
|
|
@ -100,7 +100,9 @@ typedef enum GPUBuiltinShader {
|
|||
GPU_SHADER_EDGES_FRONT_BACK_PERSP,
|
||||
GPU_SHADER_EDGES_FRONT_BACK_ORTHO,
|
||||
GPU_SHADER_EDGES_OVERLAY_SIMPLE,
|
||||
GPU_SHADER_EDGES_OVERLAY_EDIT,
|
||||
GPU_SHADER_EDGES_OVERLAY_EDIT_TRI,
|
||||
GPU_SHADER_EDGES_OVERLAY_EDIT_VERT,
|
||||
GPU_SHADER_EDGES_OVERLAY_EDIT_EDGE,
|
||||
GPU_SHADER_EDGES_OVERLAY,
|
||||
GPU_SHADER_KEYFRAME_DIAMOND,
|
||||
GPU_SHADER_SIMPLE_LIGHTING,
|
||||
|
|
|
@ -110,7 +110,9 @@ extern char datatoc_gpu_shader_edges_overlay_geom_glsl[];
|
|||
extern char datatoc_gpu_shader_edges_overlay_simple_geom_glsl[];
|
||||
extern char datatoc_gpu_shader_edges_overlay_frag_glsl[];
|
||||
extern char datatoc_gpu_shader_edit_overlay_frag_glsl[];
|
||||
extern char datatoc_gpu_shader_edit_overlay_geom_glsl[];
|
||||
extern char datatoc_gpu_shader_edit_overlay_geom_tri_glsl[];
|
||||
extern char datatoc_gpu_shader_edit_overlay_geom_edge_glsl[];
|
||||
extern char datatoc_gpu_shader_edit_overlay_geom_vert_glsl[];
|
||||
extern char datatoc_gpu_shader_edit_overlay_vert_glsl[];
|
||||
extern char datatoc_gpu_shader_text_vert_glsl[];
|
||||
extern char datatoc_gpu_shader_text_frag_glsl[];
|
||||
|
@ -670,9 +672,15 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
|
|||
datatoc_gpu_shader_flat_color_frag_glsl },
|
||||
[GPU_SHADER_EDGES_OVERLAY_SIMPLE] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_edges_overlay_frag_glsl,
|
||||
datatoc_gpu_shader_edges_overlay_simple_geom_glsl },
|
||||
[GPU_SHADER_EDGES_OVERLAY_EDIT] = { datatoc_gpu_shader_edit_overlay_vert_glsl,
|
||||
datatoc_gpu_shader_edit_overlay_frag_glsl,
|
||||
datatoc_gpu_shader_edit_overlay_geom_glsl },
|
||||
[GPU_SHADER_EDGES_OVERLAY_EDIT_TRI] = { datatoc_gpu_shader_edit_overlay_vert_glsl,
|
||||
datatoc_gpu_shader_edit_overlay_frag_glsl,
|
||||
datatoc_gpu_shader_edit_overlay_geom_tri_glsl },
|
||||
[GPU_SHADER_EDGES_OVERLAY_EDIT_EDGE] = { datatoc_gpu_shader_edit_overlay_vert_glsl,
|
||||
datatoc_gpu_shader_edit_overlay_frag_glsl,
|
||||
datatoc_gpu_shader_edit_overlay_geom_edge_glsl },
|
||||
[GPU_SHADER_EDGES_OVERLAY_EDIT_VERT] = { datatoc_gpu_shader_edit_overlay_vert_glsl,
|
||||
datatoc_gpu_shader_edit_overlay_frag_glsl,
|
||||
datatoc_gpu_shader_edit_overlay_geom_vert_glsl },
|
||||
[GPU_SHADER_EDGES_OVERLAY] = { datatoc_gpu_shader_edges_overlay_vert_glsl,
|
||||
datatoc_gpu_shader_edges_overlay_frag_glsl,
|
||||
datatoc_gpu_shader_edges_overlay_geom_glsl },
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
|
||||
/* Solid Wirefram implementation
|
||||
* Mike Erwin, Clément Foucault */
|
||||
|
||||
/* This shader follows the principles of
|
||||
* http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */
|
||||
|
||||
layout(lines) in;
|
||||
layout(triangle_strip, max_vertices=6) out;
|
||||
|
||||
const float fixupSize = 9.5; /* in pixels */
|
||||
|
||||
uniform mat4 ProjectionMatrix;
|
||||
uniform vec2 viewportSize;
|
||||
|
||||
in vec4 vPos[];
|
||||
in vec4 pPos[];
|
||||
in ivec4 vData[];
|
||||
|
||||
/* these are the same for all vertices
|
||||
* and does not need interpolation */
|
||||
flat out vec3 edgesCrease;
|
||||
flat out vec3 edgesSharp;
|
||||
flat out ivec3 flag;
|
||||
flat out vec4 faceColor;
|
||||
flat out int clipCase;
|
||||
#ifdef VERTEX_SELECTION
|
||||
smooth out vec3 vertexColor;
|
||||
#endif
|
||||
|
||||
/* See fragment shader */
|
||||
noperspective out vec4 eData1;
|
||||
flat out vec4 eData2;
|
||||
|
||||
#define VERTEX_ACTIVE (1 << 0)
|
||||
#define VERTEX_SELECTED (1 << 1)
|
||||
|
||||
#define FACE_ACTIVE (1 << 2)
|
||||
#define FACE_SELECTED (1 << 3)
|
||||
|
||||
/* Table 1. Triangle Projection Cases */
|
||||
const ivec4 clipPointsIdx[6] = ivec4[6](
|
||||
ivec4(0, 1, 2, 2),
|
||||
ivec4(0, 2, 1, 1),
|
||||
ivec4(0, 0, 1, 2),
|
||||
ivec4(1, 2, 0, 0),
|
||||
ivec4(1, 1, 0, 2),
|
||||
ivec4(2, 2, 0, 1)
|
||||
);
|
||||
|
||||
/* project to screen space */
|
||||
vec2 proj(vec4 pos)
|
||||
{
|
||||
return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
|
||||
}
|
||||
|
||||
float dist(vec2 pos[3], vec2 vpos, int v)
|
||||
{
|
||||
/* endpoints of opposite edge */
|
||||
vec2 e1 = pos[(v + 1) % 3];
|
||||
vec2 e2 = pos[(v + 2) % 3];
|
||||
/* Edge normalized vector */
|
||||
vec2 dir = normalize(e2 - e1);
|
||||
/* perpendicular to dir */
|
||||
vec2 orthogonal = vec2(-dir.y, dir.x);
|
||||
|
||||
return abs(dot(vpos - e1, orthogonal));
|
||||
}
|
||||
|
||||
vec3 getVertexColor(int v)
|
||||
{
|
||||
if ((vData[v].x & VERTEX_ACTIVE) != 0)
|
||||
return vec3(0.0, 1.0, 0.0);
|
||||
else if ((vData[v].x & VERTEX_SELECTED) != 0)
|
||||
return vec3(1.0, 0.0, 0.0);
|
||||
else
|
||||
return vec3(0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
void doVertex(int v, vec4 pos)
|
||||
{
|
||||
#ifdef VERTEX_SELECTION
|
||||
vertexColor = getVertexColor(v);
|
||||
#endif
|
||||
|
||||
gl_Position = pos;
|
||||
|
||||
EmitVertex();
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
clipCase = 0;
|
||||
|
||||
/* Face */
|
||||
faceColor = vec4(0.0);
|
||||
|
||||
/* Proj Vertex */
|
||||
vec2 pos[2] = vec2[2](proj(pPos[0]), proj(pPos[1]));
|
||||
|
||||
/* little optimization use a vec4 to vectorize
|
||||
* following operations */
|
||||
vec4 dirs1, dirs2;
|
||||
|
||||
/* Edge normalized vector */
|
||||
dirs1.xy = normalize(pos[1] - pos[0]);
|
||||
|
||||
/* perpendicular to dir */
|
||||
dirs1.zw = vec2(-dirs1.y, dirs1.x);
|
||||
|
||||
/* Make it view independant */
|
||||
dirs1 *= fixupSize / viewportSize.xyxy;
|
||||
|
||||
dirs2 = dirs1;
|
||||
|
||||
/* Perspective */
|
||||
if (ProjectionMatrix[3][3] == 0.0) {
|
||||
/* vPos[i].z is negative and we don't want
|
||||
* our fixvec to be flipped */
|
||||
dirs1 *= -vPos[0].z;
|
||||
dirs2 *= -vPos[1].z;
|
||||
}
|
||||
|
||||
/* Edge / Vert data */
|
||||
eData1 = vec4(1e10);
|
||||
eData2.zw = pos[0];
|
||||
eData2.xy = pos[1];
|
||||
flag[0] = (vData[0].x << 8);
|
||||
flag[1] = (vData[1].x << 8);
|
||||
flag[2] = 0;
|
||||
|
||||
doVertex(0, pPos[0] + vec4(-dirs1.xy, 0.0, 0.0));
|
||||
doVertex(0, pPos[0] + vec4( dirs1.zw, 0.0, 0.0));
|
||||
doVertex(0, pPos[0] + vec4(-dirs1.zw, 0.0, 0.0));
|
||||
|
||||
flag[2] = vData[0].y | (vData[0].x << 8);
|
||||
edgesCrease[2] = vData[0].z / 255.0;
|
||||
edgesSharp[2] = vData[0].w / 255.0;
|
||||
|
||||
doVertex(1, pPos[1] + vec4( dirs2.zw, 0.0, 0.0));
|
||||
doVertex(1, pPos[1] + vec4(-dirs2.zw, 0.0, 0.0));
|
||||
|
||||
flag[2] = 0;
|
||||
doVertex(1, pPos[1] + vec4( dirs2.xy, 0.0, 0.0));
|
||||
|
||||
EndPrimitive();
|
||||
}
|
|
@ -5,8 +5,7 @@
|
|||
/* This shader follows the principles of
|
||||
* http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */
|
||||
|
||||
#define EDGE_FIX
|
||||
|
||||
//#define EDGE_FIX
|
||||
layout(triangles) in;
|
||||
|
||||
#ifdef EDGE_FIX
|
||||
|
@ -39,9 +38,9 @@ flat out vec3 edgesSharp;
|
|||
flat out ivec3 flag;
|
||||
flat out vec4 faceColor;
|
||||
flat out int clipCase;
|
||||
// #ifdef VERTEX_SELECTION
|
||||
#ifdef VERTEX_SELECTION
|
||||
smooth out vec3 vertexColor;
|
||||
// #endif
|
||||
#endif
|
||||
|
||||
/* See fragment shader */
|
||||
noperspective out vec4 eData1;
|
||||
|
@ -50,10 +49,9 @@ flat out vec4 eData2;
|
|||
|
||||
#define VERTEX_ACTIVE (1 << 0)
|
||||
#define VERTEX_SELECTED (1 << 1)
|
||||
#define VERTEX_LOOSE (1 << 2)
|
||||
|
||||
#define FACE_ACTIVE (1 << 3)
|
||||
#define FACE_SELECTED (1 << 4)
|
||||
#define FACE_ACTIVE (1 << 2)
|
||||
#define FACE_SELECTED (1 << 3)
|
||||
|
||||
/* Table 1. Triangle Projection Cases */
|
||||
const ivec4 clipPointsIdx[6] = ivec4[6](
|
||||
|
@ -113,19 +111,6 @@ void doVertex(int v, vec4 pos)
|
|||
EmitVertex();
|
||||
}
|
||||
|
||||
void doLooseVertex(int v, vec4 pos, vec2 fixvec)
|
||||
{
|
||||
doVertex(v, pos + vec4( fixvec.x, fixvec.y, 0.0, 0.0));
|
||||
|
||||
/* Quad */
|
||||
doVertex(v, pos + vec4( fixvec.x, fixvec.y, 0.0, 0.0));
|
||||
doVertex(v, pos + vec4(-fixvec.x, fixvec.y, 0.0, 0.0));
|
||||
doVertex(v, pos + vec4( fixvec.x, -fixvec.y, 0.0, 0.0));
|
||||
doVertex(v, pos + vec4(-fixvec.x, -fixvec.y, 0.0, 0.0));
|
||||
|
||||
doVertex(v, pos + vec4(-fixvec.x, -fixvec.y, 0.0, 0.0));
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
/* First we detect which case we are in */
|
||||
|
@ -165,38 +150,9 @@ void main()
|
|||
/* Vertex */
|
||||
vec2 pos[3] = vec2[3](proj(pPos[0]), proj(pPos[1]), proj(pPos[2]));
|
||||
|
||||
/* Loose Vertex : emit quads linked by degenerate triangles */
|
||||
if ((vData[0].x & VERTEX_LOOSE) != 0) {
|
||||
vec2 fixvec[3];
|
||||
|
||||
/* there is no face */
|
||||
faceColor = vec4(0.0);
|
||||
|
||||
/* and don't forget to overide clipCase */
|
||||
clipCase = 0;
|
||||
|
||||
/* only verterx position 0 is used */
|
||||
eData1 = eData2 = vec4(1e10);
|
||||
|
||||
vec2 dir = vec2(1.0) * fixupSize;
|
||||
/* Make it view independant */
|
||||
dir /= viewportSize;
|
||||
|
||||
for (int v = 0; v < 3; ++v) {
|
||||
fixvec[v] = dir;
|
||||
if (ProjectionMatrix[3][3] == 0.0) {
|
||||
fixvec[v] *= -vPos[v].z;
|
||||
}
|
||||
}
|
||||
|
||||
for (int v = 0; v < 3; ++v) {
|
||||
eData2.zw = pos[v];
|
||||
flag[0] = (vData[v].x << 8);
|
||||
doLooseVertex(v, pPos[v], fixvec[v]);
|
||||
}
|
||||
}
|
||||
/* Simple case : compute edge distances in geometry shader */
|
||||
else if (clipCase == 0) {
|
||||
if (clipCase == 0) {
|
||||
|
||||
/* Packing screen positions and 2 distances */
|
||||
eData1 = vec4(0.0, 0.0, pos[2]);
|
|
@ -0,0 +1,72 @@
|
|||
|
||||
/* Solid Wirefram implementation
|
||||
* Mike Erwin, Clément Foucault */
|
||||
|
||||
/* This shader follows the principles of
|
||||
* http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */
|
||||
|
||||
layout(points) in;
|
||||
layout(triangle_strip, max_vertices=4) out;
|
||||
|
||||
const float fixupSize = 9.5; /* in pixels */
|
||||
|
||||
uniform mat4 ProjectionMatrix;
|
||||
uniform vec2 viewportSize;
|
||||
|
||||
in vec4 vPos[];
|
||||
in vec4 pPos[];
|
||||
in ivec4 vData[];
|
||||
|
||||
/* these are the same for all vertices
|
||||
* and does not need interpolation */
|
||||
flat out ivec3 flag;
|
||||
flat out vec4 faceColor;
|
||||
flat out int clipCase;
|
||||
|
||||
/* See fragment shader */
|
||||
noperspective out vec4 eData1;
|
||||
flat out vec4 eData2;
|
||||
|
||||
/* project to screen space */
|
||||
vec2 proj(vec4 pos)
|
||||
{
|
||||
return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
|
||||
}
|
||||
|
||||
void doVertex(vec4 pos)
|
||||
{
|
||||
gl_Position = pos;
|
||||
EmitVertex();
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
clipCase = 0;
|
||||
|
||||
/* there is no face */
|
||||
faceColor = vec4(0.0);
|
||||
|
||||
/* only verterx position 0 is used */
|
||||
eData1 = eData2 = vec4(1e10);
|
||||
flag = ivec3(0);
|
||||
|
||||
vec2 dir = vec2(1.0) * fixupSize;
|
||||
/* Make it view independant */
|
||||
dir /= viewportSize;
|
||||
|
||||
if (ProjectionMatrix[3][3] == 0.0) {
|
||||
dir *= -vPos[0].z;
|
||||
}
|
||||
|
||||
eData2.zw = proj(pPos[0]);
|
||||
|
||||
flag[0] = (vData[0].x << 8);
|
||||
|
||||
/* Quad */
|
||||
doVertex(pPos[0] + vec4( dir.x, dir.y, 0.0, 0.0));
|
||||
doVertex(pPos[0] + vec4(-dir.x, dir.y, 0.0, 0.0));
|
||||
doVertex(pPos[0] + vec4( dir.x, -dir.y, 0.0, 0.0));
|
||||
doVertex(pPos[0] + vec4(-dir.x, -dir.y, 0.0, 0.0));
|
||||
|
||||
EndPrimitive();
|
||||
}
|
Loading…
Reference in New Issue