[Bf-blender-cvs] [3ffa0452af9] blender-v2.91-release: Fix T67832: Camera Background Images View Transform

Jeroen Bakker noreply at git.blender.org
Wed Nov 4 14:14:13 CET 2020


Commit: 3ffa0452af9ac0a08b321e9504c9e080ab1ce47d
Author: Jeroen Bakker
Date:   Tue Nov 3 14:39:50 2020 +0100
Branches: blender-v2.91-release
https://developer.blender.org/rB3ffa0452af9ac0a08b321e9504c9e080ab1ce47d

Fix T67832: Camera Background Images View Transform

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

===================================================================

M	source/blender/draw/engines/overlay/overlay_engine.c
M	source/blender/draw/engines/overlay/overlay_image.c
M	source/blender/draw/engines/overlay/overlay_private.h
M	source/blender/draw/intern/DRW_render.h
M	source/blender/draw/intern/draw_manager_exec.c
M	source/blender/gpu/GPU_state.h
M	source/blender/gpu/opengl/gl_state.cc

===================================================================

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;



More information about the Bf-blender-cvs mailing list