diff options
author | Jeroen Bakker <j.bakker@atmind.nl> | 2018-04-16 21:35:59 +0300 |
---|---|---|
committer | Jeroen Bakker <j.bakker@atmind.nl> | 2018-04-16 21:35:59 +0300 |
commit | c7d6aa4338527c4fe580bcbf7f8533f582583e13 (patch) | |
tree | e14c93d1f9cde421374db161b276d29dc4289bc7 /source/blender/draw | |
parent | 4ed21f13608901b10f8f4b37cee9a054a91da0bd (diff) | |
parent | 34ab90f546f097cada951b2c9ca22bf271996980 (diff) |
Merge branch 'blender2.8' into blender2.8-workbench
Diffstat (limited to 'source/blender/draw')
19 files changed, 221 insertions, 207 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index f96f496a0f9..3bf1acaf79e 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -234,6 +234,7 @@ data_to_c_simple(modes/shaders/object_empty_image_vert.glsl SRC) data_to_c_simple(modes/shaders/object_outline_resolve_frag.glsl SRC) data_to_c_simple(modes/shaders/object_outline_expand_frag.glsl SRC) data_to_c_simple(modes/shaders/object_outline_detect_frag.glsl SRC) +data_to_c_simple(modes/shaders/object_outline_prepass_frag.glsl SRC) data_to_c_simple(modes/shaders/object_grid_frag.glsl SRC) data_to_c_simple(modes/shaders/object_grid_vert.glsl SRC) data_to_c_simple(modes/shaders/object_lightprobe_grid_vert.glsl SRC) diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c index 9b19163c8d7..4bac8ba2ebd 100644 --- a/source/blender/draw/engines/eevee/eevee_motion_blur.c +++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c @@ -68,16 +68,13 @@ static void eevee_motion_blur_camera_get_matrix_at_time( cam_cpy.data = &camdata_cpy; const DRWContextState *draw_ctx = DRW_context_state_get(); - /* We will be modifying time, so we create copy of eval_ctx. */ - EvaluationContext eval_ctx = draw_ctx->eval_ctx; - eval_ctx.ctime = time; /* Past matrix */ /* FIXME : This is a temporal solution that does not take care of parent animations */ /* Recalc Anim manualy */ BKE_animsys_evaluate_animdata(scene, &cam_cpy.id, cam_cpy.adt, time, ADT_RECALC_ALL); BKE_animsys_evaluate_animdata(scene, &camdata_cpy.id, camdata_cpy.adt, time, ADT_RECALC_ALL); - BKE_object_where_is_calc_time(&eval_ctx, scene, &cam_cpy, time); + BKE_object_where_is_calc_time(draw_ctx->depsgraph, scene, &cam_cpy, time); /* Compute winmat */ CameraParams params; diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index 66ca8971a46..27f2d891cc0 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -187,6 +187,7 @@ typedef enum { DRW_TEX_R_8, DRW_TEX_R_16, DRW_TEX_R_16I, + DRW_TEX_R_16U, DRW_TEX_R_32, DRW_TEX_DEPTH_16, DRW_TEX_DEPTH_24, @@ -506,7 +507,6 @@ typedef struct DRWContextState { struct RenderEngineType *engine_type; - EvaluationContext eval_ctx; struct Depsgraph *depsgraph; eObjectMode object_mode; diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c index c14fe70e0c3..fe87e7f17fd 100644 --- a/source/blender/draw/intern/draw_armature.c +++ b/source/blender/draw/intern/draw_armature.c @@ -1228,7 +1228,7 @@ static void draw_armature_edit(Object *ob) const bool show_text = DRW_state_show_text(); - for (eBone = arm->edbo->first, index = 0; eBone; eBone = eBone->next, index++) { + for (eBone = arm->edbo->first, index = ob->select_color; eBone; eBone = eBone->next, index += 0x10000) { if (eBone->layer & arm->layer) { if ((eBone->flag & BONE_HIDDEN_A) == 0) { const int select_id = is_select ? index : (unsigned int)-1; diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c index 0530d05c199..d7e8a6b71df 100644 --- a/source/blender/draw/intern/draw_cache_impl_particles.c +++ b/source/blender/draw/intern/draw_cache_impl_particles.c @@ -46,6 +46,8 @@ #include "GPU_batch.h" +#include "DEG_depsgraph_query.h" + #include "draw_cache_impl.h" /* own include */ static void particle_batch_cache_clear(ParticleSystem *psys); @@ -466,7 +468,7 @@ static void particle_batch_cache_ensure_pos(Object *object, ParticleSystem *psys ParticleSimulationData sim = {NULL}; const DRWContextState *draw_ctx = DRW_context_state_get(); - sim.eval_ctx = &draw_ctx->eval_ctx; + sim.depsgraph = draw_ctx->depsgraph; sim.scene = draw_ctx->scene; sim.ob = object; sim.psys = psys; @@ -494,7 +496,7 @@ static void particle_batch_cache_ensure_pos(Object *object, ParticleSystem *psys GWN_vertbuf_data_alloc(cache->pos, psys->totpart); for (curr_point = 0, i = 0, pa = psys->particles; i < psys->totpart; i++, pa++) { - state.time = draw_ctx->eval_ctx.ctime; + state.time = DEG_get_ctime(draw_ctx->depsgraph); if (!psys_get_particle_state(&sim, curr_point, &state, 0)) { continue; } diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index b8ed341e2c5..7d4d27b7147 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -351,16 +351,6 @@ static void drw_viewport_cache_resize(void) DRW_instance_data_list_resize(DST.idatalist); } -static void drw_state_eval_ctx_init(DRWManager *dst) -{ - DRWContextState *draw_ctx = &dst->draw_ctx; - DEG_evaluation_context_init_from_scene( - &draw_ctx->eval_ctx, - draw_ctx->scene, - draw_ctx->view_layer, - DST.options.is_scene_render ? DAG_EVAL_RENDER : DAG_EVAL_VIEWPORT); -} - /* Not a viewport variable, we could split this out. */ static void drw_context_state_init(void) { @@ -389,8 +379,6 @@ static void drw_context_state_init(void) else { DST.draw_ctx.object_pose = NULL; } - - drw_state_eval_ctx_init(&DST); } /* It also stores viewport variable to an immutable place: DST @@ -1123,15 +1111,14 @@ void DRW_notify_id_update(const DRWUpdateContext *update_ctx, ID *id) * for each relevant engine / mode engine. */ void DRW_draw_view(const bContext *C) { - EvaluationContext eval_ctx; - CTX_data_eval_ctx(C, &eval_ctx); + Depsgraph *depsgraph = CTX_data_depsgraph(C); RenderEngineType *engine_type = CTX_data_engine_type(C); ARegion *ar = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); /* Reset before using it. */ drw_state_prepare_clean_for_draw(&DST); - DRW_draw_render_loop_ex(eval_ctx.depsgraph, engine_type, ar, v3d, C); + DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, C); } /** @@ -1555,7 +1542,14 @@ void DRW_draw_select_loop( drw_engines_cache_init(); if (use_obedit) { +#if 0 drw_engines_cache_populate(obact); +#else + FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, obact->mode, ob_iter) { + drw_engines_cache_populate(ob_iter); + } + FOREACH_OBJECT_IN_MODE_END; +#endif } else { DEG_OBJECT_ITER_BEGIN( diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h index dd7e84f67d4..4f322b11931 100644 --- a/source/blender/draw/intern/draw_manager.h +++ b/source/blender/draw/intern/draw_manager.h @@ -222,6 +222,7 @@ struct DRWShadingGroup { int normalworld; int orcotexfac; int eye; + int callid; uint16_t matflag; /* Matrices needed, same as DRWCall.flag */ #ifndef NDEBUG diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index ae7854b436c..544129ea124 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -498,6 +498,7 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader) shgroup->normalworld = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_WORLDNORMAL); shgroup->orcotexfac = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_ORCO); shgroup->eye = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_EYE); + shgroup->callid = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_CALLID); shgroup->matflag = 0; if (shgroup->modelinverse > -1) diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index 2a5a595c682..dcd976805fd 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -384,100 +384,53 @@ void DRW_state_clip_planes_reset(void) /** \name Clipping (DRW_clipping) * \{ */ -/* Extract the 8 corners (world space). +/* Extract the 8 corners from a Projection Matrix. * Although less accurate, this solution can be simplified as follows: * BKE_boundbox_init_from_minmax(&bbox, (const float[3]){-1.0f, -1.0f, -1.0f}, (const float[3]){1.0f, 1.0f, 1.0f}); - * for (int i = 0; i < 8; i++) {mul_project_m4_v3(viewprojinv, bbox.vec[i]);} + * for (int i = 0; i < 8; i++) {mul_project_m4_v3(projinv, bbox.vec[i]);} */ -static void draw_frustum_boundbox_calc( - const float (*projmat)[4], const float (*viewinv)[4], BoundBox *r_bbox) +static void draw_frustum_boundbox_calc(const float(*projmat)[4], BoundBox *r_bbox) { - float screenvecs[3][3], loc[3], near, far, w_half, h_half; + float near, far, left, right, bottom, top; bool is_persp = projmat[3][3] == 0.0f; - copy_m3_m4(screenvecs, viewinv); - copy_v3_v3(loc, viewinv[3]); - /* get the values of the minimum and maximum clipping planes distances - * and half the width and height of the nearplane rectangle. */ if (is_persp) { - near = projmat[3][2] / (projmat[2][2] - 1.0f); - far = projmat[3][2] / (projmat[2][2] + 1.0f); - w_half = near / projmat[0][0]; - h_half = near / projmat[1][1]; + near = projmat[3][2] / (projmat[2][2] - 1.0f); + far = projmat[3][2] / (projmat[2][2] + 1.0f); + left = near * (projmat[2][0] - 1.0f) / projmat[0][0]; + right = near * (projmat[2][0] + 1.0f) / projmat[0][0]; + bottom = near * (projmat[2][1] - 1.0f) / projmat[1][1]; + top = near * (projmat[2][1] + 1.0f) / projmat[1][1]; } else { - near = (projmat[3][2] + 1.0f) / projmat[2][2]; - far = (projmat[3][2] - 1.0f) / projmat[2][2]; - w_half = 1.0f / projmat[0][0]; - h_half = 1.0f / projmat[1][1]; + near = ( projmat[3][2] + 1.0f) / projmat[2][2]; + far = ( projmat[3][2] - 1.0f) / projmat[2][2]; + left = (-projmat[3][0] - 1.0f) / projmat[0][0]; + right = (-projmat[3][0] + 1.0f) / projmat[0][0]; + bottom = (-projmat[3][1] - 1.0f) / projmat[1][1]; + top = (-projmat[3][1] + 1.0f) / projmat[1][1]; } - /* With vectors aligned to the screen, reconstruct - * the near plane from the dimensions obtained earlier. */ - float mid[3], hor[3], ver[3]; - mul_v3_v3fl(hor, screenvecs[0], w_half); - mul_v3_v3fl(ver, screenvecs[1], h_half); - madd_v3_v3v3fl(mid, loc, screenvecs[2], -near); - - /* The case below is for non-symmetric frustum. */ - if (is_persp) { - madd_v3_v3fl(mid, hor, projmat[2][0]); - madd_v3_v3fl(mid, ver, projmat[2][1]); - } - else { - madd_v3_v3fl(mid, hor, -projmat[3][0]); - madd_v3_v3fl(mid, ver, -projmat[3][1]); - } - - r_bbox->vec[0][0] = mid[0] - ver[0] - hor[0]; - r_bbox->vec[0][1] = mid[1] - ver[1] - hor[1]; - r_bbox->vec[0][2] = mid[2] - ver[2] - hor[2]; - - r_bbox->vec[3][0] = mid[0] + ver[0] - hor[0]; - r_bbox->vec[3][1] = mid[1] + ver[1] - hor[1]; - r_bbox->vec[3][2] = mid[2] + ver[2] - hor[2]; - - r_bbox->vec[7][0] = mid[0] + ver[0] + hor[0]; - r_bbox->vec[7][1] = mid[1] + ver[1] + hor[1]; - r_bbox->vec[7][2] = mid[2] + ver[2] + hor[2]; - - r_bbox->vec[4][0] = mid[0] - ver[0] + hor[0]; - r_bbox->vec[4][1] = mid[1] - ver[1] + hor[1]; - r_bbox->vec[4][2] = mid[2] - ver[2] + hor[2]; + r_bbox->vec[0][2] = r_bbox->vec[3][2] = r_bbox->vec[7][2] = r_bbox->vec[4][2] = -near; + r_bbox->vec[0][0] = r_bbox->vec[3][0] = left; + r_bbox->vec[4][0] = r_bbox->vec[7][0] = right; + r_bbox->vec[0][1] = r_bbox->vec[4][1] = bottom; + r_bbox->vec[7][1] = r_bbox->vec[3][1] = top; /* Get the coordinates of the far plane. */ if (is_persp) { float sca_far = far / near; - mid[0] = mid[0] + (mid[0] - loc[0]) * sca_far; - mid[1] = mid[1] + (mid[1] - loc[1]) * sca_far; - mid[2] = mid[2] + (mid[2] - loc[2]) * sca_far; - - mul_v3_fl(hor, sca_far); - mul_v3_fl(ver, sca_far); + left *= sca_far; + bottom *= sca_far; + right *= sca_far; + top *= sca_far; } - else { - madd_v3_v3v3fl(mid, loc, screenvecs[2], -far); - /* Non-symmetric frustum. */ - madd_v3_v3fl(mid, hor, -projmat[3][0]); - madd_v3_v3fl(mid, ver, -projmat[3][1]); - } - - r_bbox->vec[1][0] = mid[0] - ver[0] - hor[0]; - r_bbox->vec[1][1] = mid[1] - ver[1] - hor[1]; - r_bbox->vec[1][2] = mid[2] - ver[2] - hor[2]; - - r_bbox->vec[2][0] = mid[0] + ver[0] - hor[0]; - r_bbox->vec[2][1] = mid[1] + ver[1] - hor[1]; - r_bbox->vec[2][2] = mid[2] + ver[2] - hor[2]; - - r_bbox->vec[6][0] = mid[0] + ver[0] + hor[0]; - r_bbox->vec[6][1] = mid[1] + ver[1] + hor[1]; - r_bbox->vec[6][2] = mid[2] + ver[2] + hor[2]; - - r_bbox->vec[5][0] = mid[0] - ver[0] + hor[0]; - r_bbox->vec[5][1] = mid[1] - ver[1] + hor[1]; - r_bbox->vec[5][2] = mid[2] - ver[2] + hor[2]; + r_bbox->vec[1][2] = r_bbox->vec[2][2] = r_bbox->vec[6][2] = r_bbox->vec[5][2] = -far; + r_bbox->vec[1][0] = r_bbox->vec[2][0] = left; + r_bbox->vec[6][0] = r_bbox->vec[5][0] = right; + r_bbox->vec[1][1] = r_bbox->vec[5][1] = bottom; + r_bbox->vec[2][1] = r_bbox->vec[6][1] = top; } static void draw_clipping_setup_from_view(void) @@ -495,11 +448,15 @@ static void draw_clipping_setup_from_view(void) #if 0 /* It has accuracy problems. */ BKE_boundbox_init_from_minmax(&bbox, (const float[3]){-1.0f, -1.0f, -1.0f}, (const float[3]){1.0f, 1.0f, 1.0f}); for (int i = 0; i < 8; i++) { - mul_project_m4_v3(DST.view_data.matstate.mat[DRW_MAT_PERSINV], bbox.vec[i]); + mul_project_m4_v3(projinv, bbox.vec[i]); } #else - draw_frustum_boundbox_calc(projmat, viewinv, &bbox); + draw_frustum_boundbox_calc(projmat, &bbox); #endif + /* Transform into world space. */ + for (int i = 0; i < 8; i++) { + mul_m4_v3(viewinv, bbox.vec[i]); + } /* Compute clip planes using the world space frustum corners. */ for (int p = 0; p < 6; p++) { @@ -527,9 +484,6 @@ static void draw_clipping_setup_from_view(void) float *nearpoint = bbox.vec[0]; float *farpoint = bbox.vec[6]; - mul_project_m4_v3(projinv, nearpoint); - mul_project_m4_v3(projinv, farpoint); - /* just use median point */ mid_v3_v3v3(bsphere->center, farpoint, nearpoint); bsphere->radius = len_v3v3(bsphere->center, farpoint); @@ -553,7 +507,6 @@ static void draw_clipping_setup_from_view(void) float h_sq = len_squared_v3v3(mid_min, mid_max); float fac = (4 * h_sq + b_sq - a_sq) / (8 * h_sq); - BLI_assert(fac >= 0.0f); /* The goal is to get the smallest sphere, * not the sphere that passes through each corner */ @@ -1010,7 +963,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) # define GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count) # define GPU_SELECT_LOAD_IF_PICKSEL_LIST(_shgroup, _start, _count) \ _start = 0; \ - _count = _shgroup->interface.instance_count; + _count = _shgroup->instance_count; #endif @@ -1052,6 +1005,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) } else { bool prev_neg_scale = false; + int callid = 0; for (DRWCall *call = shgroup->calls.first; call; call = call->next) { /* OPTI/IDEA(clem): Do this preparation in another thread. */ @@ -1060,6 +1014,12 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) if ((call->state->flag & DRW_CALL_CULLED) != 0) continue; + /* XXX small exception/optimisation for outline rendering. */ + if (shgroup->callid != -1) { + GPU_shader_uniform_vector_int(shgroup->shader, shgroup->callid, 1, 1, &callid); + callid += 1; + } + /* Negative scale objects */ bool neg_scale = call->state->flag & DRW_CALL_NEGSCALE; if (neg_scale != prev_neg_scale) { diff --git a/source/blender/draw/intern/draw_manager_texture.c b/source/blender/draw/intern/draw_manager_texture.c index 65856a6bf5c..f083e399ac2 100644 --- a/source/blender/draw/intern/draw_manager_texture.c +++ b/source/blender/draw/intern/draw_manager_texture.c @@ -36,6 +36,7 @@ void drw_texture_get_format( * Generally they are multiple of 16bit. */ case DRW_TEX_R_16: case DRW_TEX_R_16I: + case DRW_TEX_R_16U: case DRW_TEX_R_32: case DRW_TEX_RG_8: case DRW_TEX_RG_16: @@ -72,6 +73,7 @@ void drw_texture_get_format( case DRW_TEX_R_8: *r_data_type = GPU_R8; break; case DRW_TEX_R_16: *r_data_type = GPU_R16F; break; case DRW_TEX_R_16I: *r_data_type = GPU_R16I; break; + case DRW_TEX_R_16U: *r_data_type = GPU_R16UI; break; case DRW_TEX_R_32: *r_data_type = GPU_R32F; break; #if 0 case DRW_TEX_RGB_8: *r_data_type = GPU_RGB8; break; diff --git a/source/blender/draw/modes/edit_curve_mode.c b/source/blender/draw/modes/edit_curve_mode.c index 73a4fb1e9e6..b33ebd8ba60 100644 --- a/source/blender/draw/modes/edit_curve_mode.c +++ b/source/blender/draw/modes/edit_curve_mode.c @@ -28,6 +28,8 @@ #include "DNA_curve_types.h" +#include "BKE_object.h" + /* If builtin shaders are needed */ #include "GPU_shader.h" #include "GPU_batch.h" @@ -233,7 +235,12 @@ static void EDIT_CURVE_cache_populate(void *vedata, Object *ob) UNUSED_VARS(psl, stl); if (ob->type == OB_CURVE) { - if (ob == draw_ctx->object_edit) { +#if 0 + if (ob == draw_ctx->object_edit) +#else + if ((ob == draw_ctx->object_edit) || BKE_object_is_in_editmode_and_selected(ob)) +#endif + { Curve *cu = ob->data; /* Get geometry cache */ struct Gwn_Batch *geom; diff --git a/source/blender/draw/modes/edit_lattice_mode.c b/source/blender/draw/modes/edit_lattice_mode.c index 0268f4eb453..e8628711ffd 100644 --- a/source/blender/draw/modes/edit_lattice_mode.c +++ b/source/blender/draw/modes/edit_lattice_mode.c @@ -26,6 +26,8 @@ #include "DRW_engine.h" #include "DRW_render.h" +#include "BKE_object.h" + /* If builtin shaders are needed */ #include "GPU_shader.h" @@ -192,7 +194,7 @@ static void EDIT_LATTICE_cache_populate(void *vedata, Object *ob) UNUSED_VARS(psl); if (ob->type == OB_LATTICE) { - if (ob == draw_ctx->object_edit) { + if ((ob == draw_ctx->object_edit) || BKE_object_is_in_editmode_and_selected(ob)) { /* Get geometry cache */ struct Gwn_Batch *geom; diff --git a/source/blender/draw/modes/edit_mesh_mode.c b/source/blender/draw/modes/edit_mesh_mode.c index 4bd69941809..c465fa38f04 100644 --- a/source/blender/draw/modes/edit_mesh_mode.c +++ b/source/blender/draw/modes/edit_mesh_mode.c @@ -37,6 +37,8 @@ #include "edit_mesh_mode_intern.h" /* own include */ +#include "BKE_object.h" + extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */ extern struct GlobalsUboStorage ts; /* draw_common.c */ @@ -448,7 +450,7 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob) struct Gwn_Batch *geom; if (ob->type == OB_MESH) { - if (ob == draw_ctx->object_edit) { + if ((ob == draw_ctx->object_edit) || BKE_object_is_in_editmode_and_selected(ob)) { const Mesh *me = ob->data; IDProperty *ces_mode_ed = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_EDIT, ""); bool do_occlude_wire = BKE_collection_engine_property_value_get_bool(ces_mode_ed, "show_occlude_wire"); diff --git a/source/blender/draw/modes/edit_metaball_mode.c b/source/blender/draw/modes/edit_metaball_mode.c index bcabeef5bc3..f7b7113a4d6 100644 --- a/source/blender/draw/modes/edit_metaball_mode.c +++ b/source/blender/draw/modes/edit_metaball_mode.c @@ -28,6 +28,7 @@ #include "DNA_meta_types.h" +#include "BKE_object.h" #include "BKE_mball.h" /* If builtin shaders are needed */ @@ -171,7 +172,7 @@ static void EDIT_METABALL_cache_populate(void *vedata, Object *ob) const DRWContextState *draw_ctx = DRW_context_state_get(); DRWShadingGroup *group = stl->g_data->group; - if (ob == draw_ctx->object_edit) { + if ((ob == draw_ctx->object_edit) || BKE_object_is_in_editmode_and_selected(ob)) { MetaBall *mb = ob->data; const bool is_select = DRW_state_is_select(); diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c index 939507a4f21..0d9e46d1268 100644 --- a/source/blender/draw/modes/object_mode.c +++ b/source/blender/draw/modes/object_mode.c @@ -40,6 +40,8 @@ #include "BIF_gl.h" +#include "BLI_string_utils.h" + #include "BKE_anim.h" #include "BKE_camera.h" #include "BKE_curve.h" @@ -69,6 +71,7 @@ extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */ extern struct GPUTexture *globals_ramp; /* draw_common.c */ extern GlobalsUboStorage ts; +extern char datatoc_object_outline_prepass_frag_glsl[]; extern char datatoc_object_outline_resolve_frag_glsl[]; extern char datatoc_object_outline_detect_frag_glsl[]; extern char datatoc_object_outline_expand_frag_glsl[]; @@ -223,6 +226,13 @@ typedef struct OBJECT_PrivateData { DRWShadingGroup *points_select; DRWShadingGroup *points_select_group; DRWShadingGroup *points_transform; + + /* Outlines id offset */ + int id_ofs_active; + int id_ofs_active_group; + int id_ofs_select; + int id_ofs_select_group; + int id_ofs_transform; } OBJECT_PrivateData; /* Transient data */ static struct { @@ -232,6 +242,7 @@ static struct { struct Gwn_VertFormat *empty_image_wire_format; /* fullscreen shaders */ + GPUShader *outline_prepass_sh; GPUShader *outline_resolve_sh; GPUShader *outline_resolve_aa_sh; GPUShader *outline_detect_sh; @@ -259,6 +270,7 @@ static struct { bool draw_grid; /* Temp buffer textures */ struct GPUTexture *outlines_depth_tx; + struct GPUTexture *outlines_id_tx; struct GPUTexture *outlines_color_tx; struct GPUTexture *outlines_blur_tx; } e_data = {NULL}; /* Engine data */ @@ -288,14 +300,20 @@ static void OBJECT_engine_init(void *vedata) if (DRW_state_is_fbo()) { e_data.outlines_depth_tx = DRW_texture_pool_query_2D(size[0], size[1], DRW_TEX_DEPTH_24, &draw_engine_object_type); - e_data.outlines_color_tx = DRW_texture_pool_query_2D(size[0], size[1], DRW_TEX_RGBA_8, - &draw_engine_object_type); + /* XXX TODO DRW_TEX_R_16U can overflow, it would cause no harm + * (only bad colored or missing outlines) but we should + * use 32bits only if the scene have that many objects */ + e_data.outlines_id_tx = DRW_texture_pool_query_2D(size[0], size[1], DRW_TEX_R_16U, + &draw_engine_object_type); GPU_framebuffer_ensure_config(&fbl->outlines_fb, { GPU_ATTACHMENT_TEXTURE(e_data.outlines_depth_tx), - GPU_ATTACHMENT_TEXTURE(e_data.outlines_color_tx) + GPU_ATTACHMENT_TEXTURE(e_data.outlines_id_tx) }); + e_data.outlines_color_tx = DRW_texture_pool_query_2D(size[0], size[1], DRW_TEX_RGBA_8, + &draw_engine_object_type); + GPU_framebuffer_ensure_config(&fbl->expand_fb, { GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(e_data.outlines_color_tx) @@ -310,66 +328,58 @@ static void OBJECT_engine_init(void *vedata) }); } + /* Shaders */ if (!e_data.outline_resolve_sh) { + /* Outline */ + e_data.outline_prepass_sh = DRW_shader_create_3D(datatoc_object_outline_prepass_frag_glsl, NULL); + e_data.outline_resolve_sh = DRW_shader_create_fullscreen(datatoc_object_outline_resolve_frag_glsl, NULL); - } - if (!e_data.outline_resolve_aa_sh) { e_data.outline_resolve_aa_sh = DRW_shader_create_with_lib( datatoc_common_fullscreen_vert_glsl, NULL, datatoc_object_outline_resolve_frag_glsl, datatoc_common_fxaa_lib_glsl, "#define FXAA_ALPHA\n" "#define USE_FXAA\n"); - } - if (!e_data.outline_detect_sh) { - e_data.outline_detect_sh = DRW_shader_create_fullscreen(datatoc_object_outline_detect_frag_glsl, NULL); - } + e_data.outline_detect_sh = DRW_shader_create_with_lib( + datatoc_common_fullscreen_vert_glsl, NULL, + datatoc_object_outline_detect_frag_glsl, + datatoc_common_globals_lib_glsl, + NULL); - if (!e_data.outline_fade_sh) { e_data.outline_fade_sh = DRW_shader_create_fullscreen(datatoc_object_outline_expand_frag_glsl, NULL); - } - if (!e_data.object_empty_image_sh) { + /* Empty images */ e_data.object_empty_image_sh = DRW_shader_create_with_lib( datatoc_object_empty_image_vert_glsl, NULL, datatoc_object_empty_image_frag_glsl, datatoc_common_globals_lib_glsl, NULL); - } - if (!e_data.object_empty_image_wire_sh) { e_data.object_empty_image_wire_sh = DRW_shader_create_with_lib( datatoc_object_empty_image_vert_glsl, NULL, datatoc_object_empty_image_frag_glsl, datatoc_common_globals_lib_glsl, "#define USE_WIRE\n"); - } - if (!e_data.grid_sh) { + /* Grid */ e_data.grid_sh = DRW_shader_create_with_lib( datatoc_object_grid_vert_glsl, NULL, datatoc_object_grid_frag_glsl, datatoc_common_globals_lib_glsl, NULL); - } - if (!e_data.part_prim_sh) { + /* Particles */ e_data.part_prim_sh = DRW_shader_create( datatoc_object_particle_prim_vert_glsl, NULL, datatoc_gpu_shader_flat_color_frag_glsl, NULL); - } - if (!e_data.part_axis_sh) { e_data.part_axis_sh = DRW_shader_create( datatoc_object_particle_prim_vert_glsl, NULL, datatoc_gpu_shader_flat_color_frag_glsl, "#define USE_AXIS\n"); - } - if (!e_data.part_dot_sh) { e_data.part_dot_sh = DRW_shader_create( datatoc_object_particle_dot_vert_glsl, NULL, datatoc_object_particle_dot_frag_glsl, NULL); - } - if (!e_data.lightprobe_grid_sh) { + /* Lightprobes */ e_data.lightprobe_grid_sh = DRW_shader_create( datatoc_object_lightprobe_grid_vert_glsl, NULL, datatoc_gpu_shader_uniform_color_frag_glsl, NULL); } @@ -558,6 +568,7 @@ static void OBJECT_engine_free(void) MEM_SAFE_FREE(e_data.particle_format); MEM_SAFE_FREE(e_data.empty_image_format); MEM_SAFE_FREE(e_data.empty_image_wire_format); + DRW_SHADER_FREE_SAFE(e_data.outline_prepass_sh); DRW_SHADER_FREE_SAFE(e_data.outline_resolve_sh); DRW_SHADER_FREE_SAFE(e_data.outline_resolve_aa_sh); DRW_SHADER_FREE_SAFE(e_data.outline_detect_sh); @@ -571,10 +582,10 @@ static void OBJECT_engine_free(void) DRW_SHADER_FREE_SAFE(e_data.lightprobe_grid_sh); } -static DRWShadingGroup *shgroup_outline(DRWPass *pass, const float col[4], GPUShader *sh) +static DRWShadingGroup *shgroup_outline(DRWPass *pass, const int *ofs, GPUShader *sh) { DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); - DRW_shgroup_uniform_vec4(grp, "color", col, 1); + DRW_shgroup_uniform_int(grp, "baseId", ofs, 1); return grp; } @@ -602,12 +613,19 @@ static DRWShadingGroup *shgroup_theme_id_to_outline_or( { switch (theme_id) { case TH_ACTIVE: + stl->g_data->id_ofs_active++; return stl->g_data->outlines_active; case TH_SELECT: + stl->g_data->id_ofs_select++; return stl->g_data->outlines_select; - case TH_GROUP_ACTIVE: + case TH_GROUP: + stl->g_data->id_ofs_select_group++; return stl->g_data->outlines_select_group; + case TH_GROUP_ACTIVE: + stl->g_data->id_ofs_active_group++; + return stl->g_data->outlines_active_group; case TH_TRANSFORM: + stl->g_data->id_ofs_transform++; return stl->g_data->outlines_transform; default: return fallback; @@ -622,8 +640,10 @@ static DRWShadingGroup *shgroup_theme_id_to_wire_or( return stl->g_data->wire_active; case TH_SELECT: return stl->g_data->wire_select; - case TH_GROUP_ACTIVE: + case TH_GROUP: return stl->g_data->wire_select_group; + case TH_GROUP_ACTIVE: + return stl->g_data->wire_active_group; case TH_TRANSFORM: return stl->g_data->wire_transform; default: @@ -639,8 +659,10 @@ static DRWShadingGroup *shgroup_theme_id_to_point_or( return stl->g_data->points_active; case TH_SELECT: return stl->g_data->points_select; - case TH_GROUP_ACTIVE: + case TH_GROUP: return stl->g_data->points_select_group; + case TH_GROUP_ACTIVE: + return stl->g_data->points_active_group; case TH_TRANSFORM: return stl->g_data->points_transform; default: @@ -786,18 +808,24 @@ static void OBJECT_cache_init(void *vedata) DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_WIRE; psl->outlines = DRW_pass_create("Outlines Depth Pass", state); - GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); + GPUShader *sh = e_data.outline_prepass_sh; /* Select */ - stl->g_data->outlines_select = shgroup_outline(psl->outlines, ts.colorSelect, sh); - stl->g_data->outlines_select_group = shgroup_outline(psl->outlines, ts.colorGroupActive, sh); + stl->g_data->outlines_select = shgroup_outline(psl->outlines, &stl->g_data->id_ofs_select, sh); + stl->g_data->outlines_select_group = shgroup_outline(psl->outlines, &stl->g_data->id_ofs_select_group, sh); /* Transform */ - stl->g_data->outlines_transform = shgroup_outline(psl->outlines, ts.colorTransform, sh); + stl->g_data->outlines_transform = shgroup_outline(psl->outlines, &stl->g_data->id_ofs_transform, sh); /* Active */ - stl->g_data->outlines_active = shgroup_outline(psl->outlines, ts.colorActive, sh); - stl->g_data->outlines_active_group = shgroup_outline(psl->outlines, ts.colorGroupActive, sh); + stl->g_data->outlines_active = shgroup_outline(psl->outlines, &stl->g_data->id_ofs_active, sh); + stl->g_data->outlines_active_group = shgroup_outline(psl->outlines, &stl->g_data->id_ofs_active_group, sh); + + stl->g_data->id_ofs_select = 0; + stl->g_data->id_ofs_select_group = 0; + stl->g_data->id_ofs_active = 0; + stl->g_data->id_ofs_active_group = 0; + stl->g_data->id_ofs_transform = 0; } { @@ -822,10 +850,12 @@ static void OBJECT_cache_init(void *vedata) psl->outlines_search = DRW_pass_create("Outlines Detect Pass", state); DRWShadingGroup *grp = DRW_shgroup_create(e_data.outline_detect_sh, psl->outlines_search); - DRW_shgroup_uniform_texture_ref(grp, "outlineColor", &e_data.outlines_color_tx); + DRW_shgroup_uniform_texture_ref(grp, "outlineId", &e_data.outlines_id_tx); DRW_shgroup_uniform_texture_ref(grp, "outlineDepth", &e_data.outlines_depth_tx); DRW_shgroup_uniform_texture_ref(grp, "sceneDepth", &dtxl->depth); + DRW_shgroup_uniform_block(grp, "globalsBlock", globals_ubo); DRW_shgroup_uniform_float(grp, "alphaOcclu", &alphaOcclu, 1); + DRW_shgroup_uniform_int(grp, "idOffsets", &stl->g_data->id_ofs_active, 5); DRW_shgroup_call_add(grp, quad, NULL); psl->outlines_expand = DRW_pass_create("Outlines Expand Pass", state); @@ -2038,6 +2068,7 @@ static void OBJECT_draw_scene(void *vedata) OBJECT_PassList *psl = ((OBJECT_Data *)vedata)->psl; OBJECT_StorageList *stl = ((OBJECT_Data *)vedata)->stl; OBJECT_FramebufferList *fbl = ((OBJECT_Data *)vedata)->fbl; + OBJECT_PrivateData *g_data = stl->g_data; DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); @@ -2045,7 +2076,18 @@ static void OBJECT_draw_scene(void *vedata) if (DRW_state_is_fbo()) { DRW_stats_group_start("Outlines"); - + + int id_ct_select = g_data->id_ofs_select; + int id_ct_select_group = g_data->id_ofs_select_group; + int id_ct_active = g_data->id_ofs_active; + int id_ct_active_group = g_data->id_ofs_active_group; + + g_data->id_ofs_active = 1; + g_data->id_ofs_active_group = g_data->id_ofs_active + id_ct_active + 1; + g_data->id_ofs_select = g_data->id_ofs_active_group + id_ct_active_group + 1; + g_data->id_ofs_select_group = g_data->id_ofs_select + id_ct_select + 1; + g_data->id_ofs_transform = g_data->id_ofs_select_group + id_ct_select_group + 1; + /* Render filled polygon on a separate framebuffer */ GPU_framebuffer_bind(fbl->outlines_fb); GPU_framebuffer_clear_color_depth(fbl->outlines_fb, clearcol, 1.0f); diff --git a/source/blender/draw/modes/pose_mode.c b/source/blender/draw/modes/pose_mode.c index 749c3e71368..1d3d31ab54d 100644 --- a/source/blender/draw/modes/pose_mode.c +++ b/source/blender/draw/modes/pose_mode.c @@ -139,7 +139,9 @@ bool DRW_pose_mode_armature(Object *ob, Object *active_ob) const DRWContextState *draw_ctx = DRW_context_state_get(); /* Pode armature is handled by pose mode engine. */ - if ((ob == active_ob) && ((draw_ctx->object_mode & OB_MODE_POSE) != 0)) { + if (((ob == active_ob) || (ob->base_flag & BASE_SELECTED)) && + ((draw_ctx->object_mode & OB_MODE_POSE) != 0)) + { return true; } diff --git a/source/blender/draw/modes/sculpt_mode.c b/source/blender/draw/modes/sculpt_mode.c index 65f4653591f..4fb4464df06 100644 --- a/source/blender/draw/modes/sculpt_mode.c +++ b/source/blender/draw/modes/sculpt_mode.c @@ -202,7 +202,7 @@ static void SCULPT_cache_populate(void *vedata, Object *ob) * but this avoids waiting on first stroke) */ Scene *scene = draw_ctx->scene; - BKE_sculpt_update_mesh_elements(&draw_ctx->eval_ctx, scene, scene->toolsettings->sculpt, ob, false, false); + BKE_sculpt_update_mesh_elements(draw_ctx->depsgraph, scene, scene->toolsettings->sculpt, ob, false, false); } PBVH *pbvh = ob->sculpt->pbvh; diff --git a/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl b/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl index dc0ea938436..6b0f66d7c94 100644 --- a/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl +++ b/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl @@ -3,77 +3,67 @@ in vec4 uvcoordsvar; out vec4 FragColor; -uniform sampler2D outlineColor; +uniform usampler2D outlineId; uniform sampler2D outlineDepth; uniform sampler2D sceneDepth; +uniform int idOffsets[5]; + uniform float alphaOcclu; uniform vec2 viewportSize; -void search_outline(ivec2 uv, vec4 ref_col, inout bool ref_occlu, inout bool outline) +vec4 convert_id_to_color(int id) { - if (!outline) { - vec4 color = texelFetch(outlineColor, uv, 0).rgba; - if (color != ref_col) { - outline = true; - } - else { - float depth = texelFetch(outlineDepth, uv, 0).r; - float scene_depth = texelFetch(sceneDepth, uv, 0).r; - bool occlu = (depth > scene_depth); - - if (occlu != ref_occlu && !ref_occlu) { - outline = true; - } - } + if (id == 0) { + return vec4(0.0); + } + if (id < idOffsets[1]) { + return colorActive; + } + else if (id < idOffsets[2]) { + return colorGroupActive; + } + else if (id < idOffsets[3]) { + return colorSelect; + } + else if (id < idOffsets[4]) { + return colorGroup; + } + else { + return colorTransform; } } +const ivec2 ofs[4] = ivec2[4]( + ivec2( 1, 0), ivec2( 0, 1), + ivec2(-1, 0), ivec2( 0, -1) +); + void main() { - ivec2 uv = ivec2(gl_FragCoord.xy); - - vec4 color[4]; - /* Idea : Use a 16bit ID to identify the color - * and store the colors in a UBO. And fetch all ids - * for discontinuity check with one textureGather \o/ */ - vec4 ref_col = texelFetch(outlineColor, uv, 0).rgba; - color[0] = texelFetchOffset(outlineColor, uv, 0, ivec2( 1, 0)).rgba; - color[1] = texelFetchOffset(outlineColor, uv, 0, ivec2( 0, 1)).rgba; - color[2] = texelFetchOffset(outlineColor, uv, 0, ivec2(-1, 0)).rgba; - color[3] = texelFetchOffset(outlineColor, uv, 0, ivec2( 0, -1)).rgba; - - /* TODO GATHER */ - vec4 depths; - float depth = texelFetch(outlineDepth, uv, 0).r; - depths.x = texelFetchOffset(outlineDepth, uv, 0, ivec2( 1, 0)).r; - depths.y = texelFetchOffset(outlineDepth, uv, 0, ivec2( 0, 1)).r; - depths.z = texelFetchOffset(outlineDepth, uv, 0, ivec2(-1, 0)).r; - depths.w = texelFetchOffset(outlineDepth, uv, 0, ivec2( 0, -1)).r; - - vec4 scene_depths; - float scene_depth = texelFetch(sceneDepth, uv, 0).r; - scene_depths.x = texelFetchOffset(sceneDepth, uv, 0, ivec2( 1, 0)).r; - scene_depths.y = texelFetchOffset(sceneDepth, uv, 0, ivec2( 0, 1)).r; - scene_depths.z = texelFetchOffset(sceneDepth, uv, 0, ivec2(-1, 0)).r; - scene_depths.w = texelFetchOffset(sceneDepth, uv, 0, ivec2( 0, -1)).r; + ivec2 texel = ivec2(gl_FragCoord.xy); + vec2 uv = gl_FragCoord.xy / vec2(textureSize(outlineId, 0).xy); - bool ref_occlu = (depth > scene_depth); - bool outline = false; - -#if 1 - bvec4 occlu = (!ref_occlu) ? notEqual(greaterThan(depths, scene_depths), bvec4(ref_occlu)) : bvec4(false); - outline = (!outline) ? (color[0] != ref_col) || occlu.x : true; - outline = (!outline) ? (color[1] != ref_col) || occlu.y : true; - outline = (!outline) ? (color[2] != ref_col) || occlu.z : true; - outline = (!outline) ? (color[3] != ref_col) || occlu.w : true; + uvec4 id; + uint ref_id = texelFetch(outlineId, texel, 0).r; +#if 0 /* commented out until being tested */ + id = textureGatherOffsets(outlineId, uv, ofs); #else - search_outline(uv + ivec2( 1, 0), ref_col, ref_occlu, outline); - search_outline(uv + ivec2( 0, 1), ref_col, ref_occlu, outline); - search_outline(uv + ivec2(-1, 0), ref_col, ref_occlu, outline); - search_outline(uv + ivec2( 0, -1), ref_col, ref_occlu, outline); + id.x = texelFetchOffset(outlineId, texel, 0, ofs[0]).r; + id.y = texelFetchOffset(outlineId, texel, 0, ofs[1]).r; + id.z = texelFetchOffset(outlineId, texel, 0, ofs[2]).r; + id.w = texelFetchOffset(outlineId, texel, 0, ofs[3]).r; #endif - FragColor = ref_col; - FragColor.a *= (outline) ? (ref_occlu) ? alphaOcclu : 1.0 : 0.0; + float ref_depth = texelFetch(outlineDepth, texel, 0).r; + float scene_depth = texelFetch(sceneDepth, texel, 0).r; + + /* Avoid bad cases of zfighting for occlusion only. */ + const float epsilon = 3.0 / 8388608.0; + bool occluded = (ref_depth > scene_depth + epsilon); + bool outline = any(notEqual(id, uvec4(ref_id))); + + FragColor = convert_id_to_color(int(ref_id)); + FragColor.a *= (occluded) ? alphaOcclu : 1.0; + FragColor.a = (outline) ? FragColor.a : 0.0; } diff --git a/source/blender/draw/modes/shaders/object_outline_prepass_frag.glsl b/source/blender/draw/modes/shaders/object_outline_prepass_frag.glsl new file mode 100644 index 00000000000..776adb787ad --- /dev/null +++ b/source/blender/draw/modes/shaders/object_outline_prepass_frag.glsl @@ -0,0 +1,10 @@ +uniform int callId; +uniform int baseId; + +/* using uint because 16bit uint can contain more ids than int. */ +out uint outId; + +void main() +{ + outId = uint(baseId + callId); +} |