diff options
author | Jeroen Bakker <jbakker> | 2019-10-05 18:18:41 +0300 |
---|---|---|
committer | Jeroen Bakker <j.bakker@atmind.nl> | 2019-10-05 18:18:53 +0300 |
commit | 0bdf4e2f2d1cd9538ac0196db8c302c21d49c860 (patch) | |
tree | 85dcecffae9e8c0fa17335dea117f1c2ff0e599b /source/blender | |
parent | 629a1c1639cb82d8cf421f02bd7fd12f5f3415c6 (diff) |
Show Background Image Beneath Transparent Objects (Cycles only)
Camera background images were not shown under transparent objects.
This patch performs an alpha under for background images for cycles.
In order to see the difference the Film transparency needs to be turned on.
Note that workbench and EEVEE still needs to be adapted as they don't
write store alpha value in the viewport.
Side note. This implementation is already an improvement of the current behavior, what users are requesting. (Show background images underneath cycles viewport rendering.) It is clear that this patch still needs to be extended to workbench and eevee. For now that should be marked as a known limitation.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D5437
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/draw/intern/draw_manager.c | 20 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_view.c | 38 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_view.h | 1 | ||||
-rw-r--r-- | source/blender/draw/modes/object_mode.c | 104 | ||||
-rw-r--r-- | source/blender/draw/modes/shaders/object_camera_image_frag.glsl | 2 |
5 files changed, 109 insertions, 56 deletions
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 6387cecc01f..66cf921d47d 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -1171,7 +1171,7 @@ static void drw_engines_cache_finish(void) MEM_freeN(DST.vedata_array); } -static void drw_engines_draw_background(void) +static bool drw_engines_draw_background(void) { for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { DrawEngineType *engine = link->data; @@ -1185,10 +1185,20 @@ static void drw_engines_draw_background(void) DRW_stats_group_end(); PROFILE_END_UPDATE(data->background_time, stime); - return; + return true; } } + /* No draw engines draw the background. We clear the background. + * We draw the background after drawing of the scene so the camera background + * images can be drawn using ALPHA Under. Otherwise the background always + * interferred with the alpha blending */ + DRW_clear_background(); + return false; +} + +static void drw_draw_background_alpha_under(void) +{ /* No draw_background found, doing default background */ const bool do_alpha_checker = !DRW_state_draw_background(); DRW_draw_background(do_alpha_checker); @@ -1685,7 +1695,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, DRW_hair_update(); - drw_engines_draw_background(); + const bool background_drawn = drw_engines_draw_background(); GPU_framebuffer_bind(DST.default_framebuffer); @@ -1696,6 +1706,10 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, drw_engines_draw_scene(); + if (!background_drawn) { + drw_draw_background_alpha_under(); + } + /* Fix 3D view being "laggy" on macos and win+nvidia. (See T56996, T61474) */ GPU_flush(); diff --git a/source/blender/draw/intern/draw_view.c b/source/blender/draw/intern/draw_view.c index 7aa2e007f79..58643eb12a8 100644 --- a/source/blender/draw/intern/draw_view.c +++ b/source/blender/draw/intern/draw_view.c @@ -41,11 +41,9 @@ #include "BKE_object.h" #include "BKE_paint.h" -#include "DRW_render.h" - #include "view3d_intern.h" -#include "draw_view.h" +#include "draw_manager.h" /* ******************** region info ***************** */ @@ -60,18 +58,17 @@ void DRW_draw_region_info(void) } /* ************************* Background ************************** */ +void DRW_clear_background() +{ + GPU_clear_color(0.0, 0.0, 0.0, 0.0); + GPU_clear(GPU_COLOR_BIT | GPU_DEPTH_BIT | GPU_STENCIL_BIT); +} void DRW_draw_background(bool do_alpha_checker) { - /* Just to make sure */ - glDepthMask(GL_TRUE); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glStencilMask(0xFF); - + drw_state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA_UNDER_PREMUL); if (do_alpha_checker) { /* Transparent render, do alpha checker. */ - GPU_depth_test(false); - GPU_matrix_push(); GPU_matrix_identity_set(); GPU_matrix_identity_projection_set(); @@ -79,18 +76,11 @@ void DRW_draw_background(bool do_alpha_checker) imm_draw_box_checker_2d(-1.0f, -1.0f, 1.0f, 1.0f); GPU_matrix_pop(); - - GPU_clear(GPU_DEPTH_BIT | GPU_STENCIL_BIT); - - GPU_depth_test(true); } - else if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) { + else { float m[4][4]; unit_m4(m); - /* Gradient background Color */ - GPU_depth_test(false); - GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); uint color = GPU_vertformat_attr_add( @@ -103,8 +93,8 @@ void DRW_draw_background(bool do_alpha_checker) immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR_DITHER); - UI_GetThemeColor3ubv(TH_BACK_GRAD, col_lo); UI_GetThemeColor3ubv(TH_BACK, col_hi); + UI_GetThemeColor3ubv(UI_GetThemeValue(TH_SHOW_BACK_GRAD) ? TH_BACK_GRAD : TH_BACK, col_lo); immBegin(GPU_PRIM_TRI_FAN, 4); immAttr3ubv(color, col_lo); @@ -119,16 +109,6 @@ void DRW_draw_background(bool do_alpha_checker) immUnbindProgram(); GPU_matrix_pop(); - - GPU_clear(GPU_DEPTH_BIT | GPU_STENCIL_BIT); - - GPU_depth_test(true); - } - else { - /* Solid background Color */ - UI_ThemeClearColorAlpha(TH_BACK, 1.0f); - - GPU_clear(GPU_COLOR_BIT | GPU_DEPTH_BIT | GPU_STENCIL_BIT); } } diff --git a/source/blender/draw/intern/draw_view.h b/source/blender/draw/intern/draw_view.h index 715c3c0d40c..7be186f1c72 100644 --- a/source/blender/draw/intern/draw_view.h +++ b/source/blender/draw/intern/draw_view.h @@ -24,6 +24,7 @@ #define __DRAW_VIEW_H__ void DRW_draw_region_info(void); +void DRW_clear_background(void); void DRW_draw_background(bool do_alpha_checker); void DRW_draw_cursor(void); void DRW_draw_gizmo_3d(void); diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c index 05a915185df..ec19c731e96 100644 --- a/source/blender/draw/modes/object_mode.c +++ b/source/blender/draw/modes/object_mode.c @@ -122,8 +122,9 @@ typedef struct OBJECT_PassList { struct DRWPass *bone_axes[2]; struct DRWPass *particle; struct DRWPass *lightprobes; - struct DRWPass *camera_images_back; - struct DRWPass *camera_images_front; + struct DRWPass *camera_images_back_alpha_under; + struct DRWPass *camera_images_back_alpha_over; + struct DRWPass *camera_images_front_alpha_over; } OBJECT_PassList; typedef struct OBJECT_FramebufferList { @@ -991,13 +992,19 @@ static void DRW_shgroup_empty_image(OBJECT_Shaders *sh_data, } } -/* Draw Camera Background Images */ +/* -------------------------------------------------------------------- */ +/** \name Camera Background Images + * \{ */ typedef struct CameraEngineData { DrawData dd; ListBase bg_data; } CameraEngineData; + typedef struct CameraEngineBGData { + CameraBGImage *camera_image; + GPUTexture *texture; float transform_mat[4][4]; + bool premultiplied; } CameraEngineBGData; static void camera_engine_data_free(DrawData *dd) @@ -1032,6 +1039,26 @@ static void camera_background_images_stereo_setup(Scene *scene, iuser->flag &= ~IMA_SHOW_STEREO; } } +static void camera_background_images_add_shgroup(DRWPass *pass, + CameraEngineBGData *bg_data, + GPUShader *shader, + GPUBatch *batch) +{ + CameraBGImage *camera_image = bg_data->camera_image; + DRWShadingGroup *grp = DRW_shgroup_create(shader, pass); + + DRW_shgroup_uniform_float_copy( + grp, "depth", camera_image->flag & CAM_BGIMG_FLAG_FOREGROUND ? 0.000001f : 0.999999f); + DRW_shgroup_uniform_float_copy(grp, "alpha", camera_image->alpha); + DRW_shgroup_uniform_texture(grp, "image", bg_data->texture); + DRW_shgroup_uniform_bool_copy(grp, "imagePremultiplied", bg_data->premultiplied); + DRW_shgroup_uniform_float_copy( + grp, "flipX", (camera_image->flag & CAM_BGIMG_FLAG_FLIP_X) ? -1.0 : 1.0); + DRW_shgroup_uniform_float_copy( + grp, "flipY", (camera_image->flag & CAM_BGIMG_FLAG_FLIP_Y) ? -1.0 : 1.0); + DRW_shgroup_uniform_mat4(grp, "TransformMat", bg_data->transform_mat); + DRW_shgroup_call(grp, batch, NULL); +} static void DRW_shgroup_camera_background_images(OBJECT_Shaders *sh_data, OBJECT_PassList *psl, @@ -1255,25 +1282,46 @@ static void DRW_shgroup_camera_background_images(OBJECT_Shaders *sh_data, scale_m4, uv2img_space); - DRWPass *pass = (bgpic->flag & CAM_BGIMG_FLAG_FOREGROUND) ? psl->camera_images_front : - psl->camera_images_back; - GPUShader *shader = DRW_state_do_color_management() ? sh_data->object_camera_image_cm : - sh_data->object_camera_image; - DRWShadingGroup *grp = DRW_shgroup_create(shader, pass); + /* Keep the references so we can reverse the loop */ + bg_data->camera_image = bgpic; + bg_data->texture = tex; + bg_data->premultiplied = premultiplied; + } - DRW_shgroup_uniform_float_copy( - grp, "depth", (bgpic->flag & CAM_BGIMG_FLAG_FOREGROUND) ? 0.000001 : 0.999999); - DRW_shgroup_uniform_float_copy(grp, "alpha", bgpic->alpha); - DRW_shgroup_uniform_texture(grp, "image", tex); - DRW_shgroup_uniform_bool_copy(grp, "imagePremultiplied", premultiplied); + /* Mark the rest bg_data's to be reused in the next drawing call */ + LinkData *last_node = list_node ? list_node->prev : camera_engine_data->bg_data.last; + while (list_node != NULL) { + CameraEngineBGData *bg_data = (CameraEngineBGData *)list_node->data; + bg_data->texture = NULL; + bg_data->camera_image = NULL; + list_node = list_node->next; + } - DRW_shgroup_uniform_float_copy( - grp, "flipX", (bgpic->flag & CAM_BGIMG_FLAG_FLIP_X) ? -1.0 : 1.0); - DRW_shgroup_uniform_float_copy( - grp, "flipY", (bgpic->flag & CAM_BGIMG_FLAG_FLIP_Y) ? -1.0 : 1.0); - DRW_shgroup_uniform_mat4(grp, "TransformMat", bg_data->transform_mat); + GPUShader *shader = DRW_state_do_color_management() ? sh_data->object_camera_image_cm : + sh_data->object_camera_image; + /* loop 1: camera images alpha under */ + for (list_node = last_node; list_node; list_node = list_node->prev) { + CameraEngineBGData *bg_data = (CameraEngineBGData *)list_node->data; + CameraBGImage *camera_image = bg_data->camera_image; + if ((camera_image->flag & CAM_BGIMG_FLAG_FOREGROUND) == 0) { + camera_background_images_add_shgroup( + psl->camera_images_back_alpha_under, bg_data, shader, batch); + } + } - DRW_shgroup_call(grp, batch, NULL); + /* loop 2: camera images alpha over */ + for (list_node = camera_engine_data->bg_data.first; list_node; list_node = list_node->next) { + CameraEngineBGData *bg_data = (CameraEngineBGData *)list_node->data; + CameraBGImage *camera_image = bg_data->camera_image; + if (camera_image == NULL) { + break; + } + camera_background_images_add_shgroup((camera_image->flag & CAM_BGIMG_FLAG_FOREGROUND) ? + psl->camera_images_front_alpha_over : + psl->camera_images_back_alpha_over, + bg_data, + shader, + batch); } } } @@ -1286,6 +1334,7 @@ static void camera_background_images_free_textures(void) } BLI_freelistN(&e_data.movie_clips); } +/* \} */ static void OBJECT_cache_init(void *vedata) { @@ -1427,9 +1476,15 @@ static void OBJECT_cache_init(void *vedata) /* Camera background images */ { - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ALPHA; - psl->camera_images_back = DRW_pass_create("Camera Images Back", state); - psl->camera_images_front = DRW_pass_create("Camera Images Front", state); + psl->camera_images_back_alpha_over = DRW_pass_create( + "Camera Images Back Over", + DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ALPHA_PREMUL); + psl->camera_images_back_alpha_under = DRW_pass_create( + "Camera Images Back Under", + DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_GREATER | DRW_STATE_BLEND_ALPHA_UNDER_PREMUL); + psl->camera_images_front_alpha_over = DRW_pass_create( + "Camera Images Front Over", + DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ALPHA_PREMUL); } for (int i = 0; i < 2; i++) { @@ -3666,7 +3721,8 @@ static void OBJECT_draw_scene(void *vedata) float clearcol[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - DRW_draw_pass(psl->camera_images_back); + DRW_draw_pass(psl->camera_images_back_alpha_under); + DRW_draw_pass(psl->camera_images_back_alpha_over); /* Don't draw Transparent passes in MSAA buffer. */ // DRW_draw_pass(psl->bone_envelope); /* Never drawn in Object mode currently. */ @@ -3774,7 +3830,7 @@ static void OBJECT_draw_scene(void *vedata) batch_camera_path_free(&stl->g_data->sgl_ghost.camera_path); - DRW_draw_pass(psl->camera_images_front); + DRW_draw_pass(psl->camera_images_front_alpha_over); camera_background_images_free_textures(); DRW_draw_pass(psl->ob_center); diff --git a/source/blender/draw/modes/shaders/object_camera_image_frag.glsl b/source/blender/draw/modes/shaders/object_camera_image_frag.glsl index 5d8ad3c79ea..7804ebdb8c9 100644 --- a/source/blender/draw/modes/shaders/object_camera_image_frag.glsl +++ b/source/blender/draw/modes/shaders/object_camera_image_frag.glsl @@ -19,5 +19,7 @@ void main() #endif color.a *= alpha; + color.rgb *= color.a; + fragColor = color; } |