[Bf-blender-cvs] [d56f1a5f446] greasepencil-refactor: GPencil: Refactor: Add Rim FX

Clément Foucault noreply at git.blender.org
Thu Dec 19 01:31:03 CET 2019


Commit: d56f1a5f446cad754382b98bafb621a34c0199a1
Author: Clément Foucault
Date:   Wed Dec 18 23:08:57 2019 +0100
Branches: greasepencil-refactor
https://developer.blender.org/rBd56f1a5f446cad754382b98bafb621a34c0199a1

GPencil: Refactor: Add Rim FX

Nothing has changed functionality wise.

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

M	source/blender/draw/engines/gpencil/gpencil_engine.c
M	source/blender/draw/engines/gpencil/gpencil_engine.h
M	source/blender/draw/engines/gpencil/gpencil_shader.c
M	source/blender/draw/engines/gpencil/gpencil_shader_fx.c
M	source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl

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

diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index 39fab08dae8..4fd6ca82a54 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -364,6 +364,7 @@ static void GPENCIL_engine_free(void)
   DRW_SHADER_FREE_SAFE(e_data.fx_composite_sh);
   DRW_SHADER_FREE_SAFE(e_data.fx_glow_sh);
   DRW_SHADER_FREE_SAFE(e_data.fx_pixel_sh);
+  DRW_SHADER_FREE_SAFE(e_data.fx_rim_sh);
   DRW_SHADER_FREE_SAFE(e_data.fx_shadow_sh);
 
   DRW_TEXTURE_FREE_SAFE(e_data.gpencil_blank_texture);
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h
index 2df8688f0d1..be5be0f2861 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.h
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.h
@@ -475,6 +475,7 @@ typedef struct GPENCIL_e_data {
   struct GPUShader *fx_blur_sh;
   struct GPUShader *fx_glow_sh;
   struct GPUShader *fx_pixel_sh;
+  struct GPUShader *fx_rim_sh;
   struct GPUShader *fx_shadow_sh;
 
   /* general drawing shaders */
@@ -718,6 +719,7 @@ struct GPUShader *GPENCIL_shader_fx_colorize_get(GPENCIL_e_data *e_data);
 struct GPUShader *GPENCIL_shader_fx_composite_get(GPENCIL_e_data *e_data);
 struct GPUShader *GPENCIL_shader_fx_glow_get(GPENCIL_e_data *e_data);
 struct GPUShader *GPENCIL_shader_fx_pixelize_get(GPENCIL_e_data *e_data);
+struct GPUShader *GPENCIL_shader_fx_rim_get(GPENCIL_e_data *e_data);
 struct GPUShader *GPENCIL_shader_fx_shadow_get(GPENCIL_e_data *e_data);
 
 /* main functions */
diff --git a/source/blender/draw/engines/gpencil/gpencil_shader.c b/source/blender/draw/engines/gpencil/gpencil_shader.c
index 60bfdf9ccce..8f29c288cd8 100644
--- a/source/blender/draw/engines/gpencil/gpencil_shader.c
+++ b/source/blender/draw/engines/gpencil/gpencil_shader.c
@@ -141,6 +141,31 @@ struct GPUShader *GPENCIL_shader_fx_colorize_get(GPENCIL_e_data *e_data)
   return e_data->fx_colorize_sh;
 }
 
+struct GPUShader *GPENCIL_shader_fx_rim_get(GPENCIL_e_data *e_data)
+{
+  if (!e_data->fx_rim_sh) {
+    e_data->fx_rim_sh = GPU_shader_create_from_arrays({
+        .vert =
+            (const char *[]){
+                datatoc_common_fullscreen_vert_glsl,
+                NULL,
+            },
+        .frag =
+            (const char *[]){
+                datatoc_gpencil_common_lib_glsl,
+                datatoc_gpencil_vfx_frag_glsl,
+                NULL,
+            },
+        .defs =
+            (const char *[]){
+                "#define RIM\n",
+                NULL,
+            },
+    });
+  }
+  return e_data->fx_rim_sh;
+}
+
 struct GPUShader *GPENCIL_shader_fx_composite_get(GPENCIL_e_data *e_data)
 {
   if (!e_data->fx_composite_sh) {
diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
index fe33113bd6f..95f69b1467e 100644
--- a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
+++ b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
@@ -1135,6 +1135,78 @@ static void gpencil_vfx_colorize(ColorizeShaderFxData *fx, Object *UNUSED(ob), g
   DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
 }
 
+static void gpencil_vfx_rim(RimShaderFxData *fx, Object *ob, gpIterVfxData *iter)
+{
+  DRWShadingGroup *grp;
+
+  float winmat[4][4], persmat[4][4];
+  float offset[2] = {fx->offset[0], fx->offset[1]};
+  float blur_size[2] = {fx->blur[0], fx->blur[1]};
+  DRW_view_winmat_get(NULL, winmat, false);
+  DRW_view_persmat_get(NULL, persmat, false);
+  const float *vp_size = DRW_viewport_size_get();
+  const float *vp_size_inv = DRW_viewport_invert_size_get();
+
+  const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->obmat[3]));
+
+  /* Modify by distance to camera and object scale. */
+  float world_pixel_scale = 1.0f / 2000.0f;
+  float scale = mat4_to_scale(ob->obmat);
+  float distance_factor = (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w;
+  mul_v2_fl(offset, distance_factor);
+  mul_v2_v2(offset, vp_size_inv);
+  mul_v2_fl(blur_size, distance_factor);
+
+  GPUShader *sh = GPENCIL_shader_fx_rim_get(&en_data);
+
+  DRWState state = DRW_STATE_WRITE_COLOR;
+  grp = gpencil_vfx_pass_create("Fx Rim H", state, iter, sh);
+  DRW_shgroup_uniform_vec2_copy(grp, "blurDir", (float[2]){blur_size[0] * vp_size_inv[0], 0.0f});
+  DRW_shgroup_uniform_vec2_copy(grp, "uvOffset", offset);
+  DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, blur_size[0])));
+  DRW_shgroup_uniform_vec3_copy(grp, "maskColor", fx->mask_rgb);
+  DRW_shgroup_uniform_bool_copy(grp, "isFirstPass", true);
+  DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+
+  switch (fx->mode) {
+    case eShaderFxRimMode_Normal:
+      state |= DRW_STATE_BLEND_ALPHA_PREMUL;
+      break;
+    case eShaderFxRimMode_Add:
+      state |= DRW_STATE_BLEND_ADD_FULL;
+      break;
+    case eShaderFxRimMode_Subtract:
+      state |= DRW_STATE_BLEND_SUB;
+      break;
+    case eShaderFxRimMode_Multiply:
+    case eShaderFxRimMode_Divide:
+    case eShaderFxRimMode_Overlay:
+      state |= DRW_STATE_BLEND_MUL;
+      break;
+  }
+
+  zero_v2(offset);
+
+  grp = gpencil_vfx_pass_create("Fx Rim V", state, iter, sh);
+  DRW_shgroup_uniform_vec2_copy(grp, "blurDir", (float[2]){0.0f, blur_size[1] * vp_size_inv[1]});
+  DRW_shgroup_uniform_vec2_copy(grp, "uvOffset", offset);
+  DRW_shgroup_uniform_vec3_copy(grp, "rimColor", fx->rim_rgb);
+  DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, blur_size[1])));
+  DRW_shgroup_uniform_int_copy(grp, "blendMode", fx->mode);
+  DRW_shgroup_uniform_bool_copy(grp, "isFirstPass", false);
+  DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+
+  if (fx->mode == eShaderFxRimMode_Overlay) {
+    /* We cannot do custom blending on MultiTarget framebuffers.
+     * Workaround by doing 2 passes. */
+    grp = DRW_shgroup_create_sub(grp);
+    DRW_shgroup_state_disable(grp, DRW_STATE_BLEND_MUL);
+    DRW_shgroup_state_enable(grp, DRW_STATE_BLEND_ADD_FULL);
+    DRW_shgroup_uniform_int_copy(grp, "blendMode", 999);
+    DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+  }
+}
+
 static void gpencil_vfx_pixelize(PixelShaderFxData *fx, Object *ob, gpIterVfxData *iter)
 {
   DRWShadingGroup *grp;
@@ -1372,6 +1444,7 @@ void gpencil_vfx_cache_populate(GPENCIL_Data *vedata, Object *ob, GPENCIL_tObjec
           gpencil_vfx_pixelize((PixelShaderFxData *)fx, ob, &iter);
           break;
         case eShaderFxType_Rim:
+          gpencil_vfx_rim((RimShaderFxData *)fx, ob, &iter);
           break;
         case eShaderFxType_Shadow:
           gpencil_vfx_shadow((ShadowShaderFxData *)fx, ob, &iter);
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl
index 6e790acff9f..a7a3c4a6a27 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl
@@ -159,6 +159,56 @@ void main()
   }
 }
 
+#elif defined(RIM)
+
+uniform vec2 blurDir;
+uniform vec2 uvOffset;
+uniform vec3 rimColor;
+uniform vec3 maskColor;
+uniform int sampCount;
+uniform int blendMode;
+uniform bool isFirstPass;
+
+void main()
+{
+  /* Blur revealage buffer. */
+  fragRevealage = vec4(0.0);
+  float weight_accum = 0.0;
+  for (int i = -sampCount; i <= sampCount; i++) {
+    float x = float(i) / float(sampCount);
+    float weight = gaussian_weight(x);
+    weight_accum += weight;
+    vec2 uv = uvcoordsvar.xy + blurDir * x + uvOffset;
+    vec3 col = texture(revealBuf, uv).rgb;
+    if (any(not(equal(vec2(0.0), floor(uv))))) {
+      col = vec3(0.0);
+    }
+    fragRevealage.rgb += col * weight;
+  }
+  fragRevealage /= weight_accum;
+
+  if (isFirstPass) {
+    /* In first pass we copy the reveal buffer. This let us do alpha masking in second pass. */
+    fragColor = texture(revealBuf, uvcoordsvar.xy);
+    /* Also add the masked color to the reveal buffer. */
+    vec3 col = texture(colorBuf, uvcoordsvar.xy).rgb;
+    if (all(lessThan(abs(col - maskColor), vec3(0.05)))) {
+      fragColor = vec4(1.0);
+    }
+  }
+  else {
+    /* Premult by foreground alpha (alpha mask). */
+    float mask = 1.0 - clamp(dot(vec3(0.333334), texture(colorBuf, uvcoordsvar.xy).rgb), 0.0, 1.0);
+
+    /* fragRevealage is blurred shadow. */
+    float rim = clamp(dot(vec3(0.333334), fragRevealage.rgb), 0.0, 1.0);
+
+    vec4 color = vec4(rimColor, 1.0);
+
+    blend_mode_output(blendMode, color, rim * mask, fragColor, fragRevealage);
+  }
+}
+
 #elif defined(SHADOW)
 
 uniform vec4 shadowColor;



More information about the Bf-blender-cvs mailing list