From 86abc4da10c70a79c8e0d8c695b19955ee84a4a8 Mon Sep 17 00:00:00 2001 From: Germano Date: Mon, 16 Apr 2018 10:40:46 -0300 Subject: Fix rBb31ebd8c5c55: the asymmetric furstrum algorithm was still incorrect. Although somewhat less micro efficient, I decided to separate the `viewinv` matrix to calculate the world position separately. This makes it easier to understand the code. --- source/blender/draw/intern/draw_manager_exec.c | 109 ++++++++----------------- 1 file changed, 34 insertions(+), 75 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index 2a5a595c682..5f2b7a3c4e0 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -384,100 +384,55 @@ 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]; + float w_half = near / projmat[0][0]; + float h_half = near / projmat[1][1]; + left = projmat[2][0] - w_half; + right = projmat[2][0] + w_half; + bottom = projmat[2][1] - h_half; + top = projmat[2][1] + h_half; } 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]; + left = (-1.0f - projmat[3][0]) / projmat[0][0]; + right = (1.0f - projmat[3][0]) / projmat[0][0]; + bottom = (-1.0f - projmat[3][1]) / projmat[1][1]; + top = (1.0f - projmat[3][1]) / 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[1][2] = r_bbox->vec[2][2] = r_bbox->vec[6][2] = r_bbox->vec[5][2] = -far; + 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][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 +450,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++) { -- cgit v1.2.3 From 10f7f4ec1429f8bee0db128df027bdf2658b4338 Mon Sep 17 00:00:00 2001 From: Germano Date: Mon, 16 Apr 2018 11:42:20 -0300 Subject: Fix unreported error: Algorithm for extracting the Bounding Sphere from an Orthographic frustum was incorrect. There was double transformation. --- source/blender/draw/intern/draw_manager_exec.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index 5f2b7a3c4e0..5671e8374fb 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -486,9 +486,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); -- cgit v1.2.3 From 3a14a0381288ae9f49d1ab489a250cd29a00e771 Mon Sep 17 00:00:00 2001 From: Germano Date: Mon, 16 Apr 2018 11:48:58 -0300 Subject: DRW: Culling: Reorganize frustum_boundbox_calc to match comments. And Cleanup. --- source/blender/draw/intern/draw_manager_exec.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index 5671e8374fb..147868df310 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -399,10 +399,10 @@ static void draw_frustum_boundbox_calc(const float(*projmat)[4], BoundBox *r_bbo far = projmat[3][2] / (projmat[2][2] + 1.0f); float w_half = near / projmat[0][0]; float h_half = near / projmat[1][1]; - left = projmat[2][0] - w_half; - right = projmat[2][0] + w_half; + left = projmat[2][0] - w_half; + right = projmat[2][0] + w_half; bottom = projmat[2][1] - h_half; - top = projmat[2][1] + h_half; + top = projmat[2][1] + h_half; } else { near = (projmat[3][2] + 1.0f) / projmat[2][2]; @@ -414,7 +414,6 @@ static void draw_frustum_boundbox_calc(const float(*projmat)[4], BoundBox *r_bbo } r_bbox->vec[0][2] = r_bbox->vec[3][2] = r_bbox->vec[7][2] = r_bbox->vec[4][2] = -near; - r_bbox->vec[1][2] = r_bbox->vec[2][2] = r_bbox->vec[6][2] = r_bbox->vec[5][2] = -far; 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; @@ -423,12 +422,13 @@ static void draw_frustum_boundbox_calc(const float(*projmat)[4], BoundBox *r_bbo /* Get the coordinates of the far plane. */ if (is_persp) { float sca_far = far / near; - left *= sca_far; + left *= sca_far; bottom *= sca_far; - right *= sca_far; - top *= sca_far; + right *= sca_far; + top *= sca_far; } + 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; -- cgit v1.2.3 From 80bb4254c6fb638cee0d33868c81c76c104817bf Mon Sep 17 00:00:00 2001 From: Germano Date: Mon, 16 Apr 2018 12:37:14 -0300 Subject: Fix T54491: Do not avoid the creation of inverted frustum. Blender allows this. The Cube in the file in the report would always disappear with the non camera view. The clip_end was too small. The correction here is only on the assert. --- source/blender/draw/intern/draw_manager_exec.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index 147868df310..d37a8a643f9 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -395,22 +395,23 @@ static void draw_frustum_boundbox_calc(const float(*projmat)[4], BoundBox *r_bbo bool is_persp = projmat[3][3] == 0.0f; if (is_persp) { - near = projmat[3][2] / (projmat[2][2] - 1.0f); - far = projmat[3][2] / (projmat[2][2] + 1.0f); - float w_half = near / projmat[0][0]; - float h_half = near / projmat[1][1]; + float w_half, h_half; + 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]; left = projmat[2][0] - w_half; right = projmat[2][0] + w_half; bottom = projmat[2][1] - h_half; top = projmat[2][1] + h_half; } else { - near = (projmat[3][2] + 1.0f) / projmat[2][2]; - far = (projmat[3][2] - 1.0f) / projmat[2][2]; - left = (-1.0f - projmat[3][0]) / projmat[0][0]; - right = (1.0f - projmat[3][0]) / projmat[0][0]; + near = (projmat[3][2] + 1.0f) / projmat[2][2]; + far = (projmat[3][2] - 1.0f) / projmat[2][2]; + left = (-1.0f - projmat[3][0]) / projmat[0][0]; + right = (1.0f - projmat[3][0]) / projmat[0][0]; bottom = (-1.0f - projmat[3][1]) / projmat[1][1]; - top = (1.0f - projmat[3][1]) / projmat[1][1]; + top = (1.0f - projmat[3][1]) / projmat[1][1]; } r_bbox->vec[0][2] = r_bbox->vec[3][2] = r_bbox->vec[7][2] = r_bbox->vec[4][2] = -near; @@ -509,7 +510,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 */ -- cgit v1.2.3 From bfc9d426bb95e2bc0dd4541d6b4c5f802909149c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 16 Apr 2018 16:27:55 +0200 Subject: Multi-Object Editing This adds initial multi-object editing support. - Selected objects are used when entering edit & pose modes. - Selection & tools work on all objects however many tools need porting See: T54641 for remaining tasks. Indentation will be done separately. See patch: D3101 --- source/blender/draw/intern/draw_armature.c | 2 +- source/blender/draw/intern/draw_manager.c | 7 +++++++ source/blender/draw/modes/edit_curve_mode.c | 9 ++++++++- source/blender/draw/modes/edit_lattice_mode.c | 4 +++- source/blender/draw/modes/edit_mesh_mode.c | 4 +++- source/blender/draw/modes/edit_metaball_mode.c | 3 ++- source/blender/draw/modes/pose_mode.c | 4 +++- 7 files changed, 27 insertions(+), 6 deletions(-) (limited to 'source/blender/draw') 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_manager.c b/source/blender/draw/intern/draw_manager.c index 6ba1225b687..420841e2efa 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -1554,7 +1554,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/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/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; } -- cgit v1.2.3 From 2b0b4133c8ced3dc569b787873883f44ec9c8979 Mon Sep 17 00:00:00 2001 From: Germano Date: Mon, 16 Apr 2018 14:34:32 -0300 Subject: DRW: Culling: Fix algorithm for asymmetric perspective frustum reconstruction. --- source/blender/draw/intern/draw_manager_exec.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index d37a8a643f9..0ff5522c109 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -395,23 +395,20 @@ static void draw_frustum_boundbox_calc(const float(*projmat)[4], BoundBox *r_bbo bool is_persp = projmat[3][3] == 0.0f; if (is_persp) { - float w_half, h_half; 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]; - left = projmat[2][0] - w_half; - right = projmat[2][0] + w_half; - bottom = projmat[2][1] - h_half; - top = projmat[2][1] + h_half; + 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]; - left = (-1.0f - projmat[3][0]) / projmat[0][0]; - right = (1.0f - projmat[3][0]) / projmat[0][0]; - bottom = (-1.0f - projmat[3][1]) / projmat[1][1]; - top = (1.0f - projmat[3][1]) / 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]; } r_bbox->vec[0][2] = r_bbox->vec[3][2] = r_bbox->vec[7][2] = r_bbox->vec[4][2] = -near; -- cgit v1.2.3 From dccda1fe434e3e3af47c44720cfedc9c1c4ccf52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Mon, 16 Apr 2018 19:26:54 +0200 Subject: DRW/GWN: Add callId builtin uniform. This uniforms can be used to have a unique id for each drawcall of a shgrp. This only works for standard shgroups and is an exception for the outline drawing. --- source/blender/draw/intern/draw_manager.h | 1 + source/blender/draw/intern/draw_manager_data.c | 1 + source/blender/draw/intern/draw_manager_exec.c | 7 +++++++ 3 files changed, 9 insertions(+) (limited to 'source/blender/draw') 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 0ff5522c109..e56206f9b7d 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -1005,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. */ @@ -1013,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) { -- cgit v1.2.3 From c2d4ba2ff54b47a8053c8dd19411186d2a050115 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Mon, 16 Apr 2018 19:33:09 +0200 Subject: GPU/DRW: Add GPU_R16UI format. --- source/blender/draw/intern/DRW_render.h | 1 + source/blender/draw/intern/draw_manager_texture.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'source/blender/draw') diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index 66ca8971a46..5e00005edb6 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, 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; -- cgit v1.2.3 From 7f5d76b37fc909b15a72df725c70c8443c8e760e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Mon, 16 Apr 2018 19:38:40 +0200 Subject: Object Mode: Rework outline drawing. This changes quite a few things. - Outline is now per object. - No more outline at object intersection (fix hairs problem). - Simplify the code quite a bit. We use a R16UI buffer to save one id per object outline. We convert this id to color when detecting the outline. Added textureGatherOffsets to the code but could not test on current hardware so leaving it commented for now. --- source/blender/draw/CMakeLists.txt | 1 + source/blender/draw/modes/object_mode.c | 116 ++++++++++++++------- .../modes/shaders/object_outline_detect_frag.glsl | 104 +++++++++--------- .../modes/shaders/object_outline_prepass_frag.glsl | 10 ++ 4 files changed, 137 insertions(+), 94 deletions(-) create mode 100644 source/blender/draw/modes/shaders/object_outline_prepass_frag.glsl (limited to 'source/blender/draw') diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index d292e4d9405..d2e70300561 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -229,6 +229,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/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/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); +} -- cgit v1.2.3 From 45f04ba48a698439e7c4dd38901edc28bc2033a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Mon, 16 Apr 2018 19:38:49 +0200 Subject: DRW: Fix outdated code. --- source/blender/draw/intern/draw_manager_exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index e56206f9b7d..dcd976805fd 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -963,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 -- cgit v1.2.3 From 34ab90f546f097cada951b2c9ca22bf271996980 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 6 Apr 2018 12:07:27 +0200 Subject: Depsgraph: remove EvaluationContext, pass Depsgraph instead. The depsgraph was always created within a fixed evaluation context. Passing both risks the depsgraph and evaluation context not matching, and it complicates the Python API where we'd have to expose both which is not so easy to understand. This also removes the global evaluation context in main, which assumed there to be a single active scene and view layer. Differential Revision: https://developer.blender.org/D3152 --- source/blender/draw/engines/eevee/eevee_motion_blur.c | 5 +---- source/blender/draw/intern/DRW_render.h | 1 - source/blender/draw/intern/draw_cache_impl_particles.c | 6 ++++-- source/blender/draw/intern/draw_manager.c | 17 ++--------------- source/blender/draw/modes/sculpt_mode.c | 2 +- 5 files changed, 8 insertions(+), 23 deletions(-) (limited to 'source/blender/draw') 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 5e00005edb6..27f2d891cc0 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -507,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_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 420841e2efa..b77218ec6ff 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -350,16 +350,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) { @@ -388,8 +378,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 @@ -1122,15 +1110,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); } /** 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; -- cgit v1.2.3