[Bf-blender-cvs] [a5e6e56a6d3] greasepencil-refactor: GPencil: Refactor: Draw gpencil strokes using instanced quad
Clément Foucault
noreply at git.blender.org
Sun Dec 8 01:39:09 CET 2019
Commit: a5e6e56a6d32918119a1ee66f295400847a24851
Author: Clément Foucault
Date: Sun Dec 8 01:23:17 2019 +0100
Branches: greasepencil-refactor
https://developer.blender.org/rBa5e6e56a6d32918119a1ee66f295400847a24851
GPencil: Refactor: Draw gpencil strokes using instanced quad
Using the instance range drawing (DRW) & the attrib multiload (GPU) we
use the instancing of quad geometry to draw arbitrary thick lines using
only the vertex shader.
===================================================================
M source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
M source/blender/draw/engines/gpencil/gpencil_engine.c
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_draw_cache_impl.c b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
index f4fd90f6e92..67e3635b880 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
@@ -69,9 +69,9 @@ static GPUVertBuf *gpencil_dummy_buffer_get(void)
typedef struct gpStrokeVert {
int mat;
float pos[3];
- float color[4];
- float thickness;
- float uvdata[2];
+ // float col[4];
+ // float rad;
+ // float uv[2];
} gpStrokeVert;
static GPUVertFormat *gpencil_stroke_format(void)
@@ -79,11 +79,13 @@ static GPUVertFormat *gpencil_stroke_format(void)
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
/* TODO Try reducing format size. */
- GPU_vertformat_attr_add(&format, "mat", GPU_COMP_U32, 1, GPU_FETCH_INT);
+ GPU_vertformat_attr_add(&format, "ma", GPU_COMP_I32, 1, GPU_FETCH_INT);
GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- GPU_vertformat_attr_add(&format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- GPU_vertformat_attr_add(&format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ // GPU_vertformat_attr_add(&format, "col", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ // GPU_vertformat_attr_add(&format, "rad", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ // GPU_vertformat_attr_add(&format, "uv", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ /* IMPORTANT: This means having only 4 attributes to fit into opengl limit of 16 attrib. */
+ GPU_vertformat_multiload_enable(&format, 4);
}
return &format;
}
@@ -184,7 +186,7 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache)
gpIterData iter = {
.verts = NULL,
.ibo = {0},
- .vert_len = 0,
+ .vert_len = 1, /* Start at 1 for the gl_InstanceID trick to work (see vert shader). */
.tri_len = 0,
};
gpencil_object_visible_stroke_iter(ob, NULL, gp_object_verts_count_cb, &iter);
@@ -192,7 +194,8 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache)
/* Create VBO. */
GPUVertFormat *format = gpencil_stroke_format();
cache->vbo = GPU_vertbuf_create_with_format(format);
- GPU_vertbuf_data_alloc(cache->vbo, iter.vert_len);
+ /* Add extra space at the end of the buffer because of quad load. */
+ GPU_vertbuf_data_alloc(cache->vbo, iter.vert_len + 2);
iter.verts = (gpStrokeVert *)cache->vbo->data;
/* Create IBO. */
GPU_indexbuf_init(&iter.ibo, GPU_PRIM_TRIS, iter.tri_len, iter.vert_len);
@@ -205,7 +208,8 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache)
/* Create the batches */
cache->fill_batch = GPU_batch_create(GPU_PRIM_TRIS, cache->vbo, cache->ibo);
- cache->stroke_batch = GPU_batch_create(GPU_PRIM_LINE_STRIP, cache->vbo, NULL);
+ cache->stroke_batch = GPU_batch_create(GPU_PRIM_TRI_STRIP, gpencil_dummy_buffer_get(), NULL);
+ GPU_batch_instbuf_add_ex(cache->stroke_batch, cache->vbo, 0);
gpd->flag &= ~GP_DATA_CACHE_IS_DIRTY;
cache->is_dirty = false;
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index 388f8e5aa71..4d527265aa3 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -743,6 +743,8 @@ static void gp_layer_cache_populate(bGPDlayer *layer,
struct GPUShader *sh = GPENCIL_shader_geometry_get(&en_data);
iter->grp = DRW_shgroup_create(sh, tgp_layer->geom_ps);
+ DRW_shgroup_uniform_vec2_copy(iter->grp, "sizeViewportInv", DRW_viewport_invert_size_get());
+ DRW_shgroup_uniform_vec2_copy(iter->grp, "sizeViewport", DRW_viewport_size_get());
}
static void gp_stroke_cache_populate(bGPDlayer *UNUSED(layer),
@@ -752,12 +754,23 @@ static void gp_stroke_cache_populate(bGPDlayer *UNUSED(layer),
{
gpIterPopulateData *iter = (gpIterPopulateData *)thunk;
- GPUBatch *geom = GPENCIL_batch_cache_strokes(iter->ob, iter->pd->cfra);
- /* Don't skip start adjacent vert. */
- int vfirst = stroke->runtime.stroke_start;
- /* Include "potential" cyclic vertex and start adj vertex (see shader). */
- int vcount = stroke->totpoints + 1 + 1;
- DRW_shgroup_call_range(iter->grp, geom, vfirst, vcount);
+ MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(iter->ob, stroke->mat_nr + 1);
+ /* if the user switch used material from data to object,
+ * the material could not be available */
+ if (gp_style == NULL) {
+ return;
+ }
+
+ bool show_stroke = (gp_style->flag & GP_STYLE_STROKE_SHOW) != 0;
+
+ if (show_stroke) {
+ GPUBatch *geom = GPENCIL_batch_cache_strokes(iter->ob, iter->pd->cfra);
+ /* Start one vert before to have gl_InstanceID > 0 (see shader). */
+ int vfirst = stroke->runtime.stroke_start - 1;
+ /* Include "potential" cyclic vertex and start adj vertex (see shader). */
+ int vcount = stroke->totpoints + 1 + 1;
+ DRW_shgroup_call_instance_range(iter->grp, geom, vfirst, vcount);
+ }
}
static void GPENCIL_cache_populate_new(void *ved, Object *ob)
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl
index 9447dfe6acd..7f39c3254ae 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl
@@ -1,7 +1,9 @@
+in vec4 finalColor;
+
out vec4 fragColor;
void main()
{
- fragColor = vec4(1.0);
+ fragColor = finalColor;
}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl
index 190115cf0d8..cd7b520a2c2 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl
@@ -1,13 +1,61 @@
-in int mat;
-in vec3 pos;
+/* TODO UBO */
+uniform vec2 sizeViewport;
+uniform vec2 sizeViewportInv;
+
+in int ma1;
+in int ma2;
+in vec3 pos; /* Prev adj vert */
+in vec3 pos1; /* Current edge */
+in vec3 pos2; /* Current edge */
+in vec3 pos3; /* Next adj vert */
+
+out vec4 finalColor;
+
+void discard_vert()
+{
+ /* We set the vertex at the camera origin to generate 0 fragments. */
+ gl_Position = vec4(0.0, 0.0, -3e36, 0.0);
+}
+
+vec2 project_to_screenspace(vec4 v)
+{
+ return ((v.xy / v.w) * 0.5 + 0.5) * sizeViewport;
+}
void main()
{
- gl_Position = point_world_to_ndc(pos);
+ /* Trick to detect if a drawcall is stroke or fill. */
+ bool is_fill = (gl_InstanceID == 0);
- if (mat == -1) {
+ if (!is_fill) {
/* Enpoints, we discard the vertices. */
- gl_Position = vec4(0.0, 0.0, -3e36, 0.0);
+ if (ma1 == -1 || ma2 == -1) {
+ discard_vert();
+ return;
+ }
+
+ /* Avoid using a vertex attrib for quad positioning. */
+ float x = float((gl_VertexID & 1));
+ float y = float((gl_VertexID & 2) >> 1);
+
+ vec4 ndc1 = point_world_to_ndc(pos1);
+ vec4 ndc2 = point_world_to_ndc(pos2);
+
+ /* TODO case where ndc2 is behind camera */
+ vec2 ss1 = project_to_screenspace(ndc1);
+ vec2 ss2 = project_to_screenspace(ndc2);
+ vec2 perp = normalize(ss2 - ss1);
+ perp = vec2(-perp.y, perp.x);
+
+ gl_Position = (x == 0.0) ? ndc1 : ndc2;
+ gl_Position.xy += perp * (y - 0.5) * sizeViewportInv.xy * gl_Position.w * 10.0;
+
+ finalColor = vec4(0.0, 0.0, 0.0, 1.0);
+ }
+ else {
+ gl_Position = point_world_to_ndc(pos1);
+
+ finalColor = vec4(1.0);
}
}
More information about the Bf-blender-cvs
mailing list