diff options
14 files changed, 421 insertions, 56 deletions
diff --git a/release/scripts/startup/bl_ui/properties_collection.py b/release/scripts/startup/bl_ui/properties_collection.py index 1e7bf9416a7..6debbaf3aac 100644 --- a/release/scripts/startup/bl_ui/properties_collection.py +++ b/release/scripts/startup/bl_ui/properties_collection.py @@ -127,6 +127,7 @@ 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") if __name__ == "__main__": # only for live edit. diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index ea1d179aa40..cb2681fcf81 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -89,6 +89,10 @@ data_to_c_simple(modes/shaders/edit_overlay_geom_edge.glsl SRC) data_to_c_simple(modes/shaders/edit_overlay_loosevert_vert.glsl SRC) data_to_c_simple(modes/shaders/edit_overlay_facedot_frag.glsl SRC) data_to_c_simple(modes/shaders/edit_overlay_facedot_vert.glsl SRC) +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) list(APPEND INC ) diff --git a/source/blender/draw/engines/clay/clay.c b/source/blender/draw/engines/clay/clay.c index 7a5beb46482..7f55ee03a3b 100644 --- a/source/blender/draw/engines/clay/clay.c +++ b/source/blender/draw/engines/clay/clay.c @@ -689,6 +689,7 @@ static void CLAY_view_draw(RenderEngine *UNUSED(engine), const bContext *context CLAY_FramebufferList *fbl = DRW_engine_framebuffer_list_get(); CLAY_engine_init(); + DRW_mode_init(); /* TODO : tag to refresh by the deps graph */ /* ideally only refresh when objects are added/removed */ diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index a9d831440dc..4c5442cc211 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -131,6 +131,7 @@ typedef struct DRWFboTexture { void DRW_framebuffer_init(struct GPUFrameBuffer **fb, int width, int height, DRWFboTexture textures[MAX_FBO_TEX], int texnbr); void DRW_framebuffer_bind(struct GPUFrameBuffer *fb); +void DRW_framebuffer_clear(bool color, bool depth, float clear_col[4]); void DRW_framebuffer_texture_attach(struct GPUFrameBuffer *fb, struct GPUTexture *tex, int slot); void DRW_framebuffer_texture_detach(struct GPUTexture *tex); void DRW_framebuffer_blit(struct GPUFrameBuffer *fb_read, struct GPUFrameBuffer *fb_write, bool depth); @@ -144,19 +145,20 @@ void DRW_shader_free(struct GPUShader *shader); /* Batches */ typedef enum { - DRW_STATE_WRITE_DEPTH = (1 << 0), - DRW_STATE_WRITE_COLOR = (1 << 1), - DRW_STATE_DEPTH_LESS = (1 << 2), - DRW_STATE_DEPTH_EQUAL = (1 << 3), - DRW_STATE_CULL_BACK = (1 << 4), - DRW_STATE_CULL_FRONT = (1 << 5), - DRW_STATE_WIRE = (1 << 6), - DRW_STATE_WIRE_LARGE = (1 << 7), - DRW_STATE_POINT = (1 << 8), - DRW_STATE_STIPPLE_2 = (1 << 9), - DRW_STATE_STIPPLE_3 = (1 << 10), - DRW_STATE_STIPPLE_4 = (1 << 11), - DRW_STATE_BLEND = (1 << 12), + DRW_STATE_WRITE_DEPTH = (1 << 0), + DRW_STATE_WRITE_COLOR = (1 << 1), + DRW_STATE_DEPTH_LESS = (1 << 2), + DRW_STATE_DEPTH_EQUAL = (1 << 3), + DRW_STATE_DEPTH_GREATER = (1 << 4), + DRW_STATE_CULL_BACK = (1 << 5), + DRW_STATE_CULL_FRONT = (1 << 6), + DRW_STATE_WIRE = (1 << 7), + DRW_STATE_WIRE_LARGE = (1 << 8), + DRW_STATE_POINT = (1 << 9), + DRW_STATE_STIPPLE_2 = (1 << 10), + DRW_STATE_STIPPLE_3 = (1 << 11), + DRW_STATE_STIPPLE_4 = (1 << 12), + DRW_STATE_BLEND = (1 << 13), } DRWState; DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass); @@ -210,6 +212,7 @@ void *DRW_render_settings_get(Scene *scene, const char *engine_name); #endif /* __DRW_ENGINE_H__ */ /* Cache */ +void DRW_mode_init(void); void DRW_mode_cache_init(void); void DRW_mode_cache_populate(struct Object *ob); void DRW_mode_cache_finish(void); diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 1ffff40fb58..ea14c59bc7f 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -942,8 +942,7 @@ static void set_state(short flag) } /* Depht Test */ - if (flag & DRW_STATE_DEPTH_LESS || - flag & DRW_STATE_DEPTH_EQUAL) + if (flag & (DRW_STATE_DEPTH_LESS | DRW_STATE_DEPTH_EQUAL | DRW_STATE_DEPTH_GREATER)) { glEnable(GL_DEPTH_TEST); @@ -952,6 +951,8 @@ static void set_state(short flag) glDepthFunc(GL_LEQUAL); else if (flag & DRW_STATE_DEPTH_EQUAL) glDepthFunc(GL_EQUAL); + else if (flag & DRW_STATE_DEPTH_GREATER) + glDepthFunc(GL_GREATER); } else { glDisable(GL_DEPTH_TEST); @@ -977,6 +978,7 @@ static void set_state(short flag) /* Blending (all buffer) */ if (flag & DRW_STATE_BLEND) { glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } else { glDisable(GL_BLEND); @@ -1063,6 +1065,23 @@ void DRW_draw_pass(DRWPass *UNUSED(pass)) #endif /* ******************************************* Mode Engine Cache ****************************************** */ + +void DRW_mode_init(void) +{ + const bContext *C = DRW_get_context(); + int mode = CTX_data_mode_enum(C); + + switch (mode) { + case CTX_MODE_EDIT_MESH: + EDIT_MESH_init(); + break; + case CTX_MODE_EDIT_ARMATURE: + break; + case CTX_MODE_OBJECT: + break; + } +} + void DRW_mode_cache_init(void) { const bContext *C = DRW_get_context(); @@ -1188,6 +1207,8 @@ void *DRW_render_settings_get(Scene *scene, const char *engine_name) void DRW_framebuffer_init(struct GPUFrameBuffer **fb, int width, int height, DRWFboTexture textures[MAX_FBO_TEX], int texnbr) { + BLI_assert(texnbr <= MAX_FBO_TEX); + if (!*fb) { int color_attachment = -1; *fb = GPU_framebuffer_create(); @@ -1226,6 +1247,19 @@ void DRW_framebuffer_bind(struct GPUFrameBuffer *fb) GPU_framebuffer_bind(fb); } +void DRW_framebuffer_clear(bool color, bool depth, float clear_col[4]) +{ + if (color) { + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glClearColor(clear_col[0], clear_col[1], clear_col[2], clear_col[4]); + } + if (depth) { + glDepthMask(GL_TRUE); + } + glClear(((color) ? GL_COLOR_BUFFER_BIT : 0) | + ((depth) ? GL_DEPTH_BUFFER_BIT : 0)); +} + void DRW_framebuffer_texture_attach(struct GPUFrameBuffer *fb, GPUTexture *tex, int slot) { GPU_framebuffer_texture_attach(fb, tex, slot); diff --git a/source/blender/draw/modes/edit_mesh_mode.c b/source/blender/draw/modes/edit_mesh_mode.c index 4177e7b843f..c9a998df9a2 100644 --- a/source/blender/draw/modes/edit_mesh_mode.c +++ b/source/blender/draw/modes/edit_mesh_mode.c @@ -27,6 +27,7 @@ #include "DRW_render.h" #include "GPU_shader.h" +#include "GPU_viewport.h" #include "DNA_view3d_types.h" #include "draw_mode_pass.h" @@ -40,14 +41,37 @@ typedef struct EDIT_MESH_PassList { struct DRWPass *wire_outline_pass; 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; } EDIT_MESH_PassList; +/* keep it under MAX_BUFFERS */ +typedef struct EDIT_MESH_FramebufferList { + struct GPUFrameBuffer *occlude_wire_fb; + struct GPUFrameBuffer *occlude_face_fb; +} EDIT_MESH_FramebufferList; + +/* keep it under MAX_TEXTURES */ +typedef struct EDIT_MESH_TextureList { + struct GPUTexture *occlude_wire_depth_tx; + struct GPUTexture *occlude_wire_color_tx; + struct GPUTexture *occlude_face_color_tx; +} EDIT_MESH_TextureList; + static DRWShadingGroup *depth_shgrp_hidden_wire; + static DRWShadingGroup *face_overlay_shgrp; static DRWShadingGroup *ledges_overlay_shgrp; static DRWShadingGroup *lverts_overlay_shgrp; static DRWShadingGroup *facedot_overlay_shgrp; +static DRWShadingGroup *face_occluded_shgrp; +static DRWShadingGroup *ledges_occluded_shgrp; +static DRWShadingGroup *lverts_occluded_shgrp; +static DRWShadingGroup *facedot_occluded_shgrp; +static DRWShadingGroup *facefill_occluded_shgrp; + extern struct GPUUniformBuffer *globals_ubo; /* draw_mode_pass.c */ static struct GPUShader *overlay_tri_sh = NULL; @@ -58,6 +82,8 @@ static struct GPUShader *overlay_edge_sh = NULL; static struct GPUShader *overlay_edge_vcol_sh = NULL; 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; extern char datatoc_edit_overlay_frag_glsl[]; extern char datatoc_edit_overlay_vert_glsl[]; @@ -66,19 +92,28 @@ extern char datatoc_edit_overlay_geom_edge_glsl[]; extern char datatoc_edit_overlay_loosevert_vert_glsl[]; extern char datatoc_edit_overlay_facedot_frag_glsl[]; extern char datatoc_edit_overlay_facedot_vert_glsl[]; +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[]; -void EDIT_MESH_cache_init(void) +void EDIT_MESH_init(void) { - EDIT_MESH_PassList *psl = DRW_mode_pass_list_get(); - static struct GPUShader *depth_sh, *tri_sh, *ledge_sh; + EDIT_MESH_TextureList *txl = DRW_mode_texture_list_get(); + EDIT_MESH_FramebufferList *fbl = DRW_mode_framebuffer_list_get(); - const struct bContext *C = DRW_get_context(); - struct RegionView3D *rv3d = CTX_wm_region_view3d(C); - Scene *scene = CTX_data_scene(C); - ToolSettings *ts = scene->toolsettings; + float *viewport_size = DRW_viewport_size_get(); - if (!depth_sh) - depth_sh = DRW_shader_create_3D_depth_only(); + DRWFboTexture tex[2] = {{&txl->occlude_wire_depth_tx, DRW_BUF_DEPTH_24}, + {&txl->occlude_wire_color_tx, DRW_BUF_RGBA_8}}; + DRW_framebuffer_init(&fbl->occlude_wire_fb, + (int)viewport_size[0], (int)viewport_size[1], + tex, 2); + + DRWFboTexture tex2 = {&txl->occlude_face_color_tx, DRW_BUF_RGBA_8}; + DRW_framebuffer_init(&fbl->occlude_face_fb, + (int)viewport_size[0], (int)viewport_size[1], + &tex2, 1); if (!overlay_tri_sh) { overlay_tri_sh = DRW_shader_create(datatoc_edit_overlay_vert_glsl, @@ -119,6 +154,25 @@ void EDIT_MESH_cache_init(void) overlay_facedot_sh = DRW_shader_create(datatoc_edit_overlay_facedot_vert_glsl, NULL, datatoc_edit_overlay_facedot_frag_glsl, NULL); } + if (!overlay_mix_sh) { + overlay_mix_sh = DRW_shader_create(datatoc_edit_overlay_mix_vert_glsl, NULL, + datatoc_edit_overlay_mix_frag_glsl, NULL); + } + if (!overlay_facefill_sh) { + overlay_facefill_sh = DRW_shader_create(datatoc_edit_overlay_facefill_vert_glsl, NULL, + datatoc_edit_overlay_facefill_frag_glsl, NULL); + } +} + +static DRWPass *edit_mesh_create_overlay_pass(DRWShadingGroup **face_shgrp, DRWShadingGroup **ledges_shgrp, + DRWShadingGroup **lverts_shgrp, DRWShadingGroup **facedot_shgrp, + float *faceAlpha, DRWState statemod) +{ + static struct GPUShader *tri_sh, *ledge_sh; + const struct bContext *C = DRW_get_context(); + RegionView3D *rv3d = CTX_wm_region_view3d(C); + Scene *scene = CTX_data_scene(C); + ToolSettings *ts = scene->toolsettings; if ((ts->selectmode & SCE_SELECT_VERTEX) != 0) { ledge_sh = overlay_edge_vcol_sh; @@ -137,25 +191,78 @@ void EDIT_MESH_cache_init(void) tri_sh = overlay_tri_sh; } - 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_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND | DRW_STATE_POINT); + DRWPass *pass = DRW_pass_create("Edit Mesh Face Overlay Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_POINT | statemod); - face_overlay_shgrp = DRW_shgroup_create(tri_sh, psl->edit_face_overlay_pass); - DRW_shgroup_uniform_block(face_overlay_shgrp, "globalsBlock", globals_ubo, 0); - DRW_shgroup_uniform_vec2(face_overlay_shgrp, "viewportSize", DRW_viewport_size_get(), 1); + *face_shgrp = DRW_shgroup_create(tri_sh, pass); + DRW_shgroup_uniform_block(*face_shgrp, "globalsBlock", globals_ubo, 0); + DRW_shgroup_uniform_vec2(*face_shgrp, "viewportSize", DRW_viewport_size_get(), 1); + DRW_shgroup_uniform_float(*face_shgrp, "faceAlphaMod", faceAlpha, 1); - ledges_overlay_shgrp = DRW_shgroup_create(ledge_sh, psl->edit_face_overlay_pass); - DRW_shgroup_uniform_vec2(ledges_overlay_shgrp, "viewportSize", DRW_viewport_size_get(), 1); + *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) { - lverts_overlay_shgrp = DRW_shgroup_create(overlay_vert_sh, psl->edit_face_overlay_pass); - DRW_shgroup_uniform_vec2(lverts_overlay_shgrp, "viewportSize", DRW_viewport_size_get(), 1); + *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) { - facedot_overlay_shgrp = DRW_shgroup_create(overlay_facedot_sh, psl->edit_face_overlay_pass); + *facedot_shgrp = DRW_shgroup_create(overlay_facedot_sh, pass); + } + + return pass; +} + +static float backwire_opacity; +static float face_mod; + +void EDIT_MESH_cache_init(void) +{ + EDIT_MESH_PassList *psl = DRW_mode_pass_list_get(); + const struct bContext *C = DRW_get_context(); + View3D *v3d = CTX_wm_view3d(C); + + bool do_zbufclip = ((v3d->flag & V3D_ZBUF_SELECT) == 0); + + static float zero = 0.0f; + static struct GPUShader *depth_sh; + + if (!depth_sh) + depth_sh = DRW_shader_create_3D_depth_only(); + + 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); + + if (!do_zbufclip) { + psl->edit_face_overlay_pass = 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, + &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); + facefill_occluded_shgrp = DRW_shgroup_create(overlay_facefill_sh, psl->facefill_occlude_pass); + DRW_shgroup_uniform_block(facefill_occluded_shgrp, "globalsBlock", globals_ubo, 0); + + /* we need a full screen pass to combine the result */ + EDIT_MESH_TextureList *txl = DRW_mode_texture_list_get(); + DefaultTextureList *dtxl = DRW_engine_texture_list_get(); + 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); + 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); + DRW_shgroup_uniform_buffer(mix_shgrp, "faceColor", &txl->occlude_face_color_tx, 1); + DRW_shgroup_uniform_buffer(mix_shgrp, "wireDepth", &txl->occlude_wire_depth_tx, 2); + DRW_shgroup_uniform_buffer(mix_shgrp, "sceneDepth", &dtxl->depth, 3); } DRW_mode_passes_setup(NULL, @@ -167,37 +274,58 @@ void EDIT_MESH_cache_init(void) NULL); } -void EDIT_MESH_cache_populate(Object *ob) +static void edit_mesh_add_ob_to_pass(Scene *scene, Object *ob, DRWShadingGroup *face_shgrp, DRWShadingGroup *ledges_shgrp, + DRWShadingGroup *lverts_shgrp, DRWShadingGroup *facedot_shgrp, DRWShadingGroup *facefill_shgrp) { - struct Batch *geom; struct Batch *geo_ovl_tris, *geo_ovl_ledges, *geo_ovl_lverts, *geo_ovl_fcenter; + ToolSettings *ts = 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); + DRW_shgroup_call_add(ledges_shgrp, geo_ovl_ledges, ob->obmat); + + if (facefill_shgrp) + DRW_shgroup_call_add(facefill_shgrp, geo_ovl_tris, ob->obmat); + + if ((ts->selectmode & SCE_SELECT_VERTEX) != 0) + DRW_shgroup_call_add(lverts_shgrp, geo_ovl_lverts, ob->obmat); + + if ((ts->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); + } +} + +void EDIT_MESH_cache_populate(Object *ob) +{ const struct bContext *C = DRW_get_context(); + View3D *v3d = CTX_wm_view3d(C); Scene *scene = CTX_data_scene(C); Object *obedit = scene->obedit; - ToolSettings *ts = scene->toolsettings; + struct Batch *geom; 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 */ + + face_mod = (do_occlude_wire) ? 0.0f : 1.0f; switch (ob->type) { case OB_MESH: - if (ob == obedit) { - 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); - - if ((ts->selectmode & SCE_SELECT_VERTEX) != 0) - DRW_shgroup_call_add(lverts_overlay_shgrp, geo_ovl_lverts, ob->obmat); - - if ((ts->selectmode & SCE_SELECT_FACE) != 0) { - geo_ovl_fcenter = DRW_cache_face_centers_get(ob); - DRW_shgroup_call_add(facedot_overlay_shgrp, geo_ovl_fcenter, ob->obmat); - } - + if (ob == obedit) { if (do_occlude_wire) { geom = DRW_cache_surface_get(ob); DRW_shgroup_call_add(depth_shgrp_hidden_wire, 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); + } + else { + edit_mesh_add_ob_to_pass(scene, ob, face_overlay_shgrp, ledges_overlay_shgrp, + lverts_overlay_shgrp, facedot_overlay_shgrp, NULL); + } } break; case OB_LAMP: @@ -229,9 +357,36 @@ void EDIT_MESH_cache_finish(void) void EDIT_MESH_draw(void) { EDIT_MESH_PassList *psl = DRW_mode_pass_list_get(); + EDIT_MESH_FramebufferList *fbl = DRW_mode_framebuffer_list_get(); + DefaultFramebufferList *dfbl = DRW_engine_framebuffer_list_get(); + DefaultTextureList *dtxl = DRW_engine_texture_list_get(); DRW_draw_pass(psl->depth_pass_hidden_wire); - DRW_draw_pass(psl->edit_face_overlay_pass); + + if (psl->edit_face_occluded_pass) { + float clearcol[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + /* render facefill */ + DRW_framebuffer_texture_detach(dtxl->depth); + DRW_framebuffer_texture_attach(fbl->occlude_face_fb, dtxl->depth, 0); + DRW_framebuffer_bind(fbl->occlude_face_fb); + DRW_framebuffer_clear(true, false, clearcol); + DRW_draw_pass(psl->facefill_occlude_pass); + DRW_framebuffer_texture_detach(dtxl->depth); + + /* Render wires on a separate framebuffer */ + DRW_framebuffer_bind(fbl->occlude_wire_fb); + DRW_framebuffer_clear(true, true, clearcol); + DRW_draw_pass(psl->edit_face_occluded_pass); + + /* Combine with scene buffer */ + DRW_framebuffer_bind(dfbl->default_fb); + DRW_draw_pass(psl->mix_occlude_pass); + DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0); + } + else { + DRW_draw_pass(psl->edit_face_overlay_pass); + } + DRW_draw_pass(psl->wire_outline_pass); DRW_draw_pass(psl->non_meshes_pass); DRW_draw_pass(psl->ob_center_pass); @@ -241,6 +396,7 @@ 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_float(ces, "backwire_opacity", 0.5); } void EDIT_MESH_engine_free(void) @@ -261,4 +417,8 @@ void EDIT_MESH_engine_free(void) DRW_shader_free(overlay_vert_sh); if (overlay_facedot_sh) DRW_shader_free(overlay_facedot_sh); + if (overlay_mix_sh) + DRW_shader_free(overlay_mix_sh); + if (overlay_facefill_sh) + DRW_shader_free(overlay_facefill_sh); }
\ No newline at end of file diff --git a/source/blender/draw/modes/edit_mesh_mode.h b/source/blender/draw/modes/edit_mesh_mode.h index 9eee473917b..508685bd033 100644 --- a/source/blender/draw/modes/edit_mesh_mode.h +++ b/source/blender/draw/modes/edit_mesh_mode.h @@ -28,6 +28,8 @@ struct Object; +void EDIT_MESH_init(void); + void EDIT_MESH_cache_init(void); void EDIT_MESH_cache_populate(struct Object *ob); void EDIT_MESH_cache_finish(void); diff --git a/source/blender/draw/modes/shaders/edit_overlay_facedot_frag.glsl b/source/blender/draw/modes/shaders/edit_overlay_facedot_frag.glsl index 9b99247efec..0bcc8aafc1f 100644 --- a/source/blender/draw/modes/shaders/edit_overlay_facedot_frag.glsl +++ b/source/blender/draw/modes/shaders/edit_overlay_facedot_frag.glsl @@ -49,7 +49,7 @@ out vec4 FragColor; void main() { if (isSelected != 0) - FragColor = vec4(colorFaceDot.rgb, 1.0); + FragColor = colorFaceDot; else - FragColor = vec4(colorWireEdit.rgb, 1.0); + FragColor = colorWireEdit; } diff --git a/source/blender/draw/modes/shaders/edit_overlay_facefill_frag.glsl b/source/blender/draw/modes/shaders/edit_overlay_facefill_frag.glsl new file mode 100644 index 00000000000..fa0197573ff --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_overlay_facefill_frag.glsl @@ -0,0 +1,27 @@ + +/* 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 */ + +flat in vec4 faceColor; +flat in int faceActive; + +out vec4 FragColor; + +const mat4 stipple_matrix = mat4(vec4(1.0, 0.0, 0.0, 0.0), + vec4(0.0, 0.0, 0.0, 0.0), + vec4(0.0, 0.0, 1.0, 0.0), + vec4(0.0, 0.0, 0.0, 0.0)); + +void main() +{ + FragColor = faceColor; + + if (faceActive == 1) { + int x = int(gl_FragCoord.x) & 0x3; /* mod 4 */ + int y = int(gl_FragCoord.y) & 0x3; /* mod 4 */ + FragColor *= stipple_matrix[x][y]; + } +} diff --git a/source/blender/draw/modes/shaders/edit_overlay_facefill_vert.glsl b/source/blender/draw/modes/shaders/edit_overlay_facefill_vert.glsl new file mode 100644 index 00000000000..be4cd4568cd --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_overlay_facefill_vert.glsl @@ -0,0 +1,72 @@ + +uniform mat4 ModelViewProjectionMatrix; + +/* keep in sync with GlobalsUboStorage */ +layout(std140) uniform globalsBlock { + vec4 colorWire; + vec4 colorWireEdit; + vec4 colorActive; + vec4 colorSelect; + vec4 colorTransform; + vec4 colorGroupActive; + vec4 colorGroup; + vec4 colorLamp; + vec4 colorSpeaker; + vec4 colorCamera; + vec4 colorEmpty; + vec4 colorVertex; + vec4 colorVertexSelect; + vec4 colorEditMeshActive; + vec4 colorEdgeSelect; + vec4 colorEdgeSeam; + vec4 colorEdgeSharp; + vec4 colorEdgeCrease; + vec4 colorEdgeBWeight; + vec4 colorEdgeFaceSelect; + vec4 colorFace; + vec4 colorFaceSelect; + vec4 colorNormal; + vec4 colorVNormal; + vec4 colorLNormal; + vec4 colorFaceDot; + + vec4 colorDeselect; + vec4 colorOutline; + vec4 colorLampNoAlpha; + + float sizeLampCenter; + float sizeLampCircle; + float sizeLampCircleShadow; + float sizeVertex; + float sizeEdge; + float sizeEdgeFix; + float sizeNormal; + float sizeFaceDot; +}; + +in vec3 pos; +in ivec4 data; + +flat out vec4 faceColor; +flat out int faceActive; + +#define FACE_ACTIVE (1 << 2) +#define FACE_SELECTED (1 << 3) + +void main() +{ + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + + if ((data.x & FACE_ACTIVE) != 0) { + faceColor = colorEditMeshActive; + faceActive = 1; + } + else if ((data.x & FACE_SELECTED) != 0) { + faceColor = colorFaceSelect; + faceActive = 0; + } + else { + faceColor = colorFace; + faceActive = 0; + } +} diff --git a/source/blender/draw/modes/shaders/edit_overlay_frag.glsl b/source/blender/draw/modes/shaders/edit_overlay_frag.glsl index a3deaa237ee..43b3e412b9d 100644 --- a/source/blender/draw/modes/shaders/edit_overlay_frag.glsl +++ b/source/blender/draw/modes/shaders/edit_overlay_frag.glsl @@ -48,6 +48,8 @@ layout(std140) uniform globalsBlock { float sizeFaceDot; }; +uniform float faceAlphaMod; + flat in vec3 edgesCrease; flat in vec3 edgesBweight; flat in ivec3 flag; @@ -175,6 +177,9 @@ void main() int y = int(gl_FragCoord.y) & 0x3; /* mod 4 */ FragColor *= stipple_matrix[x][y]; } + else { + FragColor.a *= faceAlphaMod; + } /* Edges */ for (int v = 0; v < 3; ++v) { diff --git a/source/blender/draw/modes/shaders/edit_overlay_mix_frag.glsl b/source/blender/draw/modes/shaders/edit_overlay_mix_frag.glsl new file mode 100644 index 00000000000..67687c7fc2f --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_overlay_mix_frag.glsl @@ -0,0 +1,40 @@ + +out vec4 FragColor; + +uniform sampler2D wireColor; +uniform sampler2D wireDepth; +uniform sampler2D faceColor; +uniform sampler2D sceneDepth; +uniform float alpha; + +vec4 linear(vec4 col) +{ + const float fac = 0.45454545; + return vec4(pow(col.r,fac), pow(col.g,fac), pow(col.b,fac), col.a); +} + +vec4 srgb(vec4 col) +{ + const float fac = 2.2; + return vec4(pow(col.r,fac), pow(col.g,fac), pow(col.b,fac), col.a); +} + +void main() +{ + ivec2 co = ivec2(gl_FragCoord.xy); + float wire_depth = texelFetch(wireDepth, co, 0).r; + float scene_depth = texelFetch(sceneDepth, co, 0).r; + vec4 wire_color = texelFetch(wireColor, co, 0).rgba; + vec4 face_color = texelFetch(faceColor, co, 0).rgba; + + /* this works because not rendered depth is 1.0 and the + * following test is always true even when no wires */ + if (wire_depth > scene_depth) { + wire_color.a *= alpha; + FragColor.rgb = mix(face_color.rgb, wire_color.rgb, wire_color.a); + FragColor.a = face_color.a + wire_color.a; + } + else { + FragColor = wire_color; + } +} diff --git a/source/blender/draw/modes/shaders/edit_overlay_mix_vert.glsl b/source/blender/draw/modes/shaders/edit_overlay_mix_vert.glsl new file mode 100644 index 00000000000..ef3d5d717bc --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_overlay_mix_vert.glsl @@ -0,0 +1,7 @@ + +in vec2 pos; + +void main() +{ + gl_Position = vec4(pos, 0.0, 1.0); +} diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index cefc4a59da7..75197b78e5c 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -2485,6 +2485,7 @@ 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_FLOAT(backwire_opacity) #undef RNA_LAYER_ENGINE_GET_SET #undef RNA_LAYER_ENGINE_USE_GET_SET @@ -6037,11 +6038,19 @@ static void rna_def_layer_collection_mode_settings_edit(BlenderRNA *brna) /* see RNA_LAYER_ENGINE_GET_SET macro */ prop = RNA_def_property(srna, "show_occlude_wire", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_ui_text(prop, "Hidden Wire", ""); + RNA_def_property_ui_text(prop, "Hidden Wire", "Use hidden wireframe display"); RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_EditMode_show_occlude_wire_get", "rna_LayerEngineSettings_EditMode_show_occlude_wire_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(show_occlude_wire) + + 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); + RNA_def_property_range(prop, 0.0f, 1.0f); + 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(backwire_opacity) } static void rna_def_layer_collection_mode_settings(BlenderRNA *brna) |