Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2017-03-18 03:55:41 +0300
committerClément Foucault <foucault.clem@gmail.com>2017-03-18 03:56:34 +0300
commit4137f30928dcfda4539d3d80df2c3e079eed12ec (patch)
treeb5b7fb2cef587ea9c2cdd5789350d42b3f71a9ce /source/blender/draw
parentcddde85f2c5f25f3672a9c985b5174b19670e7af (diff)
Object Mode: Add stencil test to remove object outlines inside the silouhette.
It also adds nice occluded silouhette information for selected objects that are behind visible objects. This methods is really heavy because it needs to render the wires twices.
Diffstat (limited to 'source/blender/draw')
-rw-r--r--source/blender/draw/CMakeLists.txt1
-rw-r--r--source/blender/draw/engines/clay/clay.c28
-rw-r--r--source/blender/draw/engines/eevee/eevee.c48
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h2
-rw-r--r--source/blender/draw/intern/DRW_render.h8
-rw-r--r--source/blender/draw/intern/draw_manager.c247
-rw-r--r--source/blender/draw/intern/draw_view.c5
-rw-r--r--source/blender/draw/modes/edit_mesh_mode.c2
-rw-r--r--source/blender/draw/modes/object_mode.c163
-rw-r--r--source/blender/draw/modes/shaders/object_occluded_outline_frag.glsl15
10 files changed, 329 insertions, 190 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 74e772958f5..ec34e710c10 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -115,6 +115,7 @@ data_to_c_simple(modes/shaders/edit_overlay_facefill_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_overlay_facefill_frag.glsl SRC)
data_to_c_simple(modes/shaders/edit_normals_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_normals_geom.glsl SRC)
+data_to_c_simple(modes/shaders/object_occluded_outline_frag.glsl SRC)
list(APPEND INC
)
diff --git a/source/blender/draw/engines/clay/clay.c b/source/blender/draw/engines/clay/clay.c
index a91027cb314..a40805a50c1 100644
--- a/source/blender/draw/engines/clay/clay.c
+++ b/source/blender/draw/engines/clay/clay.c
@@ -597,7 +597,11 @@ static DRWShadingGroup *CLAY_object_shgrp_get(Object *ob, CLAY_StorageList *stl,
}
static DRWShadingGroup *depth_shgrp;
+static DRWShadingGroup *depth_shgrp_select;
+static DRWShadingGroup *depth_shgrp_active;
static DRWShadingGroup *depth_shgrp_cull;
+static DRWShadingGroup *depth_shgrp_cull_select;
+static DRWShadingGroup *depth_shgrp_cull_active;
static void CLAY_cache_init(void)
{
@@ -607,11 +611,23 @@ static void CLAY_cache_init(void)
/* Depth Pass */
{
- psl->depth_pass_cull = DRW_pass_create("Depth Pass Cull", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_CULL_BACK);
psl->depth_pass = DRW_pass_create("Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+ depth_shgrp = DRW_shgroup_create(data.depth_sh, psl->depth_pass);
+
+ depth_shgrp_select = DRW_shgroup_create(data.depth_sh, psl->depth_pass);
+ DRW_shgroup_state_set(depth_shgrp_select, DRW_STATE_WRITE_STENCIL_SELECT);
+
+ depth_shgrp_active = DRW_shgroup_create(data.depth_sh, psl->depth_pass);
+ DRW_shgroup_state_set(depth_shgrp_active, DRW_STATE_WRITE_STENCIL_ACTIVE);
+ psl->depth_pass_cull = DRW_pass_create("Depth Pass Cull", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_CULL_BACK);
depth_shgrp_cull = DRW_shgroup_create(data.depth_sh, psl->depth_pass_cull);
- depth_shgrp = DRW_shgroup_create(data.depth_sh, psl->depth_pass);
+
+ depth_shgrp_cull_select = DRW_shgroup_create(data.depth_sh, psl->depth_pass_cull);
+ DRW_shgroup_state_set(depth_shgrp_cull_select, DRW_STATE_WRITE_STENCIL_SELECT);
+
+ depth_shgrp_cull_active = DRW_shgroup_create(data.depth_sh, psl->depth_pass_cull);
+ DRW_shgroup_state_set(depth_shgrp_cull_active, DRW_STATE_WRITE_STENCIL_ACTIVE);
}
/* Clay Pass */
@@ -642,7 +658,13 @@ static void CLAY_cache_populate(Object *ob)
geom = DRW_cache_surface_get(ob);
/* Depth Prepass */
- DRW_shgroup_call_add((do_cull) ? depth_shgrp_cull : depth_shgrp, geom, ob->obmat);
+ /* waiting for proper flag */
+ // if ((ob->base_flag & BASE_ACTIVE) != 0)
+ // DRW_shgroup_call_add((do_cull) ? depth_shgrp_cull_active : depth_shgrp_active, geom, ob->obmat);
+ if ((ob->base_flag & BASE_SELECTED) != 0)
+ DRW_shgroup_call_add((do_cull) ? depth_shgrp_cull_select : depth_shgrp_select, geom, ob->obmat);
+ else
+ DRW_shgroup_call_add((do_cull) ? depth_shgrp_cull : depth_shgrp, geom, ob->obmat);
/* Shading */
clay_shgrp = CLAY_object_shgrp_get(ob, stl, psl);
diff --git a/source/blender/draw/engines/eevee/eevee.c b/source/blender/draw/engines/eevee/eevee.c
index b4b461f583b..c85e35c904d 100644
--- a/source/blender/draw/engines/eevee/eevee.c
+++ b/source/blender/draw/engines/eevee/eevee.c
@@ -33,11 +33,18 @@
/* *********** STATIC *********** */
static struct {
struct GPUShader *default_lit;
+ struct GPUShader *depth_sh;
struct GPUShader *tonemap;
} e_data = {NULL}; /* Engine data */
static struct {
DRWShadingGroup *default_lit_grp;
+ DRWShadingGroup *depth_shgrp;
+ DRWShadingGroup *depth_shgrp_select;
+ DRWShadingGroup *depth_shgrp_active;
+ DRWShadingGroup *depth_shgrp_cull;
+ DRWShadingGroup *depth_shgrp_cull_select;
+ DRWShadingGroup *depth_shgrp_cull_active;
EEVEE_Data *vedata;
} g_data = {NULL}; /* Transient data */
@@ -62,6 +69,10 @@ static void EEVEE_engine_init(void)
&tex, 1);
if (!e_data.default_lit) {
+ e_data.depth_sh = DRW_shader_create_3D_depth_only();
+ }
+
+ if (!e_data.default_lit) {
e_data.default_lit = DRW_shader_create(datatoc_lit_surface_vert_glsl, NULL, datatoc_lit_surface_frag_glsl, "#define MAX_LIGHT 128\n");
}
@@ -84,7 +95,27 @@ static void EEVEE_cache_init(void)
EEVEE_StorageList *stl = g_data.vedata->stl;
{
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
+ psl->depth_pass = DRW_pass_create("Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+ g_data.depth_shgrp = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass);
+
+ g_data.depth_shgrp_select = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass);
+ DRW_shgroup_state_set(g_data.depth_shgrp_select, DRW_STATE_WRITE_STENCIL_SELECT);
+
+ g_data.depth_shgrp_active = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass);
+ DRW_shgroup_state_set(g_data.depth_shgrp_active, DRW_STATE_WRITE_STENCIL_ACTIVE);
+
+ psl->depth_pass_cull = DRW_pass_create("Depth Pass Cull", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_CULL_BACK);
+ g_data.depth_shgrp_cull = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass_cull);
+
+ g_data.depth_shgrp_cull_select = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass_cull);
+ DRW_shgroup_state_set(g_data.depth_shgrp_cull_select, DRW_STATE_WRITE_STENCIL_SELECT);
+
+ g_data.depth_shgrp_cull_active = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass_cull);
+ DRW_shgroup_state_set(g_data.depth_shgrp_cull_active, DRW_STATE_WRITE_STENCIL_ACTIVE);
+ }
+
+ {
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_EQUAL;
psl->pass = DRW_pass_create("Default Light Pass", state);
g_data.default_lit_grp = DRW_shgroup_create(e_data.default_lit, psl->pass);
@@ -112,8 +143,19 @@ static void EEVEE_cache_populate(Object *ob)
EEVEE_StorageList *stl = g_data.vedata->stl;
if (ob->type == OB_MESH) {
+ CollectionEngineSettings *ces_mode_ob = BKE_object_collection_engine_get(ob, COLLECTION_MODE_OBJECT, "");
+ bool do_cull = BKE_collection_engine_property_value_get_bool(ces_mode_ob, "show_backface_culling");
struct Batch *geom = DRW_cache_surface_get(ob);
+ /* Depth Prepass */
+ /* waiting for proper flag */
+ // if ((ob->base_flag & BASE_ACTIVE) != 0)
+ // DRW_shgroup_call_add((do_cull) ? depth_shgrp_cull_active : depth_shgrp_active, geom, ob->obmat);
+ if ((ob->base_flag & BASE_SELECTED) != 0)
+ DRW_shgroup_call_add((do_cull) ? g_data.depth_shgrp_cull_select : g_data.depth_shgrp_select, geom, ob->obmat);
+ else
+ DRW_shgroup_call_add((do_cull) ? g_data.depth_shgrp_cull : g_data.depth_shgrp, geom, ob->obmat);
+
DRW_shgroup_call_add(g_data.default_lit_grp, geom, ob->obmat);
}
else if (ob->type == OB_LAMP) {
@@ -146,8 +188,10 @@ static void EEVEE_draw_scene(void)
/* Clear Depth */
/* TODO do background */
float clearcol[4] = {0.0f, 0.0f, 0.0f, 1.0f};
- DRW_framebuffer_clear(true, true, clearcol, 1.0f);
+ DRW_framebuffer_clear(true, true, true, clearcol, 1.0f);
+ DRW_draw_pass(psl->depth_pass);
+ DRW_draw_pass(psl->depth_pass_cull);
DRW_draw_pass(psl->pass);
/* Restore default framebuffer */
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 4e966757718..4d8f697cc64 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -27,6 +27,8 @@ struct Object;
/* keep it under MAX_PASSES */
typedef struct EEVEE_PassList {
+ struct DRWPass *depth_pass;
+ struct DRWPass *depth_pass_cull;
struct DRWPass *pass;
struct DRWPass *tonemap;
} EEVEE_PassList;
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 470f061ebef..0fcfa50f480 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -161,7 +161,7 @@ typedef struct DRWFboTexture {
void DRW_framebuffer_init(struct GPUFrameBuffer **fb, int width, int height, DRWFboTexture textures[MAX_FBO_TEX], int texnbr);
void DRW_framebuffer_bind(struct GPUFrameBuffer *fb);
-void DRW_framebuffer_clear(bool color, bool depth, float clear_col[4], float clear_depth);
+void DRW_framebuffer_clear(bool color, bool depth, bool stencil, float clear_col[4], float clear_depth);
void DRW_framebuffer_texture_attach(struct GPUFrameBuffer *fb, struct GPUTexture *tex, int slot);
void DRW_framebuffer_texture_detach(struct GPUTexture *tex);
void DRW_framebuffer_blit(struct GPUFrameBuffer *fb_read, struct GPUFrameBuffer *fb_write, bool depth);
@@ -190,6 +190,11 @@ typedef enum {
DRW_STATE_STIPPLE_3 = (1 << 11),
DRW_STATE_STIPPLE_4 = (1 << 12),
DRW_STATE_BLEND = (1 << 13),
+
+ DRW_STATE_WRITE_STENCIL_SELECT = (1 << 14),
+ DRW_STATE_WRITE_STENCIL_ACTIVE = (1 << 15),
+ DRW_STATE_TEST_STENCIL_SELECT = (1 << 16),
+ DRW_STATE_TEST_STENCIL_ACTIVE = (1 << 17),
} DRWState;
DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass);
@@ -230,7 +235,6 @@ typedef enum {
void DRW_viewport_init(const bContext *C);
void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type);
-void DRW_viewport_engine_data_set(const char *engine_name, void *fbl, void *txl, void *psl, void *stl);
void *DRW_viewport_engine_data_get(const char *engine_name);
float *DRW_viewport_size_get(void);
float *DRW_viewport_screenvecs_get(void);
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 26ab09fe487..6b7fe00dba1 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -148,7 +148,7 @@ struct DRWShadingGroup {
struct GPUShader *shader; /* Shader to bind */
struct DRWInterface *interface; /* Uniforms pointers */
ListBase calls; /* DRWCall or DRWDynamicCall depending of type*/
- int state; /* State changes for this batch only */
+ DRWState state; /* State changes for this batch only */
int type;
Batch *instance_geom; /* Geometry to instance */
@@ -163,6 +163,12 @@ enum {
DRW_SHG_INSTANCE,
};
+/* only 16 bits long */
+enum {
+ STENCIL_SELECT = (1 << 0),
+ STENCIL_ACTIVE = (1 << 1),
+};
+
/* Render State */
static struct DRWGlobalState {
/* Rendering state */
@@ -730,39 +736,128 @@ void DRW_pass_free(DRWPass *pass)
/* ****************************************** DRAW ******************************************/
#ifdef WITH_CLAY_ENGINE
-/* Only alter the state (does not reset it like set_state() ) */
-static void shgroup_set_state(DRWShadingGroup *shgroup)
+static void set_state(DRWState flag, const bool reset)
{
- if (shgroup->state) {
- /* Blend */
- if (shgroup->state & DRW_STATE_BLEND) {
- glEnable(GL_BLEND);
+ /* TODO Keep track of the state and only revert what is needed */
+
+ if (reset) {
+ /* Depth Write */
+ if (flag & DRW_STATE_WRITE_DEPTH)
+ glDepthMask(GL_TRUE);
+ else
+ glDepthMask(GL_FALSE);
+
+ /* Color Write */
+ if (flag & DRW_STATE_WRITE_COLOR)
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ else
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+
+ /* Backface Culling */
+ if (flag & DRW_STATE_CULL_BACK ||
+ flag & DRW_STATE_CULL_FRONT)
+ {
+ glEnable(GL_CULL_FACE);
+
+ if (flag & DRW_STATE_CULL_BACK)
+ glCullFace(GL_BACK);
+ else if (flag & DRW_STATE_CULL_FRONT)
+ glCullFace(GL_FRONT);
+ }
+ else {
+ glDisable(GL_CULL_FACE);
}
- /* Wire width */
- if (shgroup->state & DRW_STATE_WIRE) {
- glLineWidth(1.0f);
+ /* Depht Test */
+ if (flag & (DRW_STATE_DEPTH_LESS | DRW_STATE_DEPTH_EQUAL | DRW_STATE_DEPTH_GREATER))
+ {
+ glEnable(GL_DEPTH_TEST);
+
+ if (flag & DRW_STATE_DEPTH_LESS)
+ glDepthFunc(GL_LEQUAL);
+ else if (flag & DRW_STATE_DEPTH_EQUAL)
+ glDepthFunc(GL_EQUAL);
+ else if (flag & DRW_STATE_DEPTH_GREATER)
+ glDepthFunc(GL_GREATER);
}
- else if (shgroup->state & DRW_STATE_WIRE_LARGE) {
- glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
+ else {
+ glDisable(GL_DEPTH_TEST);
}
+ }
+
+ /* Wire Width */
+ if (flag & DRW_STATE_WIRE) {
+ glLineWidth(1.0f);
+ }
+ else if (flag & DRW_STATE_WIRE_LARGE) {
+ glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
+ }
- /* Line Stipple */
- if (shgroup->state & DRW_STATE_STIPPLE_2) {
- setlinestyle(2);
+ /* Points Size */
+ if (flag & DRW_STATE_POINT) {
+ GPU_enable_program_point_size();
+ glPointSize(5.0f);
+ }
+ else if (reset) {
+ GPU_disable_program_point_size();
+ }
+
+ /* Blending (all buffer) */
+ if (flag & DRW_STATE_BLEND) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ else if (reset) {
+ glDisable(GL_BLEND);
+ }
+
+ /* Line Stipple */
+ if (flag & DRW_STATE_STIPPLE_2) {
+ setlinestyle(2);
+ }
+ else if (flag & DRW_STATE_STIPPLE_3) {
+ setlinestyle(3);
+ }
+ else if (flag & DRW_STATE_STIPPLE_4) {
+ setlinestyle(4);
+ }
+ else if (reset) {
+ setlinestyle(0);
+ }
+
+ /* Stencil */
+ if (flag & (DRW_STATE_WRITE_STENCIL_SELECT | DRW_STATE_WRITE_STENCIL_ACTIVE |
+ DRW_STATE_TEST_STENCIL_SELECT | DRW_STATE_TEST_STENCIL_ACTIVE))
+ {
+ glEnable(GL_STENCIL_TEST);
+
+ /* Stencil Write */
+ if (flag & DRW_STATE_WRITE_STENCIL_SELECT) {
+ glStencilMask(STENCIL_SELECT);
+ glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+ glStencilFunc(GL_ALWAYS, 0xFF, STENCIL_SELECT);
}
- else if (shgroup->state & DRW_STATE_STIPPLE_3) {
- setlinestyle(3);
+ else if (flag & DRW_STATE_WRITE_STENCIL_ACTIVE) {
+ glStencilMask(STENCIL_ACTIVE);
+ glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+ glStencilFunc(GL_ALWAYS, 0xFF, STENCIL_ACTIVE);
}
- else if (shgroup->state & DRW_STATE_STIPPLE_4) {
- setlinestyle(4);
+ /* Stencil Test */
+ else if (flag & DRW_STATE_TEST_STENCIL_SELECT) {
+ glStencilMask(0x00); /* disable write */
+ glStencilFunc(GL_NOTEQUAL, 0xFF, STENCIL_SELECT);
}
-
- if (shgroup->state & DRW_STATE_POINT) {
- GPU_enable_program_point_size();
- glPointSize(5.0f);
+ else if (flag & DRW_STATE_TEST_STENCIL_ACTIVE) {
+ glStencilMask(0x00); /* disable write */
+ glStencilFunc(GL_NOTEQUAL, 0xFF, STENCIL_ACTIVE);
}
}
+ else if (reset) {
+ /* disable write & test */
+ glStencilMask(0x00);
+ glStencilFunc(GL_ALWAYS, 1, 0xFF);
+ glDisable(GL_STENCIL_TEST);
+ }
}
typedef struct DRWBoundTexture {
@@ -867,7 +962,9 @@ static void draw_shgroup(DRWShadingGroup *shgroup)
shgroup_dynamic_batch_from_calls(shgroup);
}
- shgroup_set_state(shgroup);
+ if (shgroup->state != 0) {
+ set_state(shgroup->state, false);
+ }
/* Binding Uniform */
/* Don't check anything, Interface should already contain the least uniform as possible */
@@ -936,103 +1033,13 @@ static void draw_shgroup(DRWShadingGroup *shgroup)
}
}
-static void set_state(short flag)
-{
- /* TODO Keep track of the state and only revert what is needed */
-
- /* Depth Write */
- if (flag & DRW_STATE_WRITE_DEPTH)
- glDepthMask(GL_TRUE);
- else
- glDepthMask(GL_FALSE);
-
- /* Color Write */
- if (flag & DRW_STATE_WRITE_COLOR)
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- else
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
-
- /* Backface Culling */
- if (flag & DRW_STATE_CULL_BACK ||
- flag & DRW_STATE_CULL_FRONT)
- {
-
- glEnable(GL_CULL_FACE);
-
- if (flag & DRW_STATE_CULL_BACK)
- glCullFace(GL_BACK);
- else if (flag & DRW_STATE_CULL_FRONT)
- glCullFace(GL_FRONT);
- }
- else {
- glDisable(GL_CULL_FACE);
- }
-
- /* Depht Test */
- if (flag & (DRW_STATE_DEPTH_LESS | DRW_STATE_DEPTH_EQUAL | DRW_STATE_DEPTH_GREATER))
- {
-
- glEnable(GL_DEPTH_TEST);
-
- if (flag & DRW_STATE_DEPTH_LESS)
- glDepthFunc(GL_LEQUAL);
- else if (flag & DRW_STATE_DEPTH_EQUAL)
- glDepthFunc(GL_EQUAL);
- else if (flag & DRW_STATE_DEPTH_GREATER)
- glDepthFunc(GL_GREATER);
- }
- else {
- glDisable(GL_DEPTH_TEST);
- }
-
- /* Wire Width */
- if (flag & DRW_STATE_WIRE) {
- glLineWidth(1.0f);
- }
- else if (flag & DRW_STATE_WIRE_LARGE) {
- glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
- }
-
- /* Points Size */
- if (flag & DRW_STATE_POINT) {
- GPU_enable_program_point_size();
- glPointSize(5.0f);
- }
- else {
- GPU_disable_program_point_size();
- }
-
- /* Blending (all buffer) */
- if (flag & DRW_STATE_BLEND) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
- else {
- glDisable(GL_BLEND);
- }
-
- /* Line Stipple */
- if (flag & DRW_STATE_STIPPLE_2) {
- setlinestyle(2);
- }
- else if (flag & DRW_STATE_STIPPLE_3) {
- setlinestyle(3);
- }
- else if (flag & DRW_STATE_STIPPLE_4) {
- setlinestyle(4);
- }
- else {
- setlinestyle(0);
- }
-}
-
void DRW_draw_pass(DRWPass *pass)
{
/* Start fresh */
DST.shader = NULL;
DST.tex_bind_id = 0;
- set_state(pass->state);
+ set_state(pass->state, true);
BLI_listbase_clear(&DST.bound_texs);
for (DRWShadingGroup *shgroup = pass->shgroups.first; shgroup; shgroup = shgroup->next) {
@@ -1089,7 +1096,7 @@ void DRW_state_reset(void)
state |= DRW_STATE_WRITE_DEPTH;
state |= DRW_STATE_WRITE_COLOR;
state |= DRW_STATE_DEPTH_LESS;
- set_state(state);
+ set_state(state, true);
}
#else
@@ -1230,7 +1237,7 @@ void DRW_framebuffer_bind(struct GPUFrameBuffer *fb)
GPU_framebuffer_bind(fb);
}
-void DRW_framebuffer_clear(bool color, bool depth, float clear_col[4], float clear_depth)
+void DRW_framebuffer_clear(bool color, bool depth, bool stencil, float clear_col[4], float clear_depth)
{
if (color) {
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
@@ -1240,8 +1247,12 @@ void DRW_framebuffer_clear(bool color, bool depth, float clear_col[4], float cle
glDepthMask(GL_TRUE);
glClearDepth(clear_depth);
}
+ if (stencil) {
+ glStencilMask(0xFF);
+ }
glClear(((color) ? GL_COLOR_BUFFER_BIT : 0) |
- ((depth) ? GL_DEPTH_BUFFER_BIT : 0));
+ ((depth) ? GL_DEPTH_BUFFER_BIT : 0) |
+ ((stencil) ? GL_STENCIL_BUFFER_BIT : 0));
}
void DRW_framebuffer_texture_attach(struct GPUFrameBuffer *fb, GPUTexture *tex, int slot)
diff --git a/source/blender/draw/intern/draw_view.c b/source/blender/draw/intern/draw_view.c
index 4d813124118..747cc84a9cd 100644
--- a/source/blender/draw/intern/draw_view.c
+++ b/source/blender/draw/intern/draw_view.c
@@ -549,12 +549,13 @@ void DRW_draw_background(void)
/* Just to make sure */
glDepthMask(GL_TRUE);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glStencilMask(0xFF);
if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) {
/* Gradient background Color */
gpuMatrixBegin3D(); /* TODO: finish 2D API */
- glClear(GL_DEPTH_BUFFER_BIT);
+ glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
VertexFormat *format = immVertexFormat();
unsigned pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
@@ -583,7 +584,7 @@ void DRW_draw_background(void)
else {
/* Solid background Color */
UI_ThemeClearColorAlpha(TH_HIGH_GRAD, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
}
}
diff --git a/source/blender/draw/modes/edit_mesh_mode.c b/source/blender/draw/modes/edit_mesh_mode.c
index 40404b2daff..b0e1dc1d022 100644
--- a/source/blender/draw/modes/edit_mesh_mode.c
+++ b/source/blender/draw/modes/edit_mesh_mode.c
@@ -396,7 +396,7 @@ static void EDIT_MESH_draw_scene(void)
/* Render wires on a separate framebuffer */
DRW_framebuffer_bind(fbl->occlude_wire_fb);
- DRW_framebuffer_clear(true, true, clearcol, 1.0f);
+ DRW_framebuffer_clear(true, true, false, clearcol, 1.0f);
DRW_draw_pass(psl->normals);
DRW_draw_pass(psl->edit_face_occluded);
diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c
index ecfde38f5be..8cb09a4e14f 100644
--- a/source/blender/draw/modes/object_mode.c
+++ b/source/blender/draw/modes/object_mode.c
@@ -46,7 +46,8 @@
typedef struct OBJECT_PassList {
struct DRWPass *non_meshes;
struct DRWPass *ob_center;
- struct DRWPass *wire_outline;
+ struct DRWPass *outlines;
+ struct DRWPass *outlines_transp;
struct DRWPass *bone_solid;
struct DRWPass *bone_wire;
} OBJECT_PassList;
@@ -108,10 +109,48 @@ static DRWShadingGroup *camera_clip_points;
static DRWShadingGroup *camera_mist;
static DRWShadingGroup *camera_mist_points;
+/* Outlines */
+static DRWShadingGroup *outlines_active;
+static DRWShadingGroup *outlines_active_group;
+static DRWShadingGroup *outlines_select;
+static DRWShadingGroup *outlines_select_group;
+static DRWShadingGroup *outlines_transform;
+static DRWShadingGroup *outlines_transp_select;
+static DRWShadingGroup *outlines_transp_select_group;
+static DRWShadingGroup *outlines_transp_active;
+static DRWShadingGroup *outlines_transp_active_group;
+static DRWShadingGroup *outlines_transp_transform;
+
extern GlobalsUboStorage ts;
static OBJECT_Data *vedata;
+static struct GPUShader *outline_sh = NULL;
+
+extern char datatoc_object_occluded_outline_frag_glsl[];
+
+static void OBJECT_engine_init(void)
+{
+ if (!outline_sh) {
+ outline_sh = DRW_shader_create_3D(datatoc_object_occluded_outline_frag_glsl, NULL);
+ }
+}
+
+static void OBJECT_engine_free(void)
+{
+ if (outline_sh)
+ DRW_shader_free(outline_sh);
+}
+
+static DRWShadingGroup *shgroup_outline(DRWPass *pass, int state_flag, const float col[4], struct GPUShader *sh)
+{
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
+ DRW_shgroup_uniform_vec4(grp, "color", col, 1);
+ DRW_shgroup_state_set(grp, state_flag);
+
+ return grp;
+}
+
static void OBJECT_cache_init(void)
{
/* DRW_viewport_engine_data_get is rather slow, better not do it on every objects */
@@ -119,11 +158,38 @@ static void OBJECT_cache_init(void)
OBJECT_PassList *psl = vedata->psl;
{
- /* This pass can draw mesh outlines and/or fancy wireframe */
- /* Fancy wireframes are not meant to be occluded (without Z offset) */
- /* Outlines and Fancy Wires use the same VBO */
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND;
- psl->wire_outline = DRW_pass_create("Wire + Outlines Pass", state);
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_WIRE_LARGE;
+ psl->outlines = DRW_pass_create("Outlines Pass", state);
+
+ struct GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ /* Select */
+ outlines_select = shgroup_outline(psl->outlines, DRW_STATE_TEST_STENCIL_SELECT, ts.colorSelect, sh);
+ outlines_select_group = shgroup_outline(psl->outlines, DRW_STATE_TEST_STENCIL_SELECT, ts.colorGroupActive, sh);
+
+ /* Transform */
+ outlines_transform = shgroup_outline(psl->outlines, DRW_STATE_TEST_STENCIL_SELECT, ts.colorTransform, sh);
+
+ /* Active */
+ outlines_active = shgroup_outline(psl->outlines, DRW_STATE_TEST_STENCIL_ACTIVE, ts.colorActive, sh);
+ outlines_active_group = shgroup_outline(psl->outlines, DRW_STATE_TEST_STENCIL_ACTIVE, ts.colorGroupActive, sh);
+ }
+
+ {
+ /* FIXME doing a 2nd pass is suboptimal, but waiting for a nice outline solution it does the job*/
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_GREATER | DRW_STATE_WIRE_LARGE;
+ psl->outlines_transp = DRW_pass_create("See-through Outlines Pass", state);
+
+ /* Select */
+ outlines_transp_select = shgroup_outline(psl->outlines_transp, DRW_STATE_TEST_STENCIL_SELECT, ts.colorSelect, outline_sh);
+ outlines_transp_select_group = shgroup_outline(psl->outlines_transp, DRW_STATE_TEST_STENCIL_SELECT, ts.colorGroupActive, outline_sh);
+
+ /* Transform */
+ outlines_transp_transform = shgroup_outline(psl->outlines_transp, DRW_STATE_TEST_STENCIL_SELECT, ts.colorTransform, outline_sh);
+
+ /* Active */
+ outlines_transp_active = shgroup_outline(psl->outlines_transp, DRW_STATE_TEST_STENCIL_ACTIVE, ts.colorActive, outline_sh);
+ outlines_transp_active_group = shgroup_outline(psl->outlines_transp, DRW_STATE_TEST_STENCIL_ACTIVE, ts.colorGroupActive, outline_sh);
}
{
@@ -280,55 +346,6 @@ static void OBJECT_cache_init(void)
}
}
-static void DRW_shgroup_wire_outline(Object *ob, const bool do_wire, const bool do_outline)
-{
- struct GPUShader *sh;
- OBJECT_PassList *psl = vedata->psl;
- struct Batch *geom = DRW_cache_wire_outline_get(ob);
-
- float *color;
- DRW_object_wire_theme_get(ob, &color);
-
- bool is_perps = DRW_viewport_is_persp_get();
- static bool bTrue = true;
- static bool bFalse = false;
-
- /* Note (TODO) : this requires cache to be discarded on ortho/perp switch
- * It may be preferable (or not depending on performance implication)
- * to introduce a shader uniform switch */
- if (is_perps) {
- sh = GPU_shader_get_builtin_shader(GPU_SHADER_EDGES_FRONT_BACK_PERSP);
- }
- else {
- sh = GPU_shader_get_builtin_shader(GPU_SHADER_EDGES_FRONT_BACK_ORTHO);
- }
-
- if (do_wire) {
- bool *bFront = (do_wire) ? &bTrue : &bFalse;
- bool *bBack = (do_wire) ? &bTrue : &bFalse;
-
- DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->wire_outline);
- DRW_shgroup_state_set(grp, DRW_STATE_WIRE);
- DRW_shgroup_uniform_vec4(grp, "frontColor", color, 1);
- DRW_shgroup_uniform_vec4(grp, "backColor", color, 1);
- DRW_shgroup_uniform_bool(grp, "drawFront", bFront, 1);
- DRW_shgroup_uniform_bool(grp, "drawBack", bBack, 1);
- DRW_shgroup_uniform_bool(grp, "drawSilhouette", &bFalse, 1);
- DRW_shgroup_call_add(grp, geom, ob->obmat);
- }
-
- if (do_outline) {
- DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->wire_outline);
- DRW_shgroup_state_set(grp, DRW_STATE_WIRE_LARGE);
- DRW_shgroup_uniform_vec4(grp, "silhouetteColor", color, 1);
- DRW_shgroup_uniform_bool(grp, "drawFront", &bFalse, 1);
- DRW_shgroup_uniform_bool(grp, "drawBack", &bFalse, 1);
- DRW_shgroup_uniform_bool(grp, "drawSilhouette", &bTrue, 1);
-
- DRW_shgroup_call_add(grp, geom, ob->obmat);
- }
-}
-
static void DRW_shgroup_lamp(Object *ob)
{
Lamp *la = ob->data;
@@ -563,17 +580,38 @@ static void OBJECT_cache_populate(Object *ob)
const struct bContext *C = DRW_get_context();
Scene *scene = CTX_data_scene(C);
- CollectionEngineSettings *ces_mode_ob = BKE_object_collection_engine_get(ob, COLLECTION_MODE_OBJECT, "");
+ //CollectionEngineSettings *ces_mode_ob = BKE_object_collection_engine_get(ob, COLLECTION_MODE_OBJECT, "");
- bool do_wire = BKE_collection_engine_property_value_get_bool(ces_mode_ob, "show_wire");
- bool do_outlines = ((ob->base_flag & BASE_SELECTED) != 0) || do_wire;
+ //bool do_wire = BKE_collection_engine_property_value_get_bool(ces_mode_ob, "show_wire");
+ bool do_outlines = ((ob->base_flag & BASE_SELECTED) != 0);
switch (ob->type) {
case OB_MESH:
{
Object *obedit = scene->obedit;
+ int theme_id = DRW_object_wire_theme_get(ob, NULL);
if (ob != obedit) {
- DRW_shgroup_wire_outline(ob, do_wire, do_outlines);
+ if (do_outlines) {
+ struct Batch *geom = DRW_cache_wire_outline_get(ob);
+ switch (theme_id) {
+ case TH_ACTIVE:
+ DRW_shgroup_call_add(outlines_active, geom, ob->obmat);
+ DRW_shgroup_call_add(outlines_transp_active, geom, ob->obmat);
+ break;
+ case TH_SELECT:
+ DRW_shgroup_call_add(outlines_select, geom, ob->obmat);
+ DRW_shgroup_call_add(outlines_transp_select, geom, ob->obmat);
+ break;
+ case TH_GROUP_ACTIVE:
+ DRW_shgroup_call_add(outlines_select_group, geom, ob->obmat);
+ DRW_shgroup_call_add(outlines_transp_select_group, geom, ob->obmat);
+ break;
+ case TH_TRANSFORM:
+ DRW_shgroup_call_add(outlines_transform, geom, ob->obmat);
+ DRW_shgroup_call_add(outlines_transp_transform, geom, ob->obmat);
+ break;
+ }
+ }
}
}
break;
@@ -612,9 +650,10 @@ static void OBJECT_draw_scene(void)
OBJECT_Data *ved = DRW_viewport_engine_data_get("ObjectMode");
OBJECT_PassList *psl = ved->psl;
+ DRW_draw_pass(psl->outlines_transp);
+ DRW_draw_pass(psl->outlines);
DRW_draw_pass(psl->bone_wire);
DRW_draw_pass(psl->bone_solid);
- DRW_draw_pass(psl->wire_outline);
DRW_draw_pass(psl->non_meshes);
DRW_draw_pass(psl->ob_center);
}
@@ -629,8 +668,8 @@ void OBJECT_collection_settings_create(CollectionEngineSettings *ces)
DrawEngineType draw_engine_object_type = {
NULL, NULL,
N_("ObjectMode"),
- NULL,
- NULL,
+ &OBJECT_engine_init,
+ &OBJECT_engine_free,
&OBJECT_cache_init,
&OBJECT_cache_populate,
NULL,
diff --git a/source/blender/draw/modes/shaders/object_occluded_outline_frag.glsl b/source/blender/draw/modes/shaders/object_occluded_outline_frag.glsl
new file mode 100644
index 00000000000..cd9f43e6c4e
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_occluded_outline_frag.glsl
@@ -0,0 +1,15 @@
+
+out vec4 FragColor;
+
+uniform vec4 color;
+
+void main()
+{
+ /* Checkerboard pattern */
+ /* 0 | 1
+ * 1 | 0 */
+ if ((((int(gl_FragCoord.x) & 0x1) + (int(gl_FragCoord.y) & 0x1)) & 0x1) != 0)
+ discard;
+
+ FragColor = vec4(color.rgb * 0.5, 1.0);
+}