diff options
-rw-r--r-- | source/blender/draw/engines/overlay/overlay_engine.c | 5 | ||||
-rw-r--r-- | source/blender/draw/engines/overlay/overlay_image.c | 40 | ||||
-rw-r--r-- | source/blender/draw/engines/overlay/overlay_private.h | 3 | ||||
-rw-r--r-- | source/blender/draw/intern/DRW_render.h | 2 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_extract_mesh.c | 12 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager_exec.c | 3 | ||||
-rw-r--r-- | source/blender/gpu/GPU_state.h | 1 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_state.cc | 7 |
8 files changed, 63 insertions, 10 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_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh.c index ff1efccd507..7766ce906b8 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]; diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index 21bcaa2d2b2..749e9e6bafb 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -206,6 +206,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; |