[Bf-blender-cvs] [f2bc524e644] greasepencil-refactor: GPencil: Refactor: Add Pixelize effect

Clément Foucault noreply at git.blender.org
Wed Dec 18 03:14:30 CET 2019


Commit: f2bc524e644a6831952a7952e6c433ebc57eed03
Author: Clément Foucault
Date:   Tue Dec 17 17:02:05 2019 +0100
Branches: greasepencil-refactor
https://developer.blender.org/rBf2bc524e644a6831952a7952e6c433ebc57eed03

GPencil: Refactor: Add Pixelize effect

Bonus: the pixelize effect use the center of the object as pixelization
center. This improves stability of the effect.

We also use a 2pass downsampling to reduce the flickering.

The pixel size is now fixed in world space and dependant of object scale
and distance to camera.

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

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 418e0944140..aea3d37ca16 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -359,8 +359,9 @@ static void GPENCIL_engine_free(void)
   DRW_SHADER_FREE_SAFE(e_data.layer_mask_sh);
   DRW_SHADER_FREE_SAFE(e_data.depth_merge_sh);
 
-  DRW_SHADER_FREE_SAFE(e_data.fx_blur_sh);
   DRW_SHADER_FREE_SAFE(e_data.fx_composite_sh);
+  DRW_SHADER_FREE_SAFE(e_data.fx_blur_sh);
+  DRW_SHADER_FREE_SAFE(e_data.fx_pixel_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 ad0ce84fb56..9c3fc0d041a 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.h
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.h
@@ -468,6 +468,7 @@ typedef struct GPENCIL_e_data {
   struct GPUShader *depth_merge_sh;
   /* Effects. */
   struct GPUShader *fx_blur_sh;
+  struct GPUShader *fx_pixel_sh;
   struct GPUShader *fx_composite_sh;
 
   /* general drawing shaders */
@@ -708,6 +709,7 @@ struct GPUShader *GPENCIL_shader_layer_mask_get(GPENCIL_e_data *e_data);
 struct GPUShader *GPENCIL_shader_depth_merge_get(GPENCIL_e_data *e_data);
 struct GPUShader *GPENCIL_shader_fx_composite_get(GPENCIL_e_data *e_data);
 struct GPUShader *GPENCIL_shader_fx_blur_get(GPENCIL_e_data *e_data);
+struct GPUShader *GPENCIL_shader_fx_pixelize_get(GPENCIL_e_data *e_data);
 
 /* main functions */
 void GPENCIL_engine_init(void *vedata);
diff --git a/source/blender/draw/engines/gpencil/gpencil_shader.c b/source/blender/draw/engines/gpencil/gpencil_shader.c
index b98819e06fb..618c44143da 100644
--- a/source/blender/draw/engines/gpencil/gpencil_shader.c
+++ b/source/blender/draw/engines/gpencil/gpencil_shader.c
@@ -128,4 +128,13 @@ struct GPUShader *GPENCIL_shader_fx_blur_get(GPENCIL_e_data *e_data)
                                                       "#define BLUR\n");
   }
   return e_data->fx_blur_sh;
-}
\ No newline at end of file
+}
+
+struct GPUShader *GPENCIL_shader_fx_pixelize_get(GPENCIL_e_data *e_data)
+{
+  if (!e_data->fx_pixel_sh) {
+    e_data->fx_pixel_sh = DRW_shader_create_fullscreen(datatoc_gpencil_vfx_frag_glsl,
+                                                       "#define PIXELIZE\n");
+  }
+  return e_data->fx_pixel_sh;
+}
diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
index a06868a1096..031e00bd4a7 100644
--- a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
+++ b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
@@ -1120,6 +1120,60 @@ static void gpencil_vfx_blur(BlurShaderFxData *fx, Object *UNUSED(ob), gpIterVfx
   DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
 }
 
+static void gpencil_vfx_pixelize(PixelShaderFxData *fx, Object *ob, gpIterVfxData *iter)
+{
+  DRWShadingGroup *grp;
+
+  float persmat[4][4], winmat[4][4], ob_center[3], pixsize_uniform[2];
+  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();
+  float pixel_size[2] = {fx->size[0], fx->size[1]};
+  mul_v2_v2(pixel_size, vp_size_inv);
+
+  /* Fixed pixelisation center from object center. */
+  const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->obmat[3]));
+  mul_v3_m4v3(ob_center, persmat, ob->obmat[3]);
+  mul_v3_fl(ob_center, 1.0f / w);
+
+  /* Convert to uvs. */
+  mul_v2_fl(ob_center, 0.5f);
+  add_v2_fl(ob_center, 0.5f);
+
+  /* Modify by distance to camera and object scale. */
+  float world_pixel_scale = 1.0f / 2000.0f;
+  float scale = mat4_to_scale(ob->obmat);
+  mul_v2_fl(pixel_size, (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w);
+
+  /* Center to texel */
+  madd_v2_v2fl(ob_center, pixel_size, -0.5f);
+
+  GPUShader *sh = GPENCIL_shader_fx_pixelize_get(&en_data);
+
+  DRWState state = DRW_STATE_WRITE_COLOR;
+
+  /* Only if pixelated effect is bigger than 1px. */
+  if (pixel_size[0] > vp_size_inv[0]) {
+    copy_v2_fl2(pixsize_uniform, pixel_size[0], vp_size_inv[1]);
+    grp = gpencil_vfx_pass_create("Fx Pixelize X", state, iter, sh);
+    DRW_shgroup_uniform_vec2_copy(grp, "targetPixelSize", pixsize_uniform);
+    DRW_shgroup_uniform_vec2_copy(grp, "targetPixelOffset", ob_center);
+    DRW_shgroup_uniform_vec2_copy(grp, "accumOffset", (float[2]){pixel_size[0], 0.0f});
+    DRW_shgroup_uniform_int_copy(grp, "sampCount", (pixel_size[0] / vp_size_inv[0] > 3.0) ? 2 : 1);
+    DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+  }
+
+  if (pixel_size[1] > vp_size_inv[1]) {
+    copy_v2_fl2(pixsize_uniform, vp_size_inv[0], pixel_size[1]);
+    grp = gpencil_vfx_pass_create("Fx Pixelize Y", state, iter, sh);
+    DRW_shgroup_uniform_vec2_copy(grp, "targetPixelSize", pixsize_uniform);
+    DRW_shgroup_uniform_vec2_copy(grp, "accumOffset", (float[2]){0.0f, pixel_size[1]});
+    DRW_shgroup_uniform_int_copy(grp, "sampCount", (pixel_size[1] / vp_size_inv[1] > 3.0) ? 2 : 1);
+    DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+  }
+}
+
 void gpencil_vfx_cache_populate(GPENCIL_Data *vedata, Object *ob, GPENCIL_tObject *tgp_ob)
 {
   bGPdata *gpd = (bGPdata *)ob->data;
@@ -1150,6 +1204,7 @@ void gpencil_vfx_cache_populate(GPENCIL_Data *vedata, Object *ob, GPENCIL_tObjec
         case eShaderFxType_Light:
           break;
         case eShaderFxType_Pixel:
+          gpencil_vfx_pixelize((PixelShaderFxData *)fx, ob, &iter);
           break;
         case eShaderFxType_Rim:
           break;
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 74102f9e550..6588e3339ab 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl
@@ -52,12 +52,39 @@ void main()
     float x = float(i) / float(sampCount);
     float weight = gaussian_weight(x);
     weight_accum += weight;
-    fragColor.rgb += texture(colorBuf, uvcoordsvar.xy - ofs * x).rgb * weight;
-    fragRevealage.rgb += texture(revealBuf, uvcoordsvar.xy - ofs * x).rgb * weight;
+    vec2 uv = uvcoordsvar.xy + ofs * x;
+    fragColor.rgb += texture(colorBuf, uv).rgb * weight;
+    fragRevealage.rgb += texture(revealBuf, uv).rgb * weight;
   }
 
   fragColor /= weight_accum;
   fragRevealage /= weight_accum;
 }
 
+#elif defined(PIXELIZE)
+
+uniform vec2 targetPixelSize;
+uniform vec2 targetPixelOffset;
+uniform vec2 accumOffset;
+uniform int sampCount;
+
+void main()
+{
+  vec2 pixel = floor((uvcoordsvar.xy - targetPixelOffset) / targetPixelSize);
+  vec2 uv = (pixel + 0.5) * targetPixelSize + targetPixelOffset;
+
+  fragColor = vec4(0.0);
+  fragRevealage = vec4(0.0);
+
+  for (int i = -sampCount; i <= sampCount; i++) {
+    float x = float(i) / float(sampCount + 1);
+    vec2 uv_ofs = uv + accumOffset * 0.5 * x;
+    fragColor += texture(colorBuf, uv_ofs);
+    fragRevealage += texture(revealBuf, uv_ofs);
+  }
+
+  fragColor /= float(sampCount) * 2.0 + 1.0;
+  fragRevealage /= float(sampCount) * 2.0 + 1.0;
+}
+
 #endif
\ No newline at end of file



More information about the Bf-blender-cvs mailing list