Weight Paint Overlay: Refactor wire drawing
This reduce the number of batch/data needed. Stores a select/visiblee flag inside the vert/loop normals.
This commit is contained in:
parent
4fceaf3848
commit
6a1315d6e7
|
@ -2992,22 +2992,6 @@ GPUBatch *DRW_cache_single_vert_get(void)
|
|||
/** \name Meshes
|
||||
* \{ */
|
||||
|
||||
GPUBatch *DRW_cache_mesh_surface_overlay_get(Object *ob)
|
||||
{
|
||||
BLI_assert(ob->type == OB_MESH);
|
||||
Mesh *me = ob->data;
|
||||
return DRW_mesh_batch_cache_get_all_triangles(me);
|
||||
}
|
||||
|
||||
GPUBatch *DRW_cache_face_centers_get(Object *ob)
|
||||
{
|
||||
BLI_assert(ob->type == OB_MESH);
|
||||
|
||||
Mesh *me = ob->data;
|
||||
|
||||
return DRW_mesh_batch_cache_get_edit_facedots(me);
|
||||
}
|
||||
|
||||
GPUBatch *DRW_cache_mesh_wire_outline_get(Object *ob)
|
||||
{
|
||||
BLI_assert(ob->type == OB_MESH);
|
||||
|
|
|
@ -124,8 +124,6 @@ struct GPUBatch *DRW_cache_bone_dof_sphere_get(void);
|
|||
struct GPUBatch *DRW_cache_bone_dof_lines_get(void);
|
||||
|
||||
/* Meshes */
|
||||
struct GPUBatch *DRW_cache_mesh_surface_overlay_get(struct Object *ob);
|
||||
struct GPUBatch *DRW_cache_face_centers_get(struct Object *ob);
|
||||
struct GPUBatch *DRW_cache_mesh_wire_outline_get(struct Object *ob);
|
||||
struct GPUBatch *DRW_cache_mesh_edge_detection_get(struct Object *ob, bool *r_is_manifold);
|
||||
struct GPUBatch *DRW_cache_mesh_surface_get(struct Object *ob);
|
||||
|
|
|
@ -130,7 +130,6 @@ struct GPUBatch *DRW_mesh_batch_cache_get_wire_loops(struct Mesh *me);
|
|||
struct GPUBatch *DRW_mesh_batch_cache_get_weight_overlay_faces(struct Mesh *me);
|
||||
struct GPUBatch *DRW_mesh_batch_cache_get_weight_overlay_verts(struct Mesh *me);
|
||||
struct GPUBatch *DRW_mesh_batch_cache_get_all_edges(struct Mesh *me);
|
||||
struct GPUBatch *DRW_mesh_batch_cache_get_all_triangles(struct Mesh *me);
|
||||
struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_normals(struct Mesh *me);
|
||||
struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_normals_and_weights(struct Mesh *me, const struct DRW_MeshWeightState *wstate);
|
||||
struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_normals_and_vert_colors(struct Mesh *me);
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "BKE_mesh.h"
|
||||
#include "BKE_mesh_tangent.h"
|
||||
#include "BKE_mesh_runtime.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_colorband.h"
|
||||
#include "BKE_cdderivedmesh.h"
|
||||
|
||||
|
@ -3345,7 +3346,7 @@ static void mesh_create_pos_and_nor(MeshRenderData *rdata, GPUVertBuf *vbo)
|
|||
static struct { uint pos, nor; } attr_id;
|
||||
if (format.attr_len == 0) {
|
||||
attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
||||
attr_id.nor = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I16, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
|
||||
attr_id.nor = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
|
||||
}
|
||||
|
||||
GPU_vertbuf_init_with_format(vbo, &format);
|
||||
|
@ -3359,19 +3360,22 @@ static void mesh_create_pos_and_nor(MeshRenderData *rdata, GPUVertBuf *vbo)
|
|||
BMVert *eve;
|
||||
uint i;
|
||||
|
||||
BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
|
||||
static short no_short[4];
|
||||
normal_float_to_short_v3(no_short, eve->no);
|
||||
mesh_render_data_ensure_vert_normals_pack(rdata);
|
||||
GPUPackedNormal *vnor = rdata->vert_normals_pack;
|
||||
|
||||
BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
|
||||
GPU_vertbuf_attr_set(vbo, attr_id.pos, i, eve->co);
|
||||
GPU_vertbuf_attr_set(vbo, attr_id.nor, i, no_short);
|
||||
GPU_vertbuf_attr_set(vbo, attr_id.nor, i, &vnor[i]);
|
||||
}
|
||||
BLI_assert(i == vbo_len_capacity);
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < vbo_len_capacity; i++) {
|
||||
const MVert *mv = &rdata->mvert[i];
|
||||
GPUPackedNormal vnor_pack = GPU_normal_convert_i10_s3(mv->no);
|
||||
vnor_pack.w = (mv->flag & ME_HIDE) ? -1 : ((mv->flag & SELECT) ? 1 : 0);
|
||||
GPU_vertbuf_attr_set(vbo, attr_id.pos, i, rdata->mvert[i].co);
|
||||
GPU_vertbuf_attr_set(vbo, attr_id.nor, i, rdata->mvert[i].no);
|
||||
GPU_vertbuf_attr_set(vbo, attr_id.nor, i, &vnor_pack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3382,8 +3386,10 @@ static void mesh_create_pos_and_nor(MeshRenderData *rdata, GPUVertBuf *vbo)
|
|||
const int v_orig = v_origindex[i];
|
||||
if (v_orig != ORIGINDEX_NONE) {
|
||||
const MVert *mv = &mvert[i];
|
||||
GPUPackedNormal vnor_pack = GPU_normal_convert_i10_s3(mv->no);
|
||||
vnor_pack.w = (mv->flag & ME_HIDE) ? -1 : ((mv->flag & SELECT) ? 1 : 0);
|
||||
GPU_vertbuf_attr_set(vbo, attr_id.pos, i, mv->co);
|
||||
GPU_vertbuf_attr_set(vbo, attr_id.nor, i, mv->no);
|
||||
GPU_vertbuf_attr_set(vbo, attr_id.nor, i, &vnor_pack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3471,7 +3477,7 @@ static void mesh_create_loop_pos_and_nor(MeshRenderData *rdata, GPUVertBuf *vbo,
|
|||
*pnor = GPU_normal_convert_i10_s3(mvert[mloop->v].no);
|
||||
}
|
||||
if (use_face_sel) {
|
||||
pnor->w = (mpoly->flag & ME_FACE_SEL) ? 1 : 0;
|
||||
pnor->w = (mpoly->flag & ME_HIDE) ? -1 : ((mpoly->flag & ME_FACE_SEL) ? 1 : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4297,42 +4303,6 @@ static void mesh_create_wireframe_data_tess(MeshRenderData *rdata, GPUVertBuf *v
|
|||
MEM_freeN(adj_data);
|
||||
}
|
||||
|
||||
static GPUIndexBuf *mesh_batch_cache_get_triangles_in_order(MeshRenderData *rdata, MeshBatchCache *cache)
|
||||
{
|
||||
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI));
|
||||
|
||||
if (cache->triangles_in_order == NULL) {
|
||||
const int vert_len = mesh_render_data_verts_len_get(rdata);
|
||||
const int tri_len = mesh_render_data_looptri_len_get(rdata);
|
||||
|
||||
GPUIndexBufBuilder elb;
|
||||
GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tri_len, vert_len);
|
||||
|
||||
if (rdata->edit_bmesh) {
|
||||
for (int i = 0; i < tri_len; i++) {
|
||||
const BMLoop **ltri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
|
||||
if (!BM_elem_flag_test(ltri[0]->f, BM_ELEM_HIDDEN)) {
|
||||
for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
|
||||
GPU_indexbuf_add_generic_vert(&elb, BM_elem_index_get(ltri[tri_corner]->v));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < tri_len; i++) {
|
||||
const MLoopTri *mlt = &rdata->mlooptri[i];
|
||||
for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
|
||||
GPU_indexbuf_add_generic_vert(&elb, mlt->tri[tri_corner]);
|
||||
}
|
||||
}
|
||||
}
|
||||
cache->triangles_in_order = GPU_indexbuf_build(&elb);
|
||||
}
|
||||
|
||||
return cache->triangles_in_order;
|
||||
}
|
||||
|
||||
|
||||
static GPUIndexBuf *mesh_batch_cache_get_loose_edges(MeshRenderData *rdata, MeshBatchCache *cache)
|
||||
{
|
||||
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI));
|
||||
|
@ -4575,6 +4545,12 @@ static GPUVertBuf *mesh_create_vert_pos_with_overlay_data(
|
|||
/** \name Public API
|
||||
* \{ */
|
||||
|
||||
GPUBatch *DRW_mesh_batch_cache_get_all_verts(Mesh *me)
|
||||
{
|
||||
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
||||
return DRW_batch_request(&cache->batch.all_verts);
|
||||
}
|
||||
|
||||
GPUBatch *DRW_mesh_batch_cache_get_all_edges(Mesh *me)
|
||||
{
|
||||
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
||||
|
@ -4594,25 +4570,6 @@ GPUBatch *DRW_mesh_batch_cache_get_all_edges(Mesh *me)
|
|||
return cache->all_edges;
|
||||
}
|
||||
|
||||
GPUBatch *DRW_mesh_batch_cache_get_all_triangles(Mesh *me)
|
||||
{
|
||||
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
||||
|
||||
if (cache->all_triangles == NULL) {
|
||||
/* create batch from DM */
|
||||
const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI;
|
||||
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
|
||||
|
||||
cache->all_triangles = GPU_batch_create(
|
||||
GPU_PRIM_TRIS, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache),
|
||||
mesh_batch_cache_get_triangles_in_order(rdata, cache));
|
||||
|
||||
mesh_render_data_free(rdata);
|
||||
}
|
||||
|
||||
return cache->all_triangles;
|
||||
}
|
||||
|
||||
GPUBatch *DRW_mesh_batch_cache_get_triangles_with_normals(Mesh *me)
|
||||
{
|
||||
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
||||
|
@ -4764,12 +4721,6 @@ GPUBatch *DRW_mesh_batch_cache_get_points_with_normals(Mesh *me)
|
|||
return cache->points_with_normals;
|
||||
}
|
||||
|
||||
GPUBatch *DRW_mesh_batch_cache_get_all_verts(Mesh *me)
|
||||
{
|
||||
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
||||
return DRW_batch_request(&cache->batch.all_verts);
|
||||
}
|
||||
|
||||
GPUBatch *DRW_mesh_batch_cache_get_fancy_edges(Mesh *me)
|
||||
{
|
||||
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
||||
|
@ -5611,11 +5562,13 @@ void DRW_mesh_batch_cache_create_requested(Object *ob, Mesh *me)
|
|||
{
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
const int mode = CTX_data_mode_enum_ex(draw_ctx->object_edit, draw_ctx->obact, draw_ctx->object_mode);
|
||||
const bool use_hide = false; /* TODO */
|
||||
const bool is_paint_mode = ELEM(mode, CTX_MODE_PAINT_TEXTURE, CTX_MODE_PAINT_VERTEX, CTX_MODE_PAINT_WEIGHT);
|
||||
const bool use_hide = (ob->type == OB_MESH) && ((is_paint_mode && (ob == draw_ctx->obact)) ||
|
||||
((mode == CTX_MODE_EDIT_MESH) && BKE_object_is_in_editmode(ob)));
|
||||
bool use_face_sel = false;
|
||||
|
||||
/* Tex paint face select */
|
||||
if ((mode == CTX_MODE_PAINT_TEXTURE) && (ob->type == OB_MESH) && (draw_ctx->obact == ob)) {
|
||||
if (is_paint_mode && (ob->type == OB_MESH) && (draw_ctx->obact == ob)) {
|
||||
const Mesh *me_orig = DEG_get_original_object(ob)->data;
|
||||
use_face_sel = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
|
||||
}
|
||||
|
|
|
@ -351,6 +351,7 @@ static void PAINT_TEXTURE_engine_free(void)
|
|||
{
|
||||
DRW_SHADER_FREE_SAFE(e_data.image_sh);
|
||||
DRW_SHADER_FREE_SAFE(e_data.wire_overlay_shader);
|
||||
DRW_SHADER_FREE_SAFE(e_data.face_overlay_shader);
|
||||
}
|
||||
|
||||
static const DrawEngineDataSize PAINT_TEXTURE_data_size = DRW_VIEWPORT_DATA_SIZE(PAINT_TEXTURE_Data);
|
||||
|
|
|
@ -45,6 +45,7 @@ extern struct GlobalsUboStorage ts; /* draw_common.c */
|
|||
|
||||
extern struct GPUTexture *globals_weight_ramp; /* draw_common.c */
|
||||
|
||||
extern char datatoc_paint_face_vert_glsl[];
|
||||
extern char datatoc_paint_weight_vert_glsl[];
|
||||
extern char datatoc_paint_weight_frag_glsl[];
|
||||
extern char datatoc_paint_wire_vert_glsl[];
|
||||
|
@ -52,6 +53,8 @@ extern char datatoc_paint_wire_frag_glsl[];
|
|||
extern char datatoc_paint_vert_frag_glsl[];
|
||||
extern char datatoc_common_globals_lib_glsl[];
|
||||
|
||||
extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
|
||||
|
||||
/* *********** LISTS *********** */
|
||||
|
||||
typedef struct PAINT_WEIGHT_PassList {
|
||||
|
@ -109,7 +112,9 @@ static void PAINT_WEIGHT_engine_init(void *UNUSED(vedata))
|
|||
}
|
||||
|
||||
if (!e_data.face_overlay_shader) {
|
||||
e_data.face_overlay_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
|
||||
e_data.face_overlay_shader = DRW_shader_create(
|
||||
datatoc_paint_face_vert_glsl, NULL,
|
||||
datatoc_gpu_shader_uniform_color_frag_glsl, NULL);
|
||||
}
|
||||
|
||||
if (!e_data.vert_overlay_shader) {
|
||||
|
@ -150,7 +155,7 @@ static void PAINT_WEIGHT_cache_init(void *vedata)
|
|||
{
|
||||
psl->wire_overlay = DRW_pass_create(
|
||||
"Wire Pass",
|
||||
DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL);
|
||||
DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_OFFSET_NEGATIVE);
|
||||
|
||||
stl->g_data->lwire_shgrp = DRW_shgroup_create(e_data.wire_overlay_shader, psl->wire_overlay);
|
||||
DRW_shgroup_uniform_block(stl->g_data->lwire_shgrp, "globalsBlock", globals_ubo);
|
||||
|
@ -170,7 +175,7 @@ static void PAINT_WEIGHT_cache_init(void *vedata)
|
|||
{
|
||||
psl->vert_overlay = DRW_pass_create(
|
||||
"Vert Mask Pass",
|
||||
DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL);
|
||||
DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_OFFSET_NEGATIVE);
|
||||
|
||||
stl->g_data->vert_shgrp = DRW_shgroup_create(e_data.vert_overlay_shader, psl->vert_overlay);
|
||||
DRW_shgroup_uniform_block(stl->g_data->vert_shgrp, "globalsBlock", globals_ubo);
|
||||
|
@ -202,12 +207,12 @@ static void PAINT_WEIGHT_cache_populate(void *vedata, Object *ob)
|
|||
}
|
||||
|
||||
if (use_face_sel) {
|
||||
geom = DRW_cache_mesh_faces_weight_overlay_get(ob);
|
||||
geom = DRW_cache_mesh_surface_get(ob);
|
||||
DRW_shgroup_call_add(stl->g_data->face_shgrp, geom, ob->obmat);
|
||||
}
|
||||
|
||||
if (use_vert_sel) {
|
||||
geom = DRW_cache_mesh_verts_weight_overlay_get(ob);
|
||||
geom = DRW_cache_mesh_verts_get(ob);
|
||||
DRW_shgroup_call_add(stl->g_data->vert_shgrp, geom, ob->obmat);
|
||||
}
|
||||
}
|
||||
|
@ -228,6 +233,7 @@ static void PAINT_WEIGHT_engine_free(void)
|
|||
DRW_SHADER_FREE_SAFE(e_data.weight_face_shader);
|
||||
DRW_SHADER_FREE_SAFE(e_data.wire_overlay_shader);
|
||||
DRW_SHADER_FREE_SAFE(e_data.vert_overlay_shader);
|
||||
DRW_SHADER_FREE_SAFE(e_data.face_overlay_shader);
|
||||
}
|
||||
|
||||
static const DrawEngineDataSize PAINT_WEIGHT_data_size = DRW_VIEWPORT_DATA_SIZE(PAINT_WEIGHT_Data);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
flat in int finalFlag;
|
||||
flat in vec4 finalColor;
|
||||
out vec4 fragColor;
|
||||
|
||||
#define VERTEX_SELECTED (1 << 0)
|
||||
|
@ -7,10 +7,6 @@ out vec4 fragColor;
|
|||
|
||||
void main()
|
||||
{
|
||||
if (bool(finalFlag & VERTEX_HIDE)) {
|
||||
discard;
|
||||
}
|
||||
|
||||
vec2 centered = gl_PointCoord - vec2(0.5);
|
||||
float dist_squared = dot(centered, centered);
|
||||
const float rad_squared = 0.25;
|
||||
|
@ -22,5 +18,5 @@ void main()
|
|||
discard;
|
||||
}
|
||||
|
||||
fragColor = bool(finalFlag & VERTEX_SELECTED) ? colSel : colUnsel;
|
||||
fragColor = finalColor;
|
||||
}
|
||||
|
|
|
@ -1,25 +1,8 @@
|
|||
|
||||
flat in int finalFlag;
|
||||
flat in vec4 finalColor;
|
||||
out vec4 fragColor;
|
||||
|
||||
#define VERTEX_SELECTED (1 << 0)
|
||||
#define VERTEX_HIDE (1 << 4)
|
||||
|
||||
void main()
|
||||
{
|
||||
if (bool(finalFlag & VERTEX_HIDE)) {
|
||||
discard;
|
||||
}
|
||||
|
||||
/* Apply depth offset by taking slope and distance into account. */
|
||||
gl_FragDepth = gl_FragCoord.z - mix(exp2(-10), exp2(-23), gl_FragCoord.z) - 2.0 * fwidth(gl_FragCoord.z);
|
||||
|
||||
#ifdef VERTEX_MODE
|
||||
vec4 colSel = colorEdgeSelect;
|
||||
colSel.rgb = clamp(colSel.rgb - 0.2, 0.0, 1.0);
|
||||
#else
|
||||
const vec4 colSel = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
#endif
|
||||
|
||||
fragColor = bool(finalFlag & VERTEX_SELECTED) ? colSel : colorWire;
|
||||
fragColor = finalColor;
|
||||
}
|
||||
|
|
|
@ -2,13 +2,30 @@
|
|||
uniform mat4 ModelViewProjectionMatrix;
|
||||
|
||||
in vec3 pos;
|
||||
in int data;
|
||||
in vec4 nor; /* flag stored in w */
|
||||
|
||||
flat out int finalFlag;
|
||||
flat out vec4 finalColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
bool is_select = (nor.w > 0.0);
|
||||
bool is_hidden = (nor.w < 0.0);
|
||||
gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
|
||||
/* Add offset in Z to avoid zfighting and render selected wires on top. */
|
||||
/* TODO scale this bias using znear and zfar range. */
|
||||
gl_Position.zw -= exp2(-20) * (is_select ? 2.0 : 1.0);
|
||||
|
||||
finalFlag = data;
|
||||
if (is_hidden) {
|
||||
gl_Position = vec4(-2.0, -2.0, -2.0, 1.0);
|
||||
}
|
||||
|
||||
#ifdef VERTEX_MODE
|
||||
vec4 colSel = colorEdgeSelect;
|
||||
colSel.rgb = clamp(colSel.rgb - 0.2, 0.0, 1.0);
|
||||
#else
|
||||
const vec4 colSel = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
#endif
|
||||
|
||||
finalColor = (is_select) ? colSel : colorWire;
|
||||
finalColor.a = nor.w;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue