diff options
-rw-r--r-- | release/scripts/startup/bl_ui/properties_collection.py | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_mesh_render.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh_render.c | 130 | ||||
-rw-r--r-- | source/blender/draw/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache.c | 24 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache.h | 2 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager.c | 1 | ||||
-rw-r--r-- | source/blender/draw/modes/edit_mesh_mode.c | 131 | ||||
-rw-r--r-- | source/blender/draw/modes/shaders/edit_normals_face_vert.glsl | 18 | ||||
-rw-r--r-- | source/blender/draw/modes/shaders/edit_normals_geom.glsl | 15 | ||||
-rw-r--r-- | source/blender/draw/modes/shaders/edit_normals_vert.glsl | 24 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_scene.c | 34 |
12 files changed, 312 insertions, 74 deletions
diff --git a/release/scripts/startup/bl_ui/properties_collection.py b/release/scripts/startup/bl_ui/properties_collection.py index 6debbaf3aac..7cbdeb6e61d 100644 --- a/release/scripts/startup/bl_ui/properties_collection.py +++ b/release/scripts/startup/bl_ui/properties_collection.py @@ -128,6 +128,10 @@ class COLLECTION_PT_edit_mode_settings(CollectionButtonsPanel, Panel): col = layout.column() template_engine_settings(col, settings, "show_occlude_wire") template_engine_settings(col, settings, "backwire_opacity") + template_engine_settings(col, settings, "face_normals_show") + template_engine_settings(col, settings, "vert_normals_show") + template_engine_settings(col, settings, "loop_normals_show") + template_engine_settings(col, settings, "normals_length") if __name__ == "__main__": # only for live edit. diff --git a/source/blender/blenkernel/BKE_mesh_render.h b/source/blender/blenkernel/BKE_mesh_render.h index 0b51dc3d9d7..0869c96abf0 100644 --- a/source/blender/blenkernel/BKE_mesh_render.h +++ b/source/blender/blenkernel/BKE_mesh_render.h @@ -39,6 +39,7 @@ void BKE_mesh_batch_cache_free(struct Mesh *me); struct Batch *BKE_mesh_batch_cache_get_all_edges(struct Mesh *me); 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_points_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_triangles(struct Mesh *me); diff --git a/source/blender/blenkernel/intern/mesh_render.c b/source/blender/blenkernel/intern/mesh_render.c index 67991d08f9d..dbe99acc10b 100644 --- a/source/blender/blenkernel/intern/mesh_render.c +++ b/source/blender/blenkernel/intern/mesh_render.c @@ -318,6 +318,22 @@ static float *mesh_render_data_vert_co(const MeshRenderData *mrdata, const int v } } +static short *mesh_render_data_vert_nor(const MeshRenderData *mrdata, const int vert_idx) +{ + BLI_assert(mrdata->types & MR_DATATYPE_VERT); + + if (mrdata->edit_bmesh) { + static short fno[3]; + BMesh *bm = mrdata->edit_bmesh->bm; + BMVert *bv = BM_vert_at_index(bm, vert_idx); + normal_float_to_short_v3(fno, bv->no); + return fno; + } + else { + return mrdata->mvert[vert_idx].no; + } +} + static void mesh_render_data_edge_verts_indices_get(const MeshRenderData *mrdata, const int edge_idx, int r_vert_idx[2]) { BLI_assert(mrdata->types & MR_DATATYPE_EDGE); @@ -710,6 +726,7 @@ static void add_overlay_loose_vert( typedef struct MeshBatchCache { VertexBuffer *pos_in_order; + VertexBuffer *nor_in_order; ElementList *edges_in_order; ElementList *triangles_in_order; @@ -717,7 +734,9 @@ typedef struct MeshBatchCache { Batch *all_edges; Batch *all_triangles; - Batch *triangles_with_normals; /* owns its vertex buffer */ + VertexBuffer *pos_with_normals; + Batch *triangles_with_normals; + Batch *points_with_normals; Batch *fancy_edges; /* owns its vertex buffer (not shared) */ /* TODO : split in 2 buffers to avoid unnecessary @@ -855,9 +874,10 @@ void BKE_mesh_batch_cache_clear(Mesh *me) if (cache->overlay_loose_edges) Batch_discard_all(cache->overlay_loose_edges); if (cache->overlay_facedots) Batch_discard_all(cache->overlay_facedots); - if (cache->triangles_with_normals) { - Batch_discard_all(cache->triangles_with_normals); - } + if (cache->triangles_with_normals) Batch_discard(cache->triangles_with_normals); + if (cache->points_with_normals) Batch_discard(cache->points_with_normals); + if (cache->pos_with_normals) VertexBuffer_discard(cache->pos_with_normals); + if (cache->fancy_edges) { Batch_discard_all(cache->fancy_edges); @@ -872,16 +892,61 @@ void BKE_mesh_batch_cache_free(Mesh *me) /* Batch cache usage. */ -static VertexBuffer *mesh_batch_cache_get_pos_in_order(MeshRenderData *mrdata, MeshBatchCache *cache) +static VertexBuffer *mesh_batch_cache_get_pos_and_normals(MeshRenderData *mrdata, MeshBatchCache *cache) +{ + BLI_assert(mrdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY)); + + if (cache->pos_with_normals == NULL) { + unsigned int vidx = 0, nidx = 0; + + static VertexFormat format = { 0 }; + static unsigned int pos_id, nor_id; + if (format.attrib_ct == 0) { + /* initialize vertex format */ + pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + nor_id = add_attrib(&format, "nor", GL_SHORT, 3, NORMALIZE_INT_TO_FLOAT); + } + + const int tottri = mesh_render_data_looptri_num_get(mrdata); + + cache->pos_with_normals = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(cache->pos_with_normals, tottri * 3); + + for (int i = 0; i < tottri; i++) { + float *tri_vert_cos[3]; + short *tri_nor, *tri_vert_nors[3]; + + const bool is_smooth = mesh_render_data_looptri_cos_nors_smooth_get(mrdata, i, &tri_vert_cos, &tri_nor, &tri_vert_nors); + + if (is_smooth) { + setAttrib(cache->pos_with_normals, nor_id, nidx++, tri_vert_nors[0]); + setAttrib(cache->pos_with_normals, nor_id, nidx++, tri_vert_nors[1]); + setAttrib(cache->pos_with_normals, nor_id, nidx++, tri_vert_nors[2]); + } + else { + setAttrib(cache->pos_with_normals, nor_id, nidx++, tri_nor); + setAttrib(cache->pos_with_normals, nor_id, nidx++, tri_nor); + setAttrib(cache->pos_with_normals, nor_id, nidx++, tri_nor); + } + + setAttrib(cache->pos_with_normals, pos_id, vidx++, tri_vert_cos[0]); + setAttrib(cache->pos_with_normals, pos_id, vidx++, tri_vert_cos[1]); + setAttrib(cache->pos_with_normals, pos_id, vidx++, tri_vert_cos[2]); + } + } + return cache->pos_with_normals; +} +static VertexBuffer *mesh_batch_cache_get_pos_and_nor_in_order(MeshRenderData *mrdata, MeshBatchCache *cache) { BLI_assert(mrdata->types & MR_DATATYPE_VERT); if (cache->pos_in_order == NULL) { static VertexFormat format = { 0 }; - static unsigned pos_id; + static unsigned pos_id, nor_id; if (format.attrib_ct == 0) { /* initialize vertex format */ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + nor_id = add_attrib(&format, "nor", GL_SHORT, 3, NORMALIZE_INT_TO_FLOAT); } const int vertex_ct = mesh_render_data_verts_num_get(mrdata); @@ -890,6 +955,7 @@ static VertexBuffer *mesh_batch_cache_get_pos_in_order(MeshRenderData *mrdata, M VertexBuffer_allocate_data(cache->pos_in_order, vertex_ct); for (int i = 0; i < vertex_ct; ++i) { setAttrib(cache->pos_in_order, pos_id, i, mesh_render_data_vert_co(mrdata, i)); + setAttrib(cache->pos_in_order, nor_id, i, mesh_render_data_vert_nor(mrdata, i)); } } @@ -948,7 +1014,7 @@ Batch *BKE_mesh_batch_cache_get_all_edges(Mesh *me) /* create batch from Mesh */ MeshRenderData *mrdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_EDGE); - cache->all_edges = Batch_create(GL_LINES, mesh_batch_cache_get_pos_in_order(mrdata, cache), + cache->all_edges = Batch_create(GL_LINES, mesh_batch_cache_get_pos_and_nor_in_order(mrdata, cache), mesh_batch_cache_get_edges_in_order(mrdata, cache)); mesh_render_data_free(mrdata); @@ -965,7 +1031,7 @@ Batch *BKE_mesh_batch_cache_get_all_triangles(Mesh *me) /* create batch from DM */ MeshRenderData *mrdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI); - cache->all_triangles = Batch_create(GL_TRIANGLES, mesh_batch_cache_get_pos_in_order(mrdata, cache), + cache->all_triangles = Batch_create(GL_TRIANGLES, mesh_batch_cache_get_pos_and_nor_in_order(mrdata, cache), mesh_batch_cache_get_triangles_in_order(mrdata, cache)); mesh_render_data_free(mrdata); @@ -979,50 +1045,29 @@ Batch *BKE_mesh_batch_cache_get_triangles_with_normals(Mesh *me) MeshBatchCache *cache = mesh_batch_cache_get(me); if (cache->triangles_with_normals == NULL) { - unsigned int vidx = 0, nidx = 0; - - static VertexFormat format = { 0 }; - static unsigned int pos_id, nor_id; - if (format.attrib_ct == 0) { - /* initialize vertex format */ - pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); - nor_id = add_attrib(&format, "nor", GL_SHORT, 3, NORMALIZE_INT_TO_FLOAT); - } - MeshRenderData *mrdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY); - const int tottri = mesh_render_data_looptri_num_get(mrdata); - VertexBuffer *vbo = VertexBuffer_create_with_format(&format); - VertexBuffer_allocate_data(vbo, tottri * 3); + cache->triangles_with_normals = Batch_create(GL_TRIANGLES, mesh_batch_cache_get_pos_and_normals(mrdata, cache), NULL); - for (int i = 0; i < tottri; i++) { - float *tri_vert_cos[3]; - short *tri_nor, *tri_vert_nors[3]; + mesh_render_data_free(mrdata); + } - const bool is_smooth = mesh_render_data_looptri_cos_nors_smooth_get(mrdata, i, &tri_vert_cos, &tri_nor, &tri_vert_nors); + return cache->triangles_with_normals; +} - if (is_smooth) { - setAttrib(vbo, nor_id, nidx++, tri_vert_nors[0]); - setAttrib(vbo, nor_id, nidx++, tri_vert_nors[1]); - setAttrib(vbo, nor_id, nidx++, tri_vert_nors[2]); - } - else { - setAttrib(vbo, nor_id, nidx++, tri_nor); - setAttrib(vbo, nor_id, nidx++, tri_nor); - setAttrib(vbo, nor_id, nidx++, tri_nor); - } +Batch *BKE_mesh_batch_cache_get_points_with_normals(Mesh *me) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); - setAttrib(vbo, pos_id, vidx++, tri_vert_cos[0]); - setAttrib(vbo, pos_id, vidx++, tri_vert_cos[1]); - setAttrib(vbo, pos_id, vidx++, tri_vert_cos[2]); - } + if (cache->points_with_normals == NULL) { + MeshRenderData *mrdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY); - cache->triangles_with_normals = Batch_create(GL_TRIANGLES, vbo, NULL); + cache->points_with_normals = Batch_create(GL_POINTS, mesh_batch_cache_get_pos_and_normals(mrdata, cache), NULL); mesh_render_data_free(mrdata); } - return cache->triangles_with_normals; + return cache->points_with_normals; } Batch *BKE_mesh_batch_cache_get_all_verts(Mesh *me) @@ -1033,8 +1078,7 @@ Batch *BKE_mesh_batch_cache_get_all_verts(Mesh *me) /* create batch from DM */ MeshRenderData *mrdata = mesh_render_data_create(me, MR_DATATYPE_VERT); - cache->all_verts = Batch_create(GL_POINTS, mesh_batch_cache_get_pos_in_order(mrdata, cache), NULL); - Batch_set_builtin_program(cache->all_verts, GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR); + cache->all_verts = Batch_create(GL_POINTS, mesh_batch_cache_get_pos_and_nor_in_order(mrdata, cache), NULL); mesh_render_data_free(mrdata); } diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index c04063d22f8..0b7060fc55e 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -91,6 +91,8 @@ data_to_c_simple(modes/shaders/edit_overlay_mix_frag.glsl SRC) data_to_c_simple(modes/shaders/edit_overlay_mix_vert.glsl SRC) data_to_c_simple(modes/shaders/edit_overlay_facefill_vert.glsl SRC) data_to_c_simple(modes/shaders/edit_overlay_facefill_frag.glsl SRC) +data_to_c_simple(modes/shaders/edit_normals_vert.glsl SRC) +data_to_c_simple(modes/shaders/edit_normals_geom.glsl SRC) list(APPEND INC ) diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index 7514a0c806a..2b5f2d2ab2b 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -1291,6 +1291,30 @@ Batch *DRW_cache_surface_get(Object *ob) return surface; } +Batch *DRW_cache_surface_verts_get(Object *ob) +{ + Batch *surface = NULL; + + BLI_assert(ob->type == OB_MESH); + + Mesh *me = ob->data; + surface = BKE_mesh_batch_cache_get_points_with_normals(me); + + return surface; +} + +Batch *DRW_cache_verts_get(Object *ob) +{ + Batch *surface = NULL; + + BLI_assert(ob->type == OB_MESH); + + Mesh *me = ob->data; + surface = BKE_mesh_batch_cache_get_all_verts(me); + + return surface; +} + #if 0 /* TODO */ struct Batch *DRW_cache_surface_material_get(Object *ob, int nr) { /* TODO */ diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index 66aa5400df5..0af7f3d08b1 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -76,5 +76,7 @@ void DRW_cache_wire_overlay_get( struct Batch *DRW_cache_face_centers_get(struct Object *ob); struct Batch *DRW_cache_wire_outline_get(struct Object *ob); struct Batch *DRW_cache_surface_get(struct Object *ob); +struct Batch *DRW_cache_surface_verts_get(struct Object *ob); +struct Batch *DRW_cache_verts_get(struct Object *ob); #endif /* __DRAW_CACHE_H__ */
\ No newline at end of file diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 54e5fa5440c..32f3bdffc4d 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -63,7 +63,6 @@ extern char datatoc_gpu_shader_2D_vert_glsl[]; extern char datatoc_gpu_shader_3D_vert_glsl[]; -extern char datatoc_gpu_shader_basic_vert_glsl[]; /* Structures */ typedef enum { diff --git a/source/blender/draw/modes/edit_mesh_mode.c b/source/blender/draw/modes/edit_mesh_mode.c index e671e9f059b..1d5b064ebbd 100644 --- a/source/blender/draw/modes/edit_mesh_mode.c +++ b/source/blender/draw/modes/edit_mesh_mode.c @@ -35,11 +35,12 @@ /* keep it under MAX_PASSES */ typedef struct EDIT_MESH_PassList { - struct DRWPass *depth_pass_hidden_wire; - struct DRWPass *edit_face_overlay_pass; - struct DRWPass *edit_face_occluded_pass; - struct DRWPass *mix_occlude_pass; - struct DRWPass *facefill_occlude_pass; + struct DRWPass *depth_hidden_wire; + struct DRWPass *edit_face_overlay; + struct DRWPass *edit_face_occluded; + struct DRWPass *mix_occlude; + struct DRWPass *facefill_occlude; + struct DRWPass *normals; } EDIT_MESH_PassList; /* keep it under MAX_BUFFERS */ @@ -63,6 +64,10 @@ typedef struct EDIT_MESH_Data { static DRWShadingGroup *depth_shgrp_hidden_wire; +static DRWShadingGroup *fnormals_shgrp; +static DRWShadingGroup *vnormals_shgrp; +static DRWShadingGroup *lnormals_shgrp; + static DRWShadingGroup *face_overlay_shgrp; static DRWShadingGroup *ledges_overlay_shgrp; static DRWShadingGroup *lverts_overlay_shgrp; @@ -75,6 +80,7 @@ static DRWShadingGroup *facedot_occluded_shgrp; static DRWShadingGroup *facefill_occluded_shgrp; extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */ +extern struct GlobalsUboStorage ts; /* draw_common.c */ static struct GPUShader *overlay_tri_sh = NULL; static struct GPUShader *overlay_tri_fast_sh = NULL; @@ -86,6 +92,9 @@ static struct GPUShader *overlay_vert_sh = NULL; static struct GPUShader *overlay_facedot_sh = NULL; static struct GPUShader *overlay_mix_sh = NULL; static struct GPUShader *overlay_facefill_sh = NULL; +static struct GPUShader *normals_face_sh = NULL; +static struct GPUShader *normals_sh = NULL; +static struct GPUShader *depth_sh = NULL; extern char datatoc_edit_overlay_frag_glsl[]; extern char datatoc_edit_overlay_vert_glsl[]; @@ -98,6 +107,10 @@ extern char datatoc_edit_overlay_mix_vert_glsl[]; extern char datatoc_edit_overlay_mix_frag_glsl[]; extern char datatoc_edit_overlay_facefill_vert_glsl[]; extern char datatoc_edit_overlay_facefill_frag_glsl[]; +extern char datatoc_edit_normals_vert_glsl[]; +extern char datatoc_edit_normals_geom_glsl[]; + +extern char datatoc_gpu_shader_uniform_color_frag_glsl[]; static void EDIT_MESH_engine_init(void) { @@ -160,6 +173,17 @@ static void EDIT_MESH_engine_init(void) overlay_facefill_sh = DRW_shader_create(datatoc_edit_overlay_facefill_vert_glsl, NULL, datatoc_edit_overlay_facefill_frag_glsl, NULL); } + if (!normals_face_sh) { + normals_face_sh = DRW_shader_create(datatoc_edit_normals_vert_glsl, datatoc_edit_normals_geom_glsl, + datatoc_gpu_shader_uniform_color_frag_glsl, "#define FACE_NORMALS\n"); + } + if (!normals_sh) { + normals_sh = DRW_shader_create(datatoc_edit_normals_vert_glsl, datatoc_edit_normals_geom_glsl, + datatoc_gpu_shader_uniform_color_frag_glsl, NULL); + } + if (!depth_sh) { + depth_sh = DRW_shader_create_3D_depth_only(); + } } static DRWPass *edit_mesh_create_overlay_pass(DRWShadingGroup **face_shgrp, DRWShadingGroup **ledges_shgrp, @@ -170,9 +194,9 @@ static DRWPass *edit_mesh_create_overlay_pass(DRWShadingGroup **face_shgrp, DRWS const struct bContext *C = DRW_get_context(); RegionView3D *rv3d = CTX_wm_region_view3d(C); Scene *scene = CTX_data_scene(C); - ToolSettings *ts = scene->toolsettings; + ToolSettings *tsettings = scene->toolsettings; - if ((ts->selectmode & SCE_SELECT_VERTEX) != 0) { + if ((tsettings->selectmode & SCE_SELECT_VERTEX) != 0) { ledge_sh = overlay_edge_vcol_sh; if ((rv3d->rflag & RV3D_NAVIGATING) != 0) @@ -199,12 +223,12 @@ static DRWPass *edit_mesh_create_overlay_pass(DRWShadingGroup **face_shgrp, DRWS *ledges_shgrp = DRW_shgroup_create(ledge_sh, pass); DRW_shgroup_uniform_vec2(*ledges_shgrp, "viewportSize", DRW_viewport_size_get(), 1); - if ((ts->selectmode & (SCE_SELECT_VERTEX)) != 0) { + if ((tsettings->selectmode & (SCE_SELECT_VERTEX)) != 0) { *lverts_shgrp = DRW_shgroup_create(overlay_vert_sh, pass); DRW_shgroup_uniform_vec2(*lverts_shgrp, "viewportSize", DRW_viewport_size_get(), 1); } - if ((ts->selectmode & (SCE_SELECT_FACE)) != 0) { + if ((tsettings->selectmode & (SCE_SELECT_FACE)) != 0) { *facedot_shgrp = DRW_shgroup_create(overlay_facedot_sh, pass); } @@ -213,6 +237,7 @@ static DRWPass *edit_mesh_create_overlay_pass(DRWShadingGroup **face_shgrp, DRWS static float backwire_opacity; static float face_mod; +static float size_normal; static void EDIT_MESH_cache_init(void) { @@ -227,35 +252,51 @@ static void EDIT_MESH_cache_init(void) bool do_zbufclip = ((v3d->flag & V3D_ZBUF_SELECT) == 0); static float zero = 0.0f; - static struct GPUShader *depth_sh; + + { + /* Complementary Depth Pass */ + psl->depth_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_hidden_wire); + } - if (!depth_sh) - depth_sh = DRW_shader_create_3D_depth_only(); + { + /* Normals */ + psl->normals = DRW_pass_create("Edit Mesh Normals Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS); + + fnormals_shgrp = DRW_shgroup_create(normals_face_sh, psl->normals); + DRW_shgroup_uniform_float(fnormals_shgrp, "normalSize", &size_normal, 1); + DRW_shgroup_uniform_vec4(fnormals_shgrp, "color", ts.colorNormal, 1); - 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); + vnormals_shgrp = DRW_shgroup_create(normals_sh, psl->normals); + DRW_shgroup_uniform_float(vnormals_shgrp, "normalSize", &size_normal, 1); + DRW_shgroup_uniform_vec4(vnormals_shgrp, "color", ts.colorVNormal, 1); + + lnormals_shgrp = DRW_shgroup_create(normals_sh, psl->normals); + DRW_shgroup_uniform_float(lnormals_shgrp, "normalSize", &size_normal, 1); + DRW_shgroup_uniform_vec4(lnormals_shgrp, "color", ts.colorLNormal, 1); + } if (!do_zbufclip) { - psl->edit_face_overlay_pass = edit_mesh_create_overlay_pass(&face_overlay_shgrp, &ledges_overlay_shgrp, &lverts_overlay_shgrp, + psl->edit_face_overlay = edit_mesh_create_overlay_pass(&face_overlay_shgrp, &ledges_overlay_shgrp, &lverts_overlay_shgrp, &facedot_overlay_shgrp, &face_mod, DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_DEPTH | DRW_STATE_BLEND); } else { /* We render all wires with depth and opaque to a new fbo and blend the result based on depth values */ - psl->edit_face_occluded_pass = edit_mesh_create_overlay_pass(&face_occluded_shgrp, &ledges_occluded_shgrp, &lverts_occluded_shgrp, + psl->edit_face_occluded = edit_mesh_create_overlay_pass(&face_occluded_shgrp, &ledges_occluded_shgrp, &lverts_occluded_shgrp, &facedot_occluded_shgrp, &zero, DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_DEPTH); /* however we loose the front faces value (because we need the depth of occluded wires and * faces are alpha blended ) so we recover them in a new pass. */ - psl->facefill_occlude_pass = DRW_pass_create("Front Face Color", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND); - facefill_occluded_shgrp = DRW_shgroup_create(overlay_facefill_sh, psl->facefill_occlude_pass); + psl->facefill_occlude = DRW_pass_create("Front Face Color", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND); + facefill_occluded_shgrp = DRW_shgroup_create(overlay_facefill_sh, psl->facefill_occlude); DRW_shgroup_uniform_block(facefill_occluded_shgrp, "globalsBlock", globals_ubo, 0); /* we need a full screen pass to combine the result */ struct Batch *quad = DRW_cache_fullscreen_quad_get(); static float mat[4][4]; /* not even used but avoid crash */ - psl->mix_occlude_pass = DRW_pass_create("Mix Occluded Wires", DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND); - DRWShadingGroup *mix_shgrp = DRW_shgroup_create(overlay_mix_sh, psl->mix_occlude_pass); + psl->mix_occlude = DRW_pass_create("Mix Occluded Wires", DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND); + DRWShadingGroup *mix_shgrp = DRW_shgroup_create(overlay_mix_sh, psl->mix_occlude); DRW_shgroup_call_add(mix_shgrp, quad, mat); DRW_shgroup_uniform_float(mix_shgrp, "alpha", &backwire_opacity, 1); DRW_shgroup_uniform_buffer(mix_shgrp, "wireColor", &txl->occlude_wire_color_tx, 0); @@ -268,7 +309,7 @@ static void edit_mesh_add_ob_to_pass(Scene *scene, Object *ob, DRWShadingGroup * DRWShadingGroup *lverts_shgrp, DRWShadingGroup *facedot_shgrp, DRWShadingGroup *facefill_shgrp) { struct Batch *geo_ovl_tris, *geo_ovl_ledges, *geo_ovl_lverts, *geo_ovl_fcenter; - ToolSettings *ts = scene->toolsettings; + ToolSettings *tsettings = scene->toolsettings; DRW_cache_wire_overlay_get(ob, &geo_ovl_tris, &geo_ovl_ledges, &geo_ovl_lverts); DRW_shgroup_call_add(face_shgrp, geo_ovl_tris, ob->obmat); @@ -277,10 +318,10 @@ static void edit_mesh_add_ob_to_pass(Scene *scene, Object *ob, DRWShadingGroup * if (facefill_shgrp) DRW_shgroup_call_add(facefill_shgrp, geo_ovl_tris, ob->obmat); - if ((ts->selectmode & SCE_SELECT_VERTEX) != 0) + if ((tsettings->selectmode & SCE_SELECT_VERTEX) != 0) DRW_shgroup_call_add(lverts_shgrp, geo_ovl_lverts, ob->obmat); - if ((ts->selectmode & SCE_SELECT_FACE) != 0) { + if ((tsettings->selectmode & SCE_SELECT_FACE) != 0) { geo_ovl_fcenter = DRW_cache_face_centers_get(ob); DRW_shgroup_call_add(facedot_shgrp, geo_ovl_fcenter, ob->obmat); } @@ -298,7 +339,12 @@ static void EDIT_MESH_cache_populate(Object *ob) if (ob == obedit) { CollectionEngineSettings *ces_mode_ed = BKE_object_collection_engine_get(ob, COLLECTION_MODE_EDIT, ""); bool do_occlude_wire = BKE_collection_engine_property_value_get_bool(ces_mode_ed, "show_occlude_wire"); - backwire_opacity = BKE_collection_engine_property_value_get_float(ces_mode_ed, "backwire_opacity"); /* should be done only once */ + backwire_opacity = BKE_collection_engine_property_value_get_float(ces_mode_ed, "backwire_opacity"); /* Updating uniform */ + + bool fnormals_do = BKE_collection_engine_property_value_get_bool(ces_mode_ed, "face_normals_show"); + bool vnormals_do = BKE_collection_engine_property_value_get_bool(ces_mode_ed, "vert_normals_show"); + bool lnormals_do = BKE_collection_engine_property_value_get_bool(ces_mode_ed, "loop_normals_show"); + size_normal = BKE_collection_engine_property_value_get_float(ces_mode_ed, "normals_length"); /* Updating uniform */ face_mod = (do_occlude_wire) ? 0.0f : 1.0f; @@ -307,6 +353,21 @@ static void EDIT_MESH_cache_populate(Object *ob) DRW_shgroup_call_add(depth_shgrp_hidden_wire, geom, ob->obmat); } + if (fnormals_do) { + geom = DRW_cache_face_centers_get(ob); + DRW_shgroup_call_add(fnormals_shgrp, geom, ob->obmat); + } + + if (vnormals_do) { + geom = DRW_cache_verts_get(ob); + DRW_shgroup_call_add(vnormals_shgrp, geom, ob->obmat); + } + + if (lnormals_do) { + geom = DRW_cache_surface_verts_get(ob); + DRW_shgroup_call_add(lnormals_shgrp, geom, ob->obmat); + } + if ((v3d->flag & V3D_ZBUF_SELECT) == 0) { edit_mesh_add_ob_to_pass(scene, ob, face_occluded_shgrp, ledges_occluded_shgrp, lverts_occluded_shgrp, facedot_occluded_shgrp, facefill_occluded_shgrp); @@ -327,30 +388,32 @@ static void EDIT_MESH_draw_scene(void) DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - DRW_draw_pass(psl->depth_pass_hidden_wire); + DRW_draw_pass(psl->depth_hidden_wire); - if (psl->edit_face_occluded_pass) { + if (psl->edit_face_occluded) { float clearcol[4] = {0.0f, 0.0f, 0.0f, 0.0f}; /* render facefill */ - DRW_draw_pass(psl->facefill_occlude_pass); + DRW_draw_pass(psl->facefill_occlude); /* Render wires on a separate framebuffer */ DRW_framebuffer_bind(fbl->occlude_wire_fb); DRW_framebuffer_clear(true, true, clearcol, 1.0f); - DRW_draw_pass(psl->edit_face_occluded_pass); + DRW_draw_pass(psl->normals); + DRW_draw_pass(psl->edit_face_occluded); /* detach textures */ DRW_framebuffer_texture_detach(dtxl->depth); /* Combine with scene buffer */ DRW_framebuffer_bind(dfbl->default_fb); - DRW_draw_pass(psl->mix_occlude_pass); + DRW_draw_pass(psl->mix_occlude); /* reattach */ DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0); } else { - DRW_draw_pass(psl->edit_face_overlay_pass); + DRW_draw_pass(psl->normals); + DRW_draw_pass(psl->edit_face_overlay); } } @@ -358,6 +421,10 @@ void EDIT_MESH_collection_settings_create(CollectionEngineSettings *ces) { BLI_assert(ces); BKE_collection_engine_property_add_int(ces, "show_occlude_wire", false); + BKE_collection_engine_property_add_int(ces, "face_normals_show", false); + BKE_collection_engine_property_add_int(ces, "vert_normals_show", false); + BKE_collection_engine_property_add_int(ces, "loop_normals_show", false); + BKE_collection_engine_property_add_float(ces, "normals_length", 0.1); BKE_collection_engine_property_add_float(ces, "backwire_opacity", 0.5); } @@ -383,6 +450,10 @@ static void EDIT_MESH_engine_free(void) DRW_shader_free(overlay_mix_sh); if (overlay_facefill_sh) DRW_shader_free(overlay_facefill_sh); + if (normals_face_sh) + DRW_shader_free(normals_face_sh); + if (normals_sh) + DRW_shader_free(normals_sh); } DrawEngineType draw_engine_edit_mesh_type = { diff --git a/source/blender/draw/modes/shaders/edit_normals_face_vert.glsl b/source/blender/draw/modes/shaders/edit_normals_face_vert.glsl new file mode 100644 index 00000000000..9c70eabc056 --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_normals_face_vert.glsl @@ -0,0 +1,18 @@ + +uniform mat4 ModelViewProjectionMatrix; +uniform mat3 NormalMatrix; +uniform mat4 ProjectionMatrix; +uniform float normalSize; + +in vec3 pos; +in vec4 norAndFlag; + +flat out vec4 v1; +flat out vec4 v2; + +void main() +{ + v1 = ModelViewProjectionMatrix * vec4(pos, 1.0); + vec3 n = normalize(NormalMatrix * norAndFlag.xyz); /* viewspace */ + v2 = v1 + ProjectionMatrix * vec4(n * normalSize, 0.0); +} diff --git a/source/blender/draw/modes/shaders/edit_normals_geom.glsl b/source/blender/draw/modes/shaders/edit_normals_geom.glsl new file mode 100644 index 00000000000..d17823f2f5a --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_normals_geom.glsl @@ -0,0 +1,15 @@ + +layout(points) in; +layout(line_strip, max_vertices=2) out; + +flat in vec4 v1[1]; +flat in vec4 v2[1]; + +void main() +{ + gl_Position = v1[0]; + EmitVertex(); + gl_Position = v2[0]; + EmitVertex(); + EndPrimitive(); +} diff --git a/source/blender/draw/modes/shaders/edit_normals_vert.glsl b/source/blender/draw/modes/shaders/edit_normals_vert.glsl new file mode 100644 index 00000000000..3e00181c8dd --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_normals_vert.glsl @@ -0,0 +1,24 @@ + +uniform mat4 ModelViewProjectionMatrix; +uniform mat3 NormalMatrix; +uniform mat4 ProjectionMatrix; +uniform float normalSize; + +in vec3 pos; + +#ifdef FACE_NORMALS +in vec4 norAndFlag; +#define nor norAndFlag.xyz +#else +in vec3 nor; +#endif + +flat out vec4 v1; +flat out vec4 v2; + +void main() +{ + v1 = ModelViewProjectionMatrix * vec4(pos, 1.0); + vec3 n = normalize(NormalMatrix * nor); /* viewspace */ + v2 = v1 + ProjectionMatrix * vec4(n * normalSize, 0.0); +} diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 55b94c244bf..5e92965f449 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -2503,6 +2503,10 @@ RNA_LAYER_MODE_OBJECT_GET_SET_BOOL(show_backface_culling) /* mesh engine */ RNA_LAYER_MODE_EDIT_GET_SET_BOOL(show_occlude_wire) +RNA_LAYER_MODE_EDIT_GET_SET_BOOL(face_normals_show) +RNA_LAYER_MODE_EDIT_GET_SET_BOOL(vert_normals_show) +RNA_LAYER_MODE_EDIT_GET_SET_BOOL(loop_normals_show) +RNA_LAYER_MODE_EDIT_GET_SET_FLOAT(normals_length) RNA_LAYER_MODE_EDIT_GET_SET_FLOAT(backwire_opacity) #undef RNA_LAYER_ENGINE_GET_SET @@ -6105,6 +6109,36 @@ static void rna_def_layer_collection_mode_settings_edit(BlenderRNA *brna) RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update"); RNA_LAYER_MODE_EDIT_USE(show_occlude_wire) + prop = RNA_def_property(srna, "face_normals_show", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_ui_text(prop, "Draw Normals", "Display face normals as lines"); + RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_EditMode_face_normals_show_get", "rna_LayerEngineSettings_EditMode_face_normals_show_set"); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update"); + RNA_LAYER_MODE_EDIT_USE(face_normals_show) + + prop = RNA_def_property(srna, "vert_normals_show", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_ui_text(prop, "Draw Vertex Normals", "Display vertex normals as lines"); + RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_EditMode_vert_normals_show_get", "rna_LayerEngineSettings_EditMode_vert_normals_show_set"); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update"); + RNA_LAYER_MODE_EDIT_USE(vert_normals_show) + + prop = RNA_def_property(srna, "loop_normals_show", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_ui_text(prop, "Draw Split Normals", "Display vertex-per-face normals as lines"); + RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_EditMode_loop_normals_show_get", "rna_LayerEngineSettings_EditMode_loop_normals_show_set"); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update"); + RNA_LAYER_MODE_EDIT_USE(loop_normals_show) + + prop = RNA_def_property(srna, "normals_length", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_ui_text(prop, "Normal Size", "Display size for normals in the 3D view"); + RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_EditMode_normals_length_get", "rna_LayerEngineSettings_EditMode_normals_length_set", NULL); + RNA_def_property_range(prop, 0.00001, 1000.0); + RNA_def_property_ui_range(prop, 0.01, 10.0, 10.0, 2); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update"); + RNA_LAYER_MODE_EDIT_USE(normals_length) + prop = RNA_def_property(srna, "backwire_opacity", PROP_FLOAT, PROP_FACTOR); RNA_def_property_ui_text(prop, "Backwire Opacity", "Opacity when rendering transparent wires"); RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_EditMode_backwire_opacity_get", "rna_LayerEngineSettings_EditMode_backwire_opacity_set", NULL); |