[Bf-blender-cvs] [b57ec68fcf8] temp-gpencil-drw-engine: GPencil: Rework Layer Blending

Clément Foucault noreply at git.blender.org
Fri Jun 28 17:41:35 CEST 2019


Commit: b57ec68fcf83bd30bc3bfaa4763b1987ff291d43
Author: Clément Foucault
Date:   Fri Jun 28 17:41:23 2019 +0200
Branches: temp-gpencil-drw-engine
https://developer.blender.org/rBb57ec68fcf83bd30bc3bfaa4763b1987ff291d43

GPencil: Rework Layer Blending

Layer blending is now done by the hardware and uses dual source blending.
This patch breaks a few things:
- The depth of the blended strokes are not merged anymore.
- The layer masking is broken.
Theses will be for a different patch.

I'm not sure if overlay fading (based on alpha) is handle correctly but it
does fade to neutral.

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

M	source/blender/draw/engines/gpencil/gpencil_engine.c
M	source/blender/draw/engines/gpencil/shaders/gpencil_blend_frag.glsl

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

diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index 26b4b4cc1c1..10f50f14675 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -540,18 +540,13 @@ void GPENCIL_cache_init(void *vedata)
 
     /* blend layers pass */
     psl->blend_layers_pass = DRW_pass_create("GPencil Blend Layers Pass",
-                                             DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA |
-                                                 DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+                                             DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM);
     DRWShadingGroup *blend_shgrp = DRW_shgroup_create(e_data.gpencil_blend_fullscreen_sh,
                                                       psl->blend_layers_pass);
     DRW_shgroup_call(blend_shgrp, quad, NULL);
     DRW_shgroup_uniform_texture_ref(blend_shgrp, "strokeColor", &stl->g_data->temp_color_a_tx);
     DRW_shgroup_uniform_texture_ref(blend_shgrp, "strokeDepth", &stl->g_data->temp_depth_a_tx);
-    DRW_shgroup_uniform_texture_ref(blend_shgrp, "blendColor", &stl->g_data->temp_color_fx_tx);
-    DRW_shgroup_uniform_texture_ref(blend_shgrp, "blendDepth", &stl->g_data->temp_depth_fx_tx);
     DRW_shgroup_uniform_int(blend_shgrp, "mode", &stl->storage->blend_mode, 1);
-    DRW_shgroup_uniform_int(blend_shgrp, "mask_layer", &stl->storage->mask_layer, 1);
-    DRW_shgroup_uniform_int(mix_shgrp, "tonemapping", &stl->storage->tonemapping, 1);
 
     /* create effects passes */
     if (!stl->storage->simplify_fx) {
@@ -1036,15 +1031,15 @@ void GPENCIL_draw_scene(void *ved)
             init_shgrp = array_elm->init_shgrp;
             end_shgrp = array_elm->end_shgrp;
 
+            if (stl->storage->multisamples > 0) {
+              GPU_framebuffer_bind(fbl->multisample_fb);
+            }
+            else {
+              GPU_framebuffer_bind(fbl->temp_a_fb);
+            }
+
             if (array_elm->mode == eGplBlendMode_Regular) {
               /* Draw current group in MSAA texture or final texture. */
-              if (stl->storage->multisamples > 0) {
-                GPU_framebuffer_bind(fbl->multisample_fb);
-              }
-              else {
-                GPU_framebuffer_bind(fbl->temp_a_fb);
-              }
-
               gpencil_draw_pass_range(
                   fbl, stl, psl, txl, fbl->temp_a_fb, ob, gpd, init_shgrp, end_shgrp);
             }
@@ -1053,16 +1048,17 @@ void GPENCIL_draw_scene(void *ved)
               GPU_framebuffer_bind(blend_fb);
               GPU_framebuffer_clear_color_depth_stencil(blend_fb, clearcol, 1.0f, 0x0);
               gpencil_draw_pass_range(
-                  fbl, stl, psl, txl, fbl->temp_a_fb, ob, gpd, init_shgrp, end_shgrp);
+                  fbl, stl, psl, txl, fbl->temp_fx_fb, ob, gpd, init_shgrp, end_shgrp);
 
               /* Draw Blended texture over MSAA texture */
-              GPU_framebuffer_bind(fbl->multisample_fb);
-              // TODO: How resolve the Blend?
-              // TODO: Mask Layers?
-              // Do I need use the blend layer pass/fragment (blend_layers_pass)
-              // stl->g_data->input_depth_tx = txl->multisample_depth;
-              // stl->g_data->input_color_tx = txl->multisample_color;
-              // DRW_draw_pass(psl->mix_screen_noblend_pass); // general copy of buffers
+              if (stl->storage->multisamples > 0) {
+                GPU_framebuffer_bind(fbl->multisample_fb);
+              }
+              else {
+                GPU_framebuffer_bind(fbl->temp_a_fb);
+              }
+              stl->storage->blend_mode = array_elm->mode;
+              DRW_draw_pass(psl->blend_layers_pass);  // general copy of buffers
             }
           }
 
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_blend_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_blend_frag.glsl
index 85dee4390a5..c118e05a4a0 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_blend_frag.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_blend_frag.glsl
@@ -1,17 +1,7 @@
-in vec4 uvcoordsvar;
-
-out vec4 FragColor;
 
 uniform sampler2D strokeColor;
 uniform sampler2D strokeDepth;
-uniform sampler2D blendColor;
-uniform sampler2D blendDepth;
 uniform int mode;
-uniform int mask_layer;
-uniform int tonemapping;
-
-#define ON 1
-#define OFF 0
 
 #define MODE_REGULAR 0
 #define MODE_OVERLAY 1
@@ -20,138 +10,67 @@ uniform int tonemapping;
 #define MODE_MULTIPLY 4
 #define MODE_DIVIDE 5
 
-float overlay_color(float a, float b)
-{
-  float rtn;
-  if (a < 0.5) {
-    rtn = 2.0 * a * b;
-  }
-  else {
-    rtn = 1.0 - 2.0 * (1.0 - a) * (1.0 - b);
-  }
-
-  return rtn;
-}
+/* Blend equation is : FragColor0 + FragColor1 * DstColor */
+layout(location = 0, index = 0) out vec4 FragColor0;
+layout(location = 0, index = 1) out vec4 FragColor1;
 
-vec4 get_blend_color(int mode, vec4 src_color, vec4 mix_color)
+void main()
 {
-  vec4 outcolor;
-
-  if (mix_color.a == 0) {
-    return src_color;
-  }
+  ivec2 texel = ivec2(gl_FragCoord.xy);
+  vec4 src = texelFetch(strokeColor, texel, 0).rgba;
+  gl_FragDepth = texelFetch(strokeDepth, texel, 0).r;
 
   switch (mode) {
-    case MODE_REGULAR: {
-      /* premult */
-      src_color = vec4(vec3(src_color.rgb / src_color.a), src_color.a);
-      mix_color = vec4(vec3(mix_color.rgb / mix_color.a), mix_color.a);
-
-      outcolor = vec4(mix(src_color.rgb, mix_color.rgb, mix_color.a), src_color.a);
+    case MODE_REGULAR:
+      FragColor0 = src;
+      FragColor1 = 1.0 - vec4(src.a);
       break;
-    }
-    case MODE_OVERLAY: {
-      src_color = vec4(vec3(src_color.rgb / src_color.a), src_color.a);
-      mix_color = vec4(vec3(mix_color.rgb / mix_color.a), mix_color.a);
-
-      mix_color.rgb = mix(src_color.rgb, mix_color.rgb, mix_color.a);
-      outcolor.r = overlay_color(src_color.r, mix_color.r);
-      outcolor.g = overlay_color(src_color.g, mix_color.g);
-      outcolor.b = overlay_color(src_color.b, mix_color.b);
-      outcolor.a = src_color.a;
+    case MODE_OVERLAY:
+      /* Original overlay is :
+       * overlay = (a < 0.5) ? (2 * a * b) : (1 - 2 * (1 - a) * (1 - b));
+       * But we are using dual source blending. So we need to rewrite it as a function of b (DST).
+       * overlay = 1 - 2 * (1 - a) * (1 - b);
+       * overlay = 1 + (2 * a - 2) * (1 - b);
+       * overlay = 1 + (2 * a - 2) - (2 * a - 2) * b;
+       * overlay = (2 * a - 1) + (2 - 2 * a) * b;
+       *
+       * With the right coefficient, we can get the 2 * a * b from the same equation.
+       * q0 = 0, q1 = -1;
+       * overlay = (2 * a - 1) * q0 + (2 * q0 - 2 * q1 * a) * b;
+       * overlay = 2 * a * b;
+       * */
+      src.rgb = mix(vec3(0.5), src.rgb, src.a);
+      vec3 q0 = vec3(greaterThanEqual(src.rgb, vec3(0.5)));
+      vec3 q1 = ((q0 - 0.5) * 2.0);
+      vec3 src2 = 2.0 * src.rgb;
+      FragColor0.rgb = src2 * q0 - q0;
+      FragColor0.a = 0.0;
+      FragColor1.rgb = 2.0 * q0 - src2 * q1;
+      FragColor1.a = 1.0;
       break;
-    }
-    case MODE_ADD: {
-      mix_color.rgb = mix(src_color.rgb, mix_color.rgb, mix_color.a);
-      outcolor = src_color + mix_color;
-      outcolor.a = src_color.a;
+    case MODE_ADD:
+      FragColor0.rgb = src.rgb * src.a;
+      FragColor0.a = 0.0;
+      FragColor1 = vec4(1.0);
       break;
-    }
-    case MODE_SUB: {
-      mix_color.rgb = mix(src_color.rgb, mix_color.rgb, mix_color.a);
-      outcolor = src_color - mix_color;
-      outcolor.a = clamp(src_color.a - mix_color.a, 0.0, 1.0);
+    case MODE_SUB:
+      FragColor0.rgb = -src.rgb * src.a;
+      FragColor0.a = 0.0;
+      FragColor1 = vec4(1.0);
       break;
-    }
-    case MODE_MULTIPLY: {
-      src_color = vec4(vec3(src_color.rgb / src_color.a), src_color.a);
-      mix_color = vec4(vec3(mix_color.rgb / mix_color.a), mix_color.a);
-
-      mix_color.rgb = mix(src_color.rgb, mix_color.rgb, mix_color.a);
-      outcolor = src_color * mix_color;
-      outcolor.a = src_color.a;
+    case MODE_MULTIPLY:
+      FragColor0 = vec4(0.0);
+      FragColor1.rgb = mix(vec3(1.0), src.rgb, src.a);
+      FragColor1.a = 1.0;
       break;
-    }
-    case MODE_DIVIDE: {
-      mix_color.rgb = mix(src_color.rgb, mix_color.rgb, mix_color.a);
-      outcolor = src_color / mix_color;
-      outcolor.a = src_color.a;
+    case MODE_DIVIDE:
+      FragColor0 = vec4(0.0);
+      FragColor1.rgb = 1.0 / mix(vec3(1.0), src.rgb, src.a);
+      FragColor1.a = 1.0;
       break;
-    }
-    default: {
-      outcolor = mix_color;
-      outcolor.a = src_color.a;
+    default:
+      FragColor0 = vec4(0.0);
+      FragColor1 = vec4(1.0);
       break;
-    }
-  }
-  return clamp(outcolor, 0.0, 1.0);
-}
-
-float linearrgb_to_srgb(float c)
-{
-  if (c < 0.0031308) {
-    return (c < 0.0) ? 0.0 : c * 12.92;
-  }
-  else {
-    return 1.055 * pow(c, 1.0 / 2.4) - 0.055;
-  }
-}
-
-vec4 tone(vec4 stroke_color)
-{
-  if (tonemapping == 1) {
-    vec4 color = vec4(0, 0, 0, stroke_color.a);
-    color.r = linearrgb_to_srgb(stroke_color.r);
-    color.g = linearrgb_to_srgb(stroke_color.g);
-    color.b = linearrgb_to_srgb(stroke_color.b);
-    return color;
-  }
-  else {
-    return stroke_color;
-  }
-}
-
-void main()
-{
-  vec4 outcolor;
-  ivec2 uv = ivec2(gl_FragCoord.xy);
-  vec4 stroke_color = texelFetch(strokeColor, uv, 0).rgba;
-  float stroke_depth = texelFetch(strokeDepth, uv, 0).r;
-
-  vec4 mix_color = texelFetch(blendColor, uv, 0).rgba;
-  float mix_depth = texelFetch(blendDepth, uv, 0).r;
-
-  if (stroke_color.a > 0) {
-    if (mix_color.a > 0) {
-      /* apply blend mode */
-      FragColor = get_blend_color(mode, stroke_color, mix_color);
-    }
-    else {
-      FragColor = stroke_color;
-    }
-    gl_FragDepth = min(stroke_depth, mix_depth);
   }
-  else {
-    if (mask_layer == ON) {
-      discard;
-    }
-    else {
-      /* if not using mask, return mix color */
-      FragColor = mix_color;
-      gl_FragDepth = mix_depth;
-    }
-  }
-
-  /* apply tone mapping */
-  FragColor = tone(FragColor);
 }



More information about the Bf-blender-cvs mailing list