[Bf-blender-cvs] [2494b982dd7] greasepencil-refactor: GPencil: Refactor: Improve stroke color mixing support

Clément Foucault noreply at git.blender.org
Thu Dec 12 02:24:29 CET 2019


Commit: 2494b982dd76a1ca9385e3f60c295bac8e7614ac
Author: Clément Foucault
Date:   Wed Dec 11 20:18:42 2019 +0100
Branches: greasepencil-refactor
https://developer.blender.org/rB2494b982dd76a1ca9385e3f60c295bac8e7614ac

GPencil: Refactor: Improve stroke color mixing support

This is a more simple implementation. Blending is done in a way that it
supports the stencil functionallity out of the box. It is compatible with
vertex paint, stroke material color and texture color without exclusivity.

UI need to be reworked to remove the stencil option.

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

M	source/blender/draw/engines/gpencil/gpencil_cache_utils.c
M	source/blender/draw/engines/gpencil/gpencil_draw_data.c
M	source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
M	source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl
M	source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl

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

diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
index d72cf35ce47..ea244feae8d 100644
--- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
@@ -60,7 +60,7 @@ GPENCIL_tLayer *gpencil_layer_cache_add_new(GPENCIL_PrivateData *pd,
   bGPdata *gpd = (bGPdata *)ob->data;
   GPENCIL_tLayer *tgp_layer = BLI_memblock_alloc(pd->gp_layer_pool);
 
-  DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA;
+  DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA_PREMUL;
   /* TODO better 3D mode. */
   if (GPENCIL_3D_DRAWMODE(ob, gpd)) {
     state |= DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_data.c b/source/blender/draw/engines/gpencil/gpencil_draw_data.c
index 116d237d7e1..a57593ecb8b 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_data.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_data.c
@@ -118,11 +118,13 @@ GPENCIL_MaterialPool *gpencil_material_pool_create(GPENCIL_PrivateData *pd, Obje
       mat_data->flag |= GP_STROKE_TEXTURE_USE;
       mat_data->flag |= premul ? GP_STROKE_TEXTURE_PREMUL : 0;
       copy_v4_v4(mat_data->stroke_color, gp_style->stroke_rgba);
+      mat_data->stroke_texture_mix = 1.0f - gp_style->mix_stroke_factor;
     }
     else /* if (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_SOLID) */ {
       pool->tex_stroke[mat_id] = NULL;
       mat_data->flag &= ~GP_STROKE_TEXTURE_USE;
       copy_v4_v4(mat_data->stroke_color, gp_style->stroke_rgba);
+      mat_data->stroke_texture_mix = 0.0f;
     }
 
     /* Fill Style */
@@ -137,24 +139,21 @@ GPENCIL_MaterialPool *gpencil_material_pool_create(GPENCIL_PrivateData *pd, Obje
                                gp_style->texture_scale,
                                gp_style->texture_angle,
                                mat_data->fill_uv_transform);
-      copy_v4_fl4(mat_data->fill_color, 1.0f, 1.0f, 1.0f, gp_style->texture_opacity);
-      if (gp_style->flag & GP_STYLE_FILL_TEX_MIX) {
-        copy_v4_v4(mat_data->fill_mix_color, gp_style->mix_rgba);
-      }
-      else {
-        copy_v4_fl(mat_data->fill_mix_color, 0.0f);
-      }
+      copy_v4_v4(mat_data->fill_color, gp_style->mix_rgba);
+      mat_data->fill_texture_mix = 1.0f - gp_style->texture_opacity;
     }
     else if (gp_style->fill_style == GP_STYLE_FILL_STYLE_TEXTURE) {
       /* TODO implement gradient as a texture. */
       pool->tex_fill[mat_id] = NULL;
       mat_data->flag &= ~GP_FILL_TEXTURE_USE;
       copy_v4_v4(mat_data->fill_color, gp_style->fill_rgba);
+      mat_data->fill_texture_mix = 0.0f;
     }
     else /* if (gp_style->fill_style == GP_STYLE_FILL_STYLE_SOLID) */ {
       pool->tex_fill[mat_id] = NULL;
       mat_data->flag &= ~GP_FILL_TEXTURE_USE;
       copy_v4_v4(mat_data->fill_color, gp_style->fill_rgba);
+      mat_data->fill_texture_mix = 0.0f;
     }
   }
 
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
index 0a84ab87d16..fc83885bb26 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
@@ -7,9 +7,9 @@ struct gpMaterial {
   vec4 fill_uv_rot_scale;
   vec4 fill_uv_offset;
   /* Put float/int at the end to avoid padding error */
-  float stroke_uv_factor;
+  float stroke_texture_mix;
+  float stroke_u_scale;
   float fill_texture_mix;
-  float fill_uv_y_scale;
   int flag;
   /* Please ensure 16 byte alignment (multiple of vec4). */
 };
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl
index 96a5573578b..03cda90a2e4 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl
@@ -2,27 +2,36 @@
 uniform sampler2D gpFillTexture;
 uniform sampler2D gpStrokeTexture;
 
-in vec4 finalColor;
+in vec4 finalColorMul;
+in vec4 finalColorAdd;
 in vec2 finalUvs;
 flat in int matFlag;
-flat in vec4 finalMixColor;
 
 out vec4 fragColor;
 
 void main()
 {
+  vec4 col;
   if (GP_FLAG_TEST(matFlag, GP_STROKE_TEXTURE_USE)) {
     bool premul = GP_FLAG_TEST(matFlag, GP_STROKE_TEXTURE_PREMUL);
-    fragColor = texture_read_as_srgb(gpStrokeTexture, premul, finalUvs);
+    col = texture_read_as_srgb(gpStrokeTexture, premul, finalUvs);
+    col.rgb *= col.a;
   }
   else if (GP_FLAG_TEST(matFlag, GP_FILL_TEXTURE_USE)) {
     bool use_clip = GP_FLAG_TEST(matFlag, GP_FILL_TEXTURE_CLIP);
     vec2 uvs = (use_clip) ? clamp(finalUvs, 0.0, 1.0) : finalUvs;
     bool premul = GP_FLAG_TEST(matFlag, GP_FILL_TEXTURE_PREMUL);
-    fragColor = texture_read_as_srgb(gpFillTexture, premul, uvs) * finalColor;
-    fragColor = fragColor + (1.0 - fragColor.a) * finalMixColor;
+    col = texture_read_as_srgb(gpFillTexture, premul, uvs);
+    col.rgb *= col.a;
   }
-  else {
-    fragColor = finalColor;
+  else /* SOLID */ {
+    col = vec4(1.0);
+  }
+  /* Composite all other colors on top of texture color.
+   * Everything is premult by col.a to have the stencil effect. */
+  fragColor = col * finalColorMul + col.a * finalColorAdd;
+
+  if (fragColor.a < 0.001) {
+    discard;
   }
 }
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl
index 26fbbe2fafd..e082b87ad62 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl
@@ -28,10 +28,10 @@ in vec4 uv2;
 in vec4 col1;
 in vec4 col2;
 
-out vec4 finalColor;
+out vec4 finalColorMul;
+out vec4 finalColorAdd;
 out vec2 finalUvs;
 flat out int matFlag;
-flat out vec4 finalMixColor;
 
 void discard_vert()
 {
@@ -71,6 +71,29 @@ vec2 safe_normalize(vec2 v)
   }
 }
 
+void stroke_color_output(vec4 stroke_col, vec4 vert_col, float vert_strength, float mix_tex)
+{
+  /* Mix stroke with vertex color. */
+  vec4 mixed_col;
+  mixed_col.rgb = mix(stroke_col.rgb, vert_col.rgb, vert_col.a);
+  mixed_col.a = clamp(stroke_col.a * vert_strength, 0.0, 1.0);
+  /**
+   * This is what the fragment shader looks like.
+   * out = col * finalColorMul + col.a * finalColorAdd.
+   * finalColorMul is how much of the texture color to keep.
+   * finalColorAdd is how much of the mixed color to add.
+   * Note that we never add alpha. This is to keep the texture act as a stencil.
+   * We do however, modulate the alpha (reduce it).
+   **/
+  /* We add the mixed color. This is 100% mix (no texture visible). */
+  finalColorMul = vec4(mixed_col.aaa, mixed_col.a);
+  finalColorAdd = vec4(mixed_col.rgb * mixed_col.a, 0.0);
+  /* Then we blend according to the texture mix factor.
+   * Note that we keep the alpha modulation. */
+  finalColorMul.rgb *= mix_tex;
+  finalColorAdd.rgb *= 1.0 - mix_tex;
+}
+
 void stroke_vertex()
 {
   /* Enpoints, we discard the vertices. */
@@ -132,15 +155,14 @@ void stroke_vertex()
 
   gl_Position.xy += miter * sizeViewportInv.xy * thickness;
 
-  vec4 vert_col = (x == 0.0) ? col1 : col2;
-  float vert_strength = (x == 0.0) ? strength1 : strength2;
-
   int m = int(ma1.x);
 
+  vec4 vert_col = (x == 0.0) ? col1 : col2;
+  float vert_strength = (x == 0.0) ? strength1 : strength2;
   vec4 stroke_col = materials[m].stroke_color;
-  finalColor.rgb = mix(stroke_col.rgb, vert_col.rgb, vert_col.a);
-  finalColor.a = clamp(stroke_col.a * vert_strength, 0.0, 1.0);
-  finalMixColor = vec4(0.0);
+  float mix_tex = materials[m].stroke_texture_mix;
+
+  stroke_color_output(stroke_col, vert_col, vert_strength, mix_tex);
 
   matFlag = materials[m].flag & ~GP_FILL_FLAGS;
 
@@ -163,8 +185,17 @@ void fill_vertex()
 
   int m = int(ma1.x);
 
-  finalColor = materials[m].fill_color;
-  finalMixColor = materials[m].fill_mix_color;
+  vec4 fill_col = materials[m].fill_color;
+  float mix_tex = materials[m].fill_texture_mix;
+
+  /* We add the mixed color. This is 100% mix (no texture visible). */
+  finalColorMul = vec4(fill_col.aaa, fill_col.a);
+  finalColorAdd = vec4(fill_col.rgb * fill_col.a, 0.0);
+  /* Then we blend according to the texture mix factor.
+   * Note that we keep the alpha modulation. */
+  finalColorMul.rgb *= mix_tex;
+  finalColorAdd.rgb *= 1.0 - mix_tex;
+
   matFlag = materials[m].flag & GP_FILL_FLAGS;
 
   vec2 loc = materials[m].fill_uv_offset.xy;



More information about the Bf-blender-cvs mailing list