From 7a7f2949406764a17cfcb77345dbec7989c13e37 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Tue, 3 Nov 2020 10:55:18 +0100 Subject: Fix T81775: Object Disappears During Texture Painting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue was that the `tris_per_mat` are not created when the first batch is drawn during select operator and then is not created when needed by the workbench pass since they are not tracked by mesh_buffer_cache_create_requested. This change will create the `tris_per_mat` just in case they are needed later. Solution by Clément Foucault Differential Revision: https://developer.blender.org/D9430 --- source/blender/draw/intern/draw_cache_extract_mesh.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh.c index 56633a6fecc..ce3a89ae45c 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.c +++ b/source/blender/draw/intern/draw_cache_extract_mesh.c @@ -902,12 +902,16 @@ static void extract_tris_finish(const MeshRenderData *mr, MeshExtract_Tri_Data *data = _data; GPU_indexbuf_build_in_place(&data->elb, ibo); - /* HACK: Create ibo sub-ranges and assign them to each #GPUBatch. */ - /* The `surface_per_mat` tests are there when object shading type is set to Wire or Bounds. In - * these cases there isn't a surface per material. */ - if (mr->use_final_mesh && cache->surface_per_mat && cache->surface_per_mat[0]) { + /* Create ibo sub-ranges. Always do this to avoid error when the standard surface batch + * is created before the surfaces-per-material. */ + if (mr->use_final_mesh && cache->final.tris_per_mat) { MeshBufferCache *mbc = &cache->final; for (int i = 0; i < mr->mat_len; i++) { + /* Theses IBOs have not been queried yet but we create them just in case they are needed + * later since they are not tracked by mesh_buffer_cache_create_requested(). */ + if (mbc->tris_per_mat[i] == NULL) { + mbc->tris_per_mat[i] = GPU_indexbuf_calloc(); + } /* Multiply by 3 because these are triangle indices. */ const int mat_start = data->tri_mat_start[i]; const int mat_end = data->tri_mat_end[i]; -- cgit v1.2.3 From 3ffa0452af9ac0a08b321e9504c9e080ab1ce47d Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Tue, 3 Nov 2020 14:39:50 +0100 Subject: Fix T67832: Camera Background Images View Transform MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch will apply the view transform when a movie clip is used as camera background image. It does this by rendering the image in the color buffer when it needs the view transform. For other images it uses the overlay buffer. Reviewed By: Clément Foucault Differential Revision: https://developer.blender.org/D7067 --- .../blender/draw/engines/overlay/overlay_engine.c | 5 +++ .../blender/draw/engines/overlay/overlay_image.c | 40 ++++++++++++++++++---- .../blender/draw/engines/overlay/overlay_private.h | 3 ++ source/blender/draw/intern/DRW_render.h | 2 ++ source/blender/draw/intern/draw_manager_exec.c | 3 ++ source/blender/gpu/GPU_state.h | 1 + source/blender/gpu/opengl/gl_state.cc | 7 ++++ 7 files changed, 55 insertions(+), 6 deletions(-) diff --git a/source/blender/draw/engines/overlay/overlay_engine.c b/source/blender/draw/engines/overlay/overlay_engine.c index 30b39e5d5e1..e49b2e45580 100644 --- a/source/blender/draw/engines/overlay/overlay_engine.c +++ b/source/blender/draw/engines/overlay/overlay_engine.c @@ -509,6 +509,11 @@ static void OVERLAY_draw_scene(void *vedata) OVERLAY_FramebufferList *fbl = data->fbl; DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + /* Needs to be done first as it modifies the scene color and depth buffer. */ + if (!pd->is_image_editor) { + OVERLAY_image_scene_background_draw(vedata); + } + if (DRW_state_is_fbo()) { const float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f}; GPU_framebuffer_bind(dfbl->overlay_only_fb); diff --git a/source/blender/draw/engines/overlay/overlay_image.c b/source/blender/draw/engines/overlay/overlay_image.c index 08cddf4e185..9695f8616a5 100644 --- a/source/blender/draw/engines/overlay/overlay_image.c +++ b/source/blender/draw/engines/overlay/overlay_image.c @@ -57,6 +57,8 @@ void OVERLAY_image_cache_init(OVERLAY_Data *vedata) state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_GREATER | DRW_STATE_BLEND_ALPHA_PREMUL; DRW_PASS_CREATE(psl->image_background_ps, state); + state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA_UNDER_PREMUL; + DRW_PASS_CREATE(psl->image_background_scene_ps, state); state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS; DRW_PASS_CREATE(psl->image_empties_ps, state | pd->clipping_state); @@ -68,6 +70,7 @@ void OVERLAY_image_cache_init(OVERLAY_Data *vedata) state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA_PREMUL; DRW_PASS_CREATE(psl->image_empties_front_ps, state); DRW_PASS_CREATE(psl->image_foreground_ps, state); + DRW_PASS_CREATE(psl->image_foreground_scene_ps, state); } static void overlay_image_calc_aspect(Image *ima, const int size[2], float r_image_aspect[2]) @@ -136,7 +139,8 @@ static struct GPUTexture *image_camera_background_texture_get(CameraBGImage *bgp const DRWContextState *draw_ctx, OVERLAY_PrivateData *pd, float *r_aspect, - bool *r_use_alpha_premult) + bool *r_use_alpha_premult, + bool *r_use_view_transform) { void *lock; Image *image = bgpic->ima; @@ -148,6 +152,7 @@ static struct GPUTexture *image_camera_background_texture_get(CameraBGImage *bgp int width, height; int ctime = (int)DEG_get_ctime(draw_ctx->depsgraph); *r_use_alpha_premult = false; + *r_use_view_transform = false; switch (bgpic->source) { case CAM_BGIMG_SOURCE_IMAGE: @@ -155,6 +160,7 @@ static struct GPUTexture *image_camera_background_texture_get(CameraBGImage *bgp return NULL; } *r_use_alpha_premult = (image->alpha_mode == IMA_ALPHA_PREMUL); + *r_use_view_transform = (image->flag & IMA_VIEW_AS_RENDER) != 0; BKE_image_user_frame_calc(image, iuser, ctime); if (image->source == IMA_SRC_SEQUENCE && !(iuser->flag & IMA_USER_FRAME_IN_RANGE)) { @@ -183,7 +189,6 @@ static struct GPUTexture *image_camera_background_texture_get(CameraBGImage *bgp aspect_x = bgpic->ima->aspx; aspect_y = bgpic->ima->aspy; - break; case CAM_BGIMG_SOURCE_MOVIE: @@ -208,6 +213,7 @@ static struct GPUTexture *image_camera_background_texture_get(CameraBGImage *bgp aspect_x = clip->aspx; aspect_y = clip->aspy; + *r_use_view_transform = true; BKE_movieclip_get_size(clip, &bgpic->cuser, &width, &height); @@ -328,21 +334,27 @@ void OVERLAY_image_camera_cache_populate(OVERLAY_Data *vedata, Object *ob) float aspect = 1.0; bool use_alpha_premult; + bool use_view_transform = false; float mat[4][4]; /* retrieve the image we want to show, continue to next when no image could be found */ GPUTexture *tex = image_camera_background_texture_get( - bgpic, draw_ctx, pd, &aspect, &use_alpha_premult); + bgpic, draw_ctx, pd, &aspect, &use_alpha_premult, &use_view_transform); if (tex) { image_camera_background_matrix_get(cam, bgpic, draw_ctx, aspect, mat); mul_m4_m4m4(mat, modelmat, mat); const bool is_foreground = (bgpic->flag & CAM_BGIMG_FLAG_FOREGROUND) != 0; + /* Alpha is clamped just below 1.0 to fix background images to intefere with foreground + * images. Without this a background image with 1.0 will be rendered on top of a transparent + * foreground image due to the differnet blending modes they use. */ + const float color_premult_alpha[4] = {1.0f, 1.0f, 1.0f, MIN2(bgpic->alpha, 0.999999)}; - const float color_premult_alpha[4] = {1.0f, 1.0f, 1.0f, bgpic->alpha}; - - DRWPass *pass = is_foreground ? psl->image_foreground_ps : psl->image_background_ps; + DRWPass *pass = is_foreground ? (use_view_transform ? psl->image_foreground_scene_ps : + psl->image_foreground_ps) : + (use_view_transform ? psl->image_background_scene_ps : + psl->image_background_ps); GPUShader *sh = OVERLAY_shader_image(); DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); @@ -449,6 +461,22 @@ void OVERLAY_image_cache_finish(OVERLAY_Data *vedata) DRW_pass_sort_shgroup_z(psl->image_empties_back_ps); } +/* This function draws images that needs the view transform applied. + * It draws these images directly into the scene color buffer. */ +void OVERLAY_image_scene_background_draw(OVERLAY_Data *vedata) +{ + OVERLAY_PassList *psl = vedata->psl; + + if (DRW_state_is_fbo() && (!DRW_pass_is_empty(psl->image_background_scene_ps) || + !DRW_pass_is_empty(psl->image_foreground_scene_ps))) { + const DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + GPU_framebuffer_bind(dfbl->default_fb); + + DRW_draw_pass(psl->image_background_scene_ps); + DRW_draw_pass(psl->image_foreground_scene_ps); + } +} + void OVERLAY_image_background_draw(OVERLAY_Data *vedata) { OVERLAY_PassList *psl = vedata->psl; diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h index ef7a2db476c..d5ba0a5423f 100644 --- a/source/blender/draw/engines/overlay/overlay_private.h +++ b/source/blender/draw/engines/overlay/overlay_private.h @@ -103,11 +103,13 @@ typedef struct OVERLAY_PassList { DRWPass *fade_ps[2]; DRWPass *grid_ps; DRWPass *image_background_ps; + DRWPass *image_background_scene_ps; DRWPass *image_empties_ps; DRWPass *image_empties_back_ps; DRWPass *image_empties_blend_ps; DRWPass *image_empties_front_ps; DRWPass *image_foreground_ps; + DRWPass *image_foreground_scene_ps; DRWPass *metaball_ps[2]; DRWPass *motion_paths_ps; DRWPass *outlines_prepass_ps; @@ -592,6 +594,7 @@ void OVERLAY_image_empty_cache_populate(OVERLAY_Data *vedata, Object *ob); void OVERLAY_image_cache_finish(OVERLAY_Data *vedata); void OVERLAY_image_draw(OVERLAY_Data *vedata); void OVERLAY_image_background_draw(OVERLAY_Data *vedata); +void OVERLAY_image_scene_background_draw(OVERLAY_Data *vedata); void OVERLAY_image_in_front_draw(OVERLAY_Data *vedata); void OVERLAY_metaball_cache_init(OVERLAY_Data *vedata); diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index 6f40e04ab7e..336e6e75659 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -347,6 +347,8 @@ typedef enum { /** Use dual source blending. WARNING: Only one color buffer allowed. */ DRW_STATE_BLEND_CUSTOM = (9 << 11), DRW_STATE_LOGIC_INVERT = (10 << 11), + DRW_STATE_BLEND_ALPHA_UNDER_PREMUL = (11 << 11), + DRW_STATE_IN_FRONT_SELECT = (1 << 27), DRW_STATE_SHADOW_OFFSET = (1 << 28), diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index 808b5cc675b..8cf96251e84 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -203,6 +203,9 @@ void drw_state_set(DRWState state) case DRW_STATE_LOGIC_INVERT: blend = GPU_BLEND_INVERT; break; + case DRW_STATE_BLEND_ALPHA_UNDER_PREMUL: + blend = GPU_BLEND_ALPHA_UNDER_PREMUL; + break; default: blend = GPU_BLEND_NONE; break; diff --git a/source/blender/gpu/GPU_state.h b/source/blender/gpu/GPU_state.h index b7bea4b0a08..f5a1ccbc40b 100644 --- a/source/blender/gpu/GPU_state.h +++ b/source/blender/gpu/GPU_state.h @@ -71,6 +71,7 @@ typedef enum eGPUBlend { /** Custom blend parameters using dual source blending : SRC0 + SRC1 * DST * NOTE: Can only be used with _ONE_ Draw Buffer and shader needs to be specialized. */ GPU_BLEND_CUSTOM, + GPU_BLEND_ALPHA_UNDER_PREMUL, } eGPUBlend; typedef enum eGPUDepthTest { diff --git a/source/blender/gpu/opengl/gl_state.cc b/source/blender/gpu/opengl/gl_state.cc index 27c9b501add..3a474da8b8e 100644 --- a/source/blender/gpu/opengl/gl_state.cc +++ b/source/blender/gpu/opengl/gl_state.cc @@ -421,6 +421,13 @@ void GLStateManager::set_blend(const eGPUBlend value) dst_alpha = GL_SRC_ALPHA; break; } + case GPU_BLEND_ALPHA_UNDER_PREMUL: { + src_rgb = GL_ONE_MINUS_DST_ALPHA; + dst_rgb = GL_ONE; + src_alpha = GL_ONE_MINUS_DST_ALPHA; + dst_alpha = GL_ONE; + break; + } case GPU_BLEND_CUSTOM: { src_rgb = GL_ONE; dst_rgb = GL_SRC1_COLOR; -- cgit v1.2.3