[Bf-blender-cvs] [ed9b98c63f2] greasepencil-object: New Viewport Fast Drawing

Antonio Vazquez noreply at git.blender.org
Tue Sep 12 17:03:10 CEST 2017


Commit: ed9b98c63f28bcf5fe91bb842b7f90509b763691
Author: Antonio Vazquez
Date:   Tue Sep 12 14:54:50 2017 +0200
Branches: greasepencil-object
https://developer.blender.org/rBed9b98c63f28bcf5fe91bb842b7f90509b763691

New Viewport Fast Drawing

Now a temp texture is used while the user is drawing to get an instant feedback.

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

M	source/blender/blenkernel/BKE_gpencil.h
M	source/blender/blenkernel/intern/gpencil.c
M	source/blender/draw/CMakeLists.txt
M	source/blender/draw/engines/gpencil/gpencil_engine.c
M	source/blender/draw/engines/gpencil/gpencil_engine.h
A	source/blender/draw/engines/gpencil/shaders/gpencil_painting_frag.glsl

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

diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index 78c4486a998..5f4f1c98e63 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -107,6 +107,7 @@ void BKE_gpencil_move_animdata_to_palettes(struct bContext *C, struct bGPdata *g
 #define GPENCIL_STRENGTH_MIN 0.003f
 
 bool gpencil_layer_is_editable(const struct bGPDlayer *gpl);
+bool BKE_gpencil_check_drawing_sessions(void);
 
 /* How gpencil_layer_getframe() should behave when there
  * is no existing GP-Frame on the frame requested.
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index fac61828c37..8c83339c13d 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -1662,6 +1662,22 @@ void BKE_gpencil_batch_cache_alldirty()
 	}
 }
 
+/* check if any datablock is painting now */
+bool BKE_gpencil_check_drawing_sessions()
+{
+	bGPdata *gpd;
+	Main *bmain = G.main;
+
+	/* loop to check if any datablock is painting */
+	for (gpd = bmain->gpencil.first; gpd; gpd = gpd->id.next) {
+		if (((gpd->sbuffer_sflag & GP_STROKE_ERASER) == 0) && (gpd->sbuffer_size > 0)) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
 /* get stroke min max values */
 void static gpencil_minmax(bGPdata *gpd, float min[3], float max[3])
 {
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 17e56c2ff59..d560fbfc9a7 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -220,6 +220,7 @@ data_to_c_simple(engines/gpencil/shaders/gpencil_gaussian_blur_frag.glsl SRC)
 data_to_c_simple(engines/gpencil/shaders/gpencil_wave_frag.glsl SRC)
 data_to_c_simple(engines/gpencil/shaders/gpencil_pixel_frag.glsl SRC)
 data_to_c_simple(engines/gpencil/shaders/gpencil_swirl_frag.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/gpencil_painting_frag.glsl SRC)
 
 list(APPEND INC
 )
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index d6dbf05cbfe..c3a50047c0e 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -53,6 +53,7 @@ extern char datatoc_gpencil_gaussian_blur_frag_glsl[];
 extern char datatoc_gpencil_wave_frag_glsl[];
 extern char datatoc_gpencil_pixel_frag_glsl[];
 extern char datatoc_gpencil_swirl_frag_glsl[];
+extern char datatoc_gpencil_painting_frag_glsl[];
 
 /* *********** STATIC *********** */
 static GPENCIL_e_data e_data = {NULL}; /* Engine data */
@@ -95,6 +96,16 @@ static void GPENCIL_engine_init(void *vedata)
 		(int)viewport_size[0], (int)viewport_size[1],
 		vfx_color_b, ARRAY_SIZE(vfx_color_b));
 
+	/* painting framebuffer to speed up drawing process */
+	DRWFboTexture tex_painting[2] = { {
+			&e_data.painting_depth_tx, DRW_TEX_DEPTH_24, DRW_TEX_TEMP },
+			{ &e_data.painting_color_tx, DRW_TEX_RGBA_16, DRW_TEX_TEMP }
+	};
+	DRW_framebuffer_init(
+		&fbl->painting_fb, &draw_engine_gpencil_type,
+		(int)viewport_size[0], (int)viewport_size[1],
+		tex_painting, ARRAY_SIZE(tex_painting));
+
 	/* normal fill shader */
 	if (!e_data.gpencil_fill_sh) {
 		e_data.gpencil_fill_sh = DRW_shader_create(datatoc_gpencil_fill_vert_glsl, NULL,
@@ -155,6 +166,7 @@ static void GPENCIL_engine_free(void)
 	DRW_SHADER_FREE_SAFE(e_data.gpencil_vfx_wave_sh);
 	DRW_SHADER_FREE_SAFE(e_data.gpencil_vfx_pixel_sh);
 	DRW_SHADER_FREE_SAFE(e_data.gpencil_vfx_swirl_sh);
+	DRW_SHADER_FREE_SAFE(e_data.gpencil_painting_sh);
 
 	DRW_TEXTURE_FREE_SAFE(e_data.gpencil_blank_texture);
 }
@@ -213,6 +225,9 @@ static void GPENCIL_cache_init(void *vedata)
 	if (!e_data.gpencil_vfx_swirl_sh) {
 		e_data.gpencil_vfx_swirl_sh = DRW_shader_create_fullscreen(datatoc_gpencil_swirl_frag_glsl, NULL);
 	}
+	if (!e_data.gpencil_painting_sh) {
+		e_data.gpencil_painting_sh = DRW_shader_create_fullscreen(datatoc_gpencil_painting_frag_glsl, NULL);
+	}
 
 	{
 		/* Stroke pass */
@@ -240,6 +255,17 @@ static void GPENCIL_cache_init(void *vedata)
 				}
 			}
 		}
+		/* detect if painting session in any datablock */
+		if (BKE_gpencil_check_drawing_sessions()) {
+			if (stl->g_data->session_flag & GP_DRW_PAINT_IDLE) {
+				stl->g_data->session_flag = GP_DRW_PAINT_DIRTY;
+			}
+		}
+		else {
+			/* if not drawing, the painting session is idle */
+			stl->g_data->session_flag = GP_DRW_PAINT_IDLE;
+		}
+
 		ob = draw_ctx->obact;
 		if (ob) {
 			gpd = ob->gpd;
@@ -306,6 +332,14 @@ static void GPENCIL_cache_init(void *vedata)
 		psl->vfx_pixel_pass = DRW_pass_create("GPencil VFX Pixel Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
 
 		psl->vfx_swirl_pass = DRW_pass_create("GPencil VFX Swirl Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+
+		/* Painting session pass (used only to speedup while the user is drawing ) */
+		struct Gwn_Batch *paintquad = DRW_cache_fullscreen_quad_get();
+		psl->painting_pass = DRW_pass_create("GPencil Painting Session Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+		DRWShadingGroup *painting_shgrp = DRW_shgroup_create(e_data.gpencil_painting_sh, psl->painting_pass);
+		DRW_shgroup_call_add(painting_shgrp, paintquad, NULL);
+		DRW_shgroup_uniform_buffer(painting_shgrp, "strokeColor", &e_data.painting_color_tx);
+		DRW_shgroup_uniform_buffer(painting_shgrp, "strokeDepth", &e_data.painting_depth_tx);
 	}
 }
 
@@ -320,16 +354,18 @@ static void GPENCIL_cache_populate(void *vedata, Object *ob)
 
 	/* object datablock (this is not draw now) */
 	if (ob->type == OB_GPENCIL && ob->gpd) {
-		if (G.debug_value == 668) {
-			printf("GPENCIL_cache_populate: %s\n", ob->id.name);
-		}
-		/* allocate memory for saving gp objects */
-		stl->g_data->gp_object_cache = gpencil_object_cache_allocate(stl->g_data->gp_object_cache, &stl->g_data->gp_cache_size, &stl->g_data->gp_cache_used);
-		/* add for drawing later */
-		gpencil_object_cache_add(stl->g_data->gp_object_cache, ob, &stl->g_data->gp_cache_used);
-		/* generate duplicated instances using array modifiers */
-		if (!GP_SIMPLIFY_MODIF(ts, playing)) {
-			gpencil_array_modifiers(stl, ob);
+		if ((stl->g_data->session_flag & GP_DRW_PAINT_READY) == 0) {
+			if (G.debug_value == 668) {
+				printf("GPENCIL_cache_populate: %s\n", ob->id.name);
+			}
+			/* allocate memory for saving gp objects */
+			stl->g_data->gp_object_cache = gpencil_object_cache_allocate(stl->g_data->gp_object_cache, &stl->g_data->gp_cache_size, &stl->g_data->gp_cache_used);
+			/* add for drawing later */
+			gpencil_object_cache_add(stl->g_data->gp_object_cache, ob, &stl->g_data->gp_cache_used);
+			/* generate duplicated instances using array modifiers */
+			if (!GP_SIMPLIFY_MODIF(ts, playing)) {
+				gpencil_array_modifiers(stl, ob);
+			}
 		}
 		/* draw current painting strokes */
 		DRW_gpencil_populate_buffer_strokes(vedata, ts, ob);
@@ -346,6 +382,11 @@ static void GPENCIL_cache_finish(void *vedata)
 	bool is_multiedit = false; 
 	bool playing = (bool)stl->storage->playing;
 
+	/* if painting session is ready, don't need to do more */
+	if (stl->g_data->session_flag & GP_DRW_PAINT_READY) {
+		return;
+	}
+
 	/* Draw all pending objects */
 	if (stl->g_data->gp_cache_used > 0) {
 		for (int i = 0; i < stl->g_data->gp_cache_used; ++i) {
@@ -476,11 +517,6 @@ static void gpencil_vfx_passes(void *vedata, tGPencilObjectCache *cache)
 		DRW_framebuffer_clear(true, true, false, clearcol, 1.0f);
 		DRW_draw_pass(psl->vfx_copy_pass);
 	}
-
-	/* Combine with default scene buffer always using tx_a as source texture */
-	DRW_framebuffer_bind(dfbl->default_fb);
-	/* Mix VFX Pass */
-	DRW_draw_pass(psl->mix_vfx_pass);
 }
 
 static void GPENCIL_draw_scene(void *vedata)
@@ -509,56 +545,85 @@ static void GPENCIL_draw_scene(void *vedata)
 	DRW_framebuffer_texture_attach(fbl->vfx_color_fb_b, e_data.vfx_fbcolor_depth_tx_b, 0, 0);
 	DRW_framebuffer_texture_attach(fbl->vfx_color_fb_b, e_data.vfx_fbcolor_color_tx_b, 0, 0);
 
-	/* Draw all pending objects */
-	if (stl->g_data->gp_cache_used > 0) {
+	DRW_framebuffer_texture_attach(fbl->painting_fb, e_data.painting_depth_tx, 0, 0);
+	DRW_framebuffer_texture_attach(fbl->painting_fb, e_data.painting_color_tx, 0, 0);
 
-		/* sort by zdepth */
-		qsort(stl->g_data->gp_object_cache, stl->g_data->gp_cache_used, 
-			sizeof(tGPencilObjectCache), gpencil_object_cache_compare_zdepth);
+	/* if we have a painting session, we use fast viewport drawing method */
+	if (stl->g_data->session_flag & GP_DRW_PAINT_READY) {
+		DRW_framebuffer_bind(dfbl->default_fb);
+		DRW_draw_pass(psl->painting_pass);
+		DRW_draw_pass(psl->drawing_pass);
+	}
+	else {
+		/* Draw all pending objects */
+		if (stl->g_data->gp_cache_used > 0) {
 
-		for (int i = 0; i < stl->g_data->gp_cache_used; ++i) {
-			cache = &stl->g_data->gp_object_cache[i];
-			Object *ob = cache->ob;
-			init_grp = cache->init_grp;
-			end_grp = cache->end_grp;
-			/* Render stroke in separated framebuffer */
-			DRW_framebuffer_bind(fbl->temp_color_fb);
-			DRW_framebuffer_clear(true, true, false, clearcol, 1.0f);
-
-			/* Stroke Pass: DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_WRITE_DEPTH
-			 * draw only a subset that usually start with a fill and end with stroke because the
-			 * shading groups are created by pairs */
-			if (G.debug_value == 668) {
-				printf("GPENCIL_draw_scene: %s %d->%d\n", ob->id.name, init_grp, end_grp);
-			}
+			/* sort by zdepth */
+			qsort(stl->g_data->gp_object_cache, stl->g_data->gp_cache_used,
+				sizeof(tGPencilObjectCache), gpencil_object_cache_compare_zdepth);
 
-			if (end_grp >= init_grp) {
-				DRW_draw_pass_subset(psl->stroke_pass,
-					stl->shgroups[init_grp].shgrps_fill != NULL ? stl->shgroups[init_grp].shgrps_fill : stl->shgroups[init_grp].shgrps_stroke,
-					stl->shgroups[end_grp].shgrps_stroke);
-			}
-			/* Current buffer drawing */
-			if (ob->gpd->sbuffer_size > 0) {
-				DRW_draw_pass(psl->drawing_pass);
-			}
+			for (int i = 0; i < stl->g_data->gp_cache_used; ++i) {
+				cache = &stl->g_data->gp_object_cache[i];
+				Object *ob = cache->ob;
+		

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list