[Bf-blender-cvs] [170680b5448] greasepencil-refactor: GPencil: Refactor: Add support for layer blending

Clément Foucault noreply at git.blender.org
Fri Dec 13 19:45:06 CET 2019


Commit: 170680b5448aabf2aa67258258ef88c998a8046d
Author: Clément Foucault
Date:   Fri Dec 13 19:38:08 2019 +0100
Branches: greasepencil-refactor
https://developer.blender.org/rB170680b5448aabf2aa67258258ef88c998a8046d

GPencil: Refactor: Add support for layer blending

This break the compatibility of old blend files as the old implementation
was done incorrectly.

With new implementation, the layer blending can affect multiple object
and in certain case affect even the rendered background. Old implementation
was only affecting the layers beneath, not other objects.

This implementation is also ready to support vfx on top.

Some blend modes (divide and subtract) have some limitations. They cannot
be propagated to other objects. This is because we would need to use
signed float buffers everywhere (for background render) so that fixed
function blending does not clamp the blending values.

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

M	source/blender/draw/CMakeLists.txt
M	source/blender/draw/engines/gpencil/gpencil_cache_utils.c
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/shaders/gpencil_composite_frag.glsl
M	source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl
A	source/blender/draw/engines/gpencil/shaders/gpencil_layer_blend_frag.glsl

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

diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 896149443d4..1783d26b9e2 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -279,6 +279,7 @@ data_to_c_simple(engines/gpencil/shaders/gpencil_frag.glsl SRC)
 data_to_c_simple(engines/gpencil/shaders/gpencil_vert.glsl SRC)
 data_to_c_simple(engines/gpencil/shaders/gpencil_common_lib.glsl SRC)
 data_to_c_simple(engines/gpencil/shaders/gpencil_composite_frag.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/gpencil_layer_blend_frag.glsl SRC)
 
 data_to_c_simple(engines/gpencil/shaders/gpencil_fill_vert.glsl SRC)
 data_to_c_simple(engines/gpencil/shaders/gpencil_fill_frag.glsl SRC)
diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
index c9c8ec77720..47c87fb2559 100644
--- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
@@ -59,22 +59,77 @@ GPENCIL_tObject *gpencil_object_cache_add_new(GPENCIL_PrivateData *pd, Object *o
 }
 
 /* TODO remove the _new suffix. */
-GPENCIL_tLayer *gpencil_layer_cache_add_new(GPENCIL_PrivateData *pd,
-                                            Object *ob,
-                                            bGPDlayer *UNUSED(layer))
+GPENCIL_tLayer *gpencil_layer_cache_add_new(GPENCIL_PrivateData *pd, Object *ob, bGPDlayer *gpl)
 {
   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_PREMUL;
-  /* TODO better 3D mode. */
-  if (GPENCIL_3D_DRAWMODE(ob, gpd)) {
-    state |= DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
+  {
+    DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA_PREMUL;
+    if (GPENCIL_3D_DRAWMODE(ob, gpd)) {
+      /* TODO better 3D mode. */
+      state |= DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
+    }
+    else {
+      /* We render all strokes with uniform depth (increasing with stroke id). */
+      state |= DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_GREATER;
+    }
+    tgp_layer->geom_ps = DRW_pass_create("GPencil Layer", state);
+  }
+
+  if ((gpl->blend_mode != eGplBlendMode_Regular) || (gpl->opacity < 1.0f)) {
+    DRWState state = DRW_STATE_WRITE_COLOR;
+    switch (gpl->blend_mode) {
+      case eGplBlendMode_Regular:
+        state |= DRW_STATE_BLEND_ALPHA_PREMUL;
+        break;
+      case eGplBlendMode_Add:
+        state |= DRW_STATE_BLEND_ADD;
+        break;
+      case eGplBlendMode_Subtract:
+        /* Caveat. This effect only propagates if target buffer has
+         * a signed floating point color buffer.
+         * i.e: This will not be conserved after this blending step.
+         * TODO(fclem) To make things consistent, we might create a dummy vfx
+         * for objects that use this blend type to always avoid the subtract
+         * affecting other objects. */
+        state |= DRW_STATE_BLEND_SUB;
+        break;
+      case eGplBlendMode_Multiply:
+      case eGplBlendMode_Divide:
+        /* Same Caveat as Subtract. This is conserved until there is a blend with a LDR buffer. */
+      case eGplBlendMode_Overlay:
+        state |= DRW_STATE_BLEND_MUL;
+        break;
+    }
+
+    tgp_layer->blend_ps = DRW_pass_create("GPencil Blend Layer", state);
+
+    GPUShader *sh = GPENCIL_shader_layer_blend_get(&en_data);
+    DRWShadingGroup *grp = DRW_shgroup_create(sh, tgp_layer->blend_ps);
+    DRW_shgroup_uniform_int_copy(grp, "blendMode", gpl->blend_mode);
+    DRW_shgroup_uniform_float_copy(grp, "blendOpacity", gpl->opacity);
+    DRW_shgroup_uniform_texture_ref(grp, "colorBuf", &pd->color_layer_tx);
+    DRW_shgroup_uniform_texture_ref(grp, "revealBuf", &pd->reveal_layer_tx);
+    /* TODO only blend pixels that have been rendered. */
+    DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+
+    if (gpl->blend_mode == eGplBlendMode_Overlay) {
+      /* We cannot do custom blending on MultiTarget framebuffers.
+       * Workaround by doing 2 passes. */
+      grp = DRW_shgroup_create(sh, tgp_layer->blend_ps);
+      DRW_shgroup_state_disable(grp, DRW_STATE_BLEND_MUL);
+      DRW_shgroup_state_enable(grp, DRW_STATE_BLEND_ADD);
+      DRW_shgroup_uniform_int_copy(grp, "blendMode", 999);
+      DRW_shgroup_uniform_texture_ref(grp, "colorBuf", &pd->color_layer_tx);
+      DRW_shgroup_uniform_texture_ref(grp, "revealBuf", &pd->reveal_layer_tx);
+      /* TODO only blend pixels that have been rendered. */
+      DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+    }
   }
   else {
-    state |= DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_GREATER;
+    tgp_layer->blend_ps = NULL;
   }
-  tgp_layer->geom_ps = DRW_pass_create("GPencil Layer", state);
 
   return tgp_layer;
 }
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index d3ffa0bb1f4..ff2f7e883fe 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -351,6 +351,8 @@ static void GPENCIL_engine_free(void)
   DRW_SHADER_FREE_SAFE(e_data.gpencil_paper_sh);
 
   DRW_SHADER_FREE_SAFE(e_data.gpencil_sh);
+  DRW_SHADER_FREE_SAFE(e_data.composite_sh);
+  DRW_SHADER_FREE_SAFE(e_data.layer_blend_sh);
 
   DRW_TEXTURE_FREE_SAFE(e_data.gpencil_blank_texture);
 
@@ -414,8 +416,8 @@ static void GPENCIL_cache_init_new(void *ved)
 
     GPUShader *sh = GPENCIL_shader_composite_get(&e_data);
     grp = DRW_shgroup_create(sh, psl->composite_ps);
-    DRW_shgroup_uniform_texture_ref(grp, "colorBuf", &pd->color);
-    DRW_shgroup_uniform_texture_ref(grp, "alphaBuf", &pd->alpha);
+    DRW_shgroup_uniform_texture_ref(grp, "colorBuf", &pd->color_tx);
+    DRW_shgroup_uniform_texture_ref(grp, "revealBuf", &pd->reveal_tx);
     DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
   }
 }
@@ -1024,22 +1026,54 @@ static void GPENCIL_cache_finish_new(void *ved)
   /* Sort object by distance to the camera. */
   pd->tobjects.first = gpencil_tobject_sort_fn_r(pd->tobjects.first, gpencil_tobject_dist_sort);
 
+  /* Create framebuffers only if needed. */
   if (pd->tobjects.first) {
-    /* Create framebuffers only if needed. */
+    /* TODO(fclem) Detect use of layers and vfx. */
+    bool use_layer_fb = true;
+    bool use_object_fb = false;
+
     const float *size = DRW_viewport_size_get();
-    pd->depth = DRW_texture_pool_query_2d(
+    pd->depth_tx = DRW_texture_pool_query_2d(
         size[0], size[1], GPU_DEPTH_COMPONENT24, &draw_engine_gpencil_type);
-    pd->color = DRW_texture_pool_query_2d(
+    pd->color_tx = DRW_texture_pool_query_2d(
         size[0], size[1], GPU_R11F_G11F_B10F, &draw_engine_gpencil_type);
-    pd->alpha = DRW_texture_pool_query_2d(
+    pd->reveal_tx = DRW_texture_pool_query_2d(
         size[0], size[1], GPU_R11F_G11F_B10F, &draw_engine_gpencil_type);
 
     GPU_framebuffer_ensure_config(&fbl->gpencil_fb,
                                   {
-                                      GPU_ATTACHMENT_TEXTURE(pd->depth),
-                                      GPU_ATTACHMENT_TEXTURE(pd->color),
-                                      GPU_ATTACHMENT_TEXTURE(pd->alpha),
+                                      GPU_ATTACHMENT_TEXTURE(pd->depth_tx),
+                                      GPU_ATTACHMENT_TEXTURE(pd->color_tx),
+                                      GPU_ATTACHMENT_TEXTURE(pd->reveal_tx),
                                   });
+
+    if (use_layer_fb) {
+      pd->color_layer_tx = DRW_texture_pool_query_2d(
+          size[0], size[1], GPU_R11F_G11F_B10F, &draw_engine_gpencil_type);
+      pd->reveal_layer_tx = DRW_texture_pool_query_2d(
+          size[0], size[1], GPU_R11F_G11F_B10F, &draw_engine_gpencil_type);
+
+      GPU_framebuffer_ensure_config(&fbl->layer_fb,
+                                    {
+                                        GPU_ATTACHMENT_TEXTURE(pd->depth_tx),
+                                        GPU_ATTACHMENT_TEXTURE(pd->color_layer_tx),
+                                        GPU_ATTACHMENT_TEXTURE(pd->reveal_layer_tx),
+                                    });
+    };
+
+    if (use_object_fb) {
+      pd->color_object_tx = DRW_texture_pool_query_2d(
+          size[0], size[1], GPU_R11F_G11F_B10F, &draw_engine_gpencil_type);
+      pd->reveal_object_tx = DRW_texture_pool_query_2d(
+          size[0], size[1], GPU_R11F_G11F_B10F, &draw_engine_gpencil_type);
+
+      GPU_framebuffer_ensure_config(&fbl->layer_fb,
+                                    {
+                                        GPU_ATTACHMENT_TEXTURE(pd->depth_tx),
+                                        GPU_ATTACHMENT_TEXTURE(pd->color_object_tx),
+                                        GPU_ATTACHMENT_TEXTURE(pd->reveal_object_tx),
+                                    });
+    }
   }
 }
 
@@ -1241,14 +1275,14 @@ static void GPENCIL_draw_scene_new(void *ved)
   GPENCIL_PrivateData *pd = vedata->stl->pd;
   GPENCIL_FramebufferList *fbl = vedata->fbl;
   DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
-  float clear_col[4] = {0.0f};
+  float clear_cols[2][4] = {{0.0f, 0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}};
 
   if (pd->tobjects.first == NULL) {
     return;
   }
 
   GPU_framebuffer_bind(fbl->gpencil_fb);
-  GPU_framebuffer_clear_color(fbl->gpencil_fb, clear_col);
+  GPU_framebuffer_multi_clear(fbl->gpencil_fb, clear_cols);
 
   for (GPENCIL_tObject *ob = pd->tobjects.first; ob; ob = ob->next) {
     DRW_stats_group_start("GPencil Object");
@@ -1262,16 +1296,15 @@ static void GPENCIL_draw_scene_new(void *ved)
 
     for (GPENCIL_tLayer *layer = ob->layers.first; layer; layer = layer->next) {
       if (layer->blend_ps) {
-        /* TODO blending */
-        // GPU_framebuffer_bind(fbl->layer_fb);
+        GPU_framebuffer_bind(fbl->layer_fb);
+        GPU_framebuffer_multi_clear(fbl->layer_fb, clear_cols);
       }
 
       DRW_draw_pass(layer->geom_ps);
 
       if (layer->blend_ps) {
-        /* TODO blending */
-        // GPU_framebuffer_bind(fbl->object_fb);
-        // DRW_draw_pass(layer->blend_ps);
+        GPU_framebuffer_bin

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list