diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2019-12-02 03:40:58 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2019-12-02 15:15:52 +0300 |
commit | 9516921c05bd9fee5c94942eb8e38f47ba7e4351 (patch) | |
tree | da007fc17bc6a02f849dae2e8f76f5ab304fe4dc /source/blender/draw/engines/overlay/overlay_wireframe.c | |
parent | 1f6c3699a836d485ed37f443cd0fcd19e978dbb6 (diff) |
Overlay Engine: Refactor & Cleanup
This is the unification of all overlays into one overlay engine as described in T65347.
I went over all the code making it more future proof with less hacks and removing old / not relevent parts.
Goals / Acheivements:
- Remove internal shader usage (only drw shaders)
- Remove viewportSize and viewportSizeInv and put them in gloabl ubo
- Fixed some drawing issues: Missing probe option and Missing Alt+B clipping of some shader
- Remove old (legacy) shaders dependancy (not using view UBO).
- Less shader variation (less compilation time at first load and less patching needed for vulkan)
- removed some geom shaders when I could
- Remove static e_data (except shaders storage where it is OK)
- Clear the way to fix some anoying limitations (dithered transparency, background image compositing etc...)
- Wireframe drawing now uses the same batching capabilities as workbench & eevee (indirect drawing).
- Reduced complexity, removed ~3000 Lines of code in draw (also removed a lot of unused shader in GPU).
- Post AA to avoid complexity and cost of MSAA.
Remaining issues:
- ~~Armature edits, overlay toggles, (... others?) are not refreshing viewport after AA is complete~~
- FXAA is not the best for wires, maybe investigate SMAA
- Maybe do something more temporally stable for AA.
- ~~Paint overlays are not working with AA.~~
- ~~infront objects are difficult to select.~~
- ~~the infront wires sometimes goes through they solid counterpart (missing clear maybe?) (toggle overlays on-off when using infront+wireframe overlay in solid shading)~~
Note: I made some decision to change slightly the appearance of some objects to simplify their drawing. Namely the empty arrows end (which is now hollow/wire) and distance points of the cameras/spots being done by lines.
Reviewed By: jbakker
Differential Revision: https://developer.blender.org/D6296
Diffstat (limited to 'source/blender/draw/engines/overlay/overlay_wireframe.c')
-rw-r--r-- | source/blender/draw/engines/overlay/overlay_wireframe.c | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/source/blender/draw/engines/overlay/overlay_wireframe.c b/source/blender/draw/engines/overlay/overlay_wireframe.c new file mode 100644 index 00000000000..d86f524cb48 --- /dev/null +++ b/source/blender/draw/engines/overlay/overlay_wireframe.c @@ -0,0 +1,231 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2019, Blender Foundation. + */ + +/** \file + * \ingroup draw_engine + */ + +#include "DNA_mesh_types.h" +#include "DNA_view3d_types.h" + +#include "BKE_editmesh.h" +#include "BKE_global.h" +#include "BKE_object.h" +#include "BKE_paint.h" + +#include "BLI_hash.h" + +#include "GPU_shader.h" +#include "DRW_render.h" + +#include "ED_view3d.h" + +#include "overlay_private.h" + +void OVERLAY_wireframe_init(OVERLAY_Data *vedata) +{ + OVERLAY_PrivateData *pd = vedata->stl->pd; + const DRWContextState *draw_ctx = DRW_context_state_get(); + pd->view_wires = DRW_view_create_with_zoffset(pd->view_default, draw_ctx->rv3d, 0.5f); +} + +void OVERLAY_wireframe_cache_init(OVERLAY_Data *vedata) +{ + OVERLAY_PassList *psl = vedata->psl; + OVERLAY_PrivateData *pd = vedata->stl->pd; + const DRWContextState *draw_ctx = DRW_context_state_get(); + DRWShadingGroup *grp = NULL; + + View3DShading *shading = &draw_ctx->v3d->shading; + + pd->shdata.wire_step_param = pd->overlay.wireframe_threshold - 254.0f / 255.0f; + + bool is_wire_shmode = (shading->type == OB_WIRE); + bool is_material_shmode = (shading->type > OB_SOLID); + bool is_object_color = is_wire_shmode && (shading->wire_color_type == V3D_SHADING_OBJECT_COLOR); + bool is_random_color = is_wire_shmode && (shading->wire_color_type == V3D_SHADING_RANDOM_COLOR); + + const bool use_select = (DRW_state_is_select() || DRW_state_is_depth()); + GPUShader *wires_sh = use_select ? OVERLAY_shader_wireframe_select() : + OVERLAY_shader_wireframe(); + + for (int xray = 0; xray < 2; xray++) { + /* Only do stencil test if stencil buffer is written by the render engine. */ + DRWState stencil_state = is_material_shmode ? 0 : DRW_STATE_STENCIL_EQUAL; + DRWState state = DRW_STATE_FIRST_VERTEX_CONVENTION | DRW_STATE_WRITE_COLOR | + DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; + DRWPass *pass; + uint stencil_mask; + + if (xray == 0) { + DRW_PASS_CREATE(psl->wireframe_ps, state | stencil_state | pd->clipping_state); + pass = psl->wireframe_ps; + stencil_mask = 0xFF; + } + else { + DRW_PASS_CREATE(psl->wireframe_xray_ps, state | pd->clipping_state); + pass = psl->wireframe_xray_ps; + stencil_mask = 0x00; + } + + for (int use_coloring = 0; use_coloring < 2; use_coloring++) { + pd->wires_grp[xray][use_coloring] = grp = DRW_shgroup_create(wires_sh, pass); + DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_float_copy(grp, "wireStepParam", pd->shdata.wire_step_param); + DRW_shgroup_uniform_bool_copy(grp, "useColoring", use_coloring); + DRW_shgroup_uniform_bool_copy(grp, "isTransform", (G.moving & G_TRANSFORM_OBJ) != 0); + DRW_shgroup_uniform_bool_copy(grp, "isObjectColor", is_object_color); + DRW_shgroup_uniform_bool_copy(grp, "isRandomColor", is_random_color); + DRW_shgroup_stencil_mask(grp, stencil_mask); + + pd->wires_all_grp[xray][use_coloring] = grp = DRW_shgroup_create(wires_sh, pass); + DRW_shgroup_uniform_float_copy(grp, "wireStepParam", 1.0f); + DRW_shgroup_stencil_mask(grp, stencil_mask); + } + + pd->wires_sculpt_grp[xray] = grp = DRW_shgroup_create(wires_sh, pass); + DRW_shgroup_uniform_float_copy(grp, "wireStepParam", 10.0f); + DRW_shgroup_uniform_bool_copy(grp, "useColoring", false); + DRW_shgroup_stencil_mask(grp, stencil_mask); + } +} + +void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata, + Object *ob, + OVERLAY_DupliData *dupli, + bool init_dupli) +{ + OVERLAY_Data *data = vedata; + OVERLAY_PrivateData *pd = data->stl->pd; + const DRWContextState *draw_ctx = DRW_context_state_get(); + const bool all_wires = (ob->dtx & OB_DRAW_ALL_EDGES) != 0; + const bool is_xray = (ob->dtx & OB_DRAWXRAY) != 0; + const bool is_mesh = ob->type == OB_MESH; + const bool use_wire = (pd->overlay.flag & V3D_OVERLAY_WIREFRAMES) || (ob->dtx & OB_DRAWWIRE) || + (ob->dt == OB_WIRE); + + /* Fast path for duplis. */ + if (dupli && !init_dupli) { + if (dupli->wire_shgrp && dupli->wire_geom) { + if (dupli->base_flag == ob->base_flag) { + DRW_shgroup_call(dupli->wire_shgrp, dupli->wire_geom, ob); + return; + } + } + else { + /* Nothing to draw for this dupli. */ + return; + } + } + + const bool is_edit_mode = BKE_object_is_in_editmode(ob); + bool has_edit_mesh_cage = false; + if (is_mesh && is_edit_mode) { + /* TODO: Should be its own function. */ + Mesh *me = (Mesh *)ob->data; + BMEditMesh *embm = me->edit_mesh; + if (embm) { + has_edit_mesh_cage = embm->mesh_eval_cage && (embm->mesh_eval_cage != embm->mesh_eval_final); + } + } + + /* Don't do that in edit Mesh mode, unless there is a modifier preview. */ + if (use_wire && (!is_mesh || (!is_edit_mode || has_edit_mesh_cage))) { + const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) && + !DRW_state_is_image_render(); + const bool use_coloring = (use_wire && !is_edit_mode && !use_sculpt_pbvh && + !has_edit_mesh_cage); + DRWShadingGroup *shgrp = NULL; + struct GPUBatch *geom = DRW_cache_object_face_wireframe_get(ob); + + if (geom || use_sculpt_pbvh) { + if (use_sculpt_pbvh) { + shgrp = pd->wires_sculpt_grp[is_xray]; + } + else if (all_wires) { + shgrp = pd->wires_all_grp[is_xray][use_coloring]; + } + else { + shgrp = pd->wires_grp[is_xray][use_coloring]; + } + + if (use_sculpt_pbvh) { + DRW_shgroup_call_sculpt(shgrp, ob, true, false, false); + } + else { + DRW_shgroup_call(shgrp, geom, ob); + } + } + + if (dupli) { + dupli->wire_shgrp = shgrp; + dupli->wire_geom = geom; + } + } + else if (is_mesh && (!is_edit_mode || has_edit_mesh_cage)) { + OVERLAY_ExtraCallBuffers *cb = OVERLAY_extra_call_buffer_get(vedata, ob); + Mesh *me = ob->data; + float *color; + DRW_object_wire_theme_get(ob, draw_ctx->view_layer, &color); + + /* Draw loose geometry. */ + if ((me->totpoly == 0 && me->totedge > 0) || has_edit_mesh_cage) { + struct GPUBatch *geom = DRW_cache_mesh_loose_edges_get(ob); + if (geom) { + OVERLAY_extra_wire(cb, geom, ob->obmat, color); + } + } + else if (me->totedge == 0 && me->totvert > 0) { + struct GPUBatch *geom = DRW_cache_mesh_all_verts_get(ob); + if (geom) { + OVERLAY_extra_loose_points(cb, geom, ob->obmat, color); + } + } + } +} + +void OVERLAY_wireframe_draw(OVERLAY_Data *data) +{ + OVERLAY_FramebufferList *fbl = data->fbl; + OVERLAY_PassList *psl = data->psl; + OVERLAY_PrivateData *pd = data->stl->pd; + + if (pd->antialiasing.enabled) { + GPU_framebuffer_bind(fbl->overlay_line_fb); + } + + DRW_view_set_active(pd->view_wires); + DRW_draw_pass(psl->wireframe_ps); + + DRW_view_set_active(pd->view_default); + + if (pd->antialiasing.enabled) { + GPU_framebuffer_bind(fbl->overlay_default_fb); + } +} + +void OVERLAY_wireframe_in_front_draw(OVERLAY_Data *data) +{ + OVERLAY_PassList *psl = data->psl; + OVERLAY_PrivateData *pd = data->stl->pd; + + DRW_view_set_active(pd->view_wires); + DRW_draw_pass(psl->wireframe_xray_ps); + + DRW_view_set_active(pd->view_default); +} |