[Bf-blender-cvs] [b4209b138f6] blender2.8: Clay: Refactor: Port clay to a deferred pipeline.

Clément Foucault noreply at git.blender.org
Wed Mar 14 12:50:51 CET 2018


Commit: b4209b138f6bda863009568bf8dc19eb5cf8361c
Author: Clément Foucault
Date:   Tue Mar 13 22:58:18 2018 +0100
Branches: blender2.8
https://developer.blender.org/rBb4209b138f6bda863009568bf8dc19eb5cf8361c

Clay: Refactor: Port clay to a deferred pipeline.

This means that rendering clay with AO only needs 1 geometry pass.
Thus greatly improving performance of poly heavy scene.

This also fix a self shadow issue in the AO, making low sample count
way better.

We also do not need to blit the depth anymore since we
are doing a fullscreen shading pass.

The constant cost of running the a deferred shading pass is negligeable.
This include quite a bit of code cleanup inside clay_engine.c.

The deferred pipeline is only enabled if at least one material needs it.
Multisampling is not supported yet.

Small hacks when doing deferred:
- We invert the normal before encoding it for precision.
- We put the facing direction into the sign of the mat_id.
- We dither the normal to fight the low bitdepth artifacts of the normal
  buffer (which is 8bits per channel to reduce bandwidth usage).

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

M	source/blender/draw/CMakeLists.txt
M	source/blender/draw/engines/clay/clay_engine.c
M	source/blender/draw/engines/clay/shaders/clay_frag.glsl
A	source/blender/draw/engines/clay/shaders/clay_prepass_frag.glsl

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

diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 6618aaea4f4..09337ea4aff 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -132,6 +132,7 @@ if(WITH_CLAY_ENGINE)
 endif()
 
 data_to_c_simple(engines/clay/shaders/clay_frag.glsl SRC)
+data_to_c_simple(engines/clay/shaders/clay_prepass_frag.glsl SRC)
 data_to_c_simple(engines/clay/shaders/clay_vert.glsl SRC)
 data_to_c_simple(engines/clay/shaders/clay_particle_vert.glsl SRC)
 data_to_c_simple(engines/clay/shaders/clay_particle_strand_frag.glsl SRC)
diff --git a/source/blender/draw/engines/clay/clay_engine.c b/source/blender/draw/engines/clay/clay_engine.c
index 655031b83b8..9736a9ad027 100644
--- a/source/blender/draw/engines/clay/clay_engine.c
+++ b/source/blender/draw/engines/clay/clay_engine.c
@@ -51,13 +51,17 @@
 
 #define MAX_CLAY_MAT 512 /* 512 = 9 bit material id */
 
-#define SHADER_DEFINES \
+#define SHADER_DEFINES_NO_AO \
 	"#define MAX_MATERIAL " STRINGIFY(MAX_CLAY_MAT) "\n" \
 	"#define USE_ROTATION\n" \
-	"#define USE_AO\n" \
 	"#define USE_HSV\n"
 
+#define SHADER_DEFINES \
+	SHADER_DEFINES_NO_AO \
+	"#define USE_AO\n"
+
 extern char datatoc_clay_frag_glsl[];
+extern char datatoc_clay_prepass_frag_glsl[];
 extern char datatoc_clay_vert_glsl[];
 extern char datatoc_clay_particle_vert_glsl[];
 extern char datatoc_clay_particle_strand_frag_glsl[];
@@ -111,6 +115,8 @@ typedef struct CLAY_Storage {
 	int hair_ubo_current_id;
 	DRWShadingGroup *shgrps[MAX_CLAY_MAT];
 	DRWShadingGroup *shgrps_flat[MAX_CLAY_MAT];
+	DRWShadingGroup *shgrps_pre[MAX_CLAY_MAT];
+	DRWShadingGroup *shgrps_pre_flat[MAX_CLAY_MAT];
 	DRWShadingGroup *hair_shgrps[MAX_CLAY_MAT];
 } CLAY_Storage;
 
@@ -120,17 +126,20 @@ typedef struct CLAY_StorageList {
 } CLAY_StorageList;
 
 typedef struct CLAY_FramebufferList {
-	/* default */
-	struct GPUFrameBuffer *default_fb;
-	/* engine specific */
-	struct GPUFrameBuffer *dupli_depth;
+	struct GPUFrameBuffer *dupli_depth_fb;
+	struct GPUFrameBuffer *prepass_fb;
 } CLAY_FramebufferList;
 
 typedef struct CLAY_PassList {
-	struct DRWPass *depth_pass;
-	struct DRWPass *depth_pass_cull;
-	struct DRWPass *clay_pass;
-	struct DRWPass *clay_pass_flat;
+	struct DRWPass *clay_ps;
+	struct DRWPass *clay_cull_ps;
+	struct DRWPass *clay_flat_ps;
+	struct DRWPass *clay_flat_cull_ps;
+	struct DRWPass *clay_pre_ps;
+	struct DRWPass *clay_pre_cull_ps;
+	struct DRWPass *clay_flat_pre_ps;
+	struct DRWPass *clay_flat_pre_cull_ps;
+	struct DRWPass *clay_deferred_ps;
 	struct DRWPass *hair_pass;
 } CLAY_PassList;
 
@@ -154,27 +163,18 @@ typedef struct CLAY_ViewLayerData {
 /* *********** STATIC *********** */
 
 static struct {
-	/* Depth Pre Pass */
-	struct GPUShader *depth_sh;
 	/* Shading Pass */
 	struct GPUShader *clay_sh;
 	struct GPUShader *clay_flat_sh;
+	struct GPUShader *clay_prepass_flat_sh;
+	struct GPUShader *clay_prepass_sh;
+	struct GPUShader *clay_deferred_shading_sh;
 	struct GPUShader *hair_sh;
-
 	/* Matcap textures */
 	struct GPUTexture *matcap_array;
 	float matcap_colors[24][4];
-
-	/* Ssao */
-	float winmat[4][4];
-	float viewvecs[3][4];
-	float ssao_params[4];
-
 	/* Just a serie of int from 0 to MAX_CLAY_MAT-1 */
 	int ubo_mat_idxs[MAX_CLAY_MAT];
-
-	/* engine specific */
-	struct GPUTexture *depth_dup;
 } e_data = {NULL}; /* Engine data */
 
 typedef struct CLAY_PrivateData {
@@ -184,7 +184,15 @@ typedef struct CLAY_PrivateData {
 	DRWShadingGroup *depth_shgrp_cull;
 	DRWShadingGroup *depth_shgrp_cull_select;
 	DRWShadingGroup *depth_shgrp_cull_active;
-	bool enable_ao;
+	/* Deferred shading */
+	struct GPUTexture *depth_dup; /* ref only, not alloced */
+	struct GPUTexture *normal_tx; /* ref only, not alloced */
+	struct GPUTexture *id_tx; /* ref only, not alloced */
+	bool enable_deferred_path;
+	/* Ssao */
+	float winmat[4][4];
+	float viewvecs[3][4];
+	float ssao_params[4];
 } CLAY_PrivateData; /* Transient data */
 
 /* Functions */
@@ -366,11 +374,6 @@ static void clay_engine_init(void *vedata)
 		e_data.matcap_array = load_matcaps(prv, 24);
 	}
 
-	/* Depth prepass */
-	if (!e_data.depth_sh) {
-		e_data.depth_sh = DRW_shader_create_3D_depth_only();
-	}
-
 	/* Shading pass */
 	if (!e_data.clay_sh) {
 		DynStr *ds = BLI_dynstr_new();
@@ -382,13 +385,26 @@ static void clay_engine_init(void *vedata)
 		matcap_with_ao = BLI_dynstr_get_cstring(ds);
 
 		e_data.clay_sh = DRW_shader_create(
-		        datatoc_clay_vert_glsl, NULL, matcap_with_ao,
-		        SHADER_DEFINES);
+		        datatoc_clay_vert_glsl, NULL, datatoc_clay_frag_glsl,
+		        SHADER_DEFINES_NO_AO);
 		e_data.clay_flat_sh = DRW_shader_create(
-		        datatoc_clay_vert_glsl, NULL, matcap_with_ao,
+		        datatoc_clay_vert_glsl, NULL, datatoc_clay_frag_glsl,
+		        SHADER_DEFINES_NO_AO
+		        "#define USE_FLAT_NORMAL\n");
+
+		e_data.clay_prepass_sh = DRW_shader_create(
+		        datatoc_clay_vert_glsl, NULL, datatoc_clay_prepass_frag_glsl,
+		        SHADER_DEFINES);
+		e_data.clay_prepass_flat_sh = DRW_shader_create(
+		        datatoc_clay_vert_glsl, NULL, datatoc_clay_prepass_frag_glsl,
 		        SHADER_DEFINES
 		        "#define USE_FLAT_NORMAL\n");
 
+		e_data.clay_deferred_shading_sh = DRW_shader_create_fullscreen(
+		        matcap_with_ao,
+		        SHADER_DEFINES
+		        "#define DEFERRED_SHADING\n");
+
 		BLI_dynstr_free(ds);
 		MEM_freeN(matcap_with_ao);
 	}
@@ -403,6 +419,12 @@ static void clay_engine_init(void *vedata)
 		stl->storage = MEM_callocN(sizeof(CLAY_Storage), "CLAY_Storage");
 	}
 
+	if (!stl->g_data) {
+		stl->g_data = MEM_mallocN(sizeof(*stl->g_data), "CLAY_PrivateStorage");
+	}
+
+	CLAY_PrivateData *g_data = stl->g_data;
+
 	if (!sldata->mat_ubo) {
 		sldata->mat_ubo = DRW_uniformbuffer_create(sizeof(CLAY_UBO_Storage), NULL);
 	}
@@ -423,11 +445,20 @@ static void clay_engine_init(void *vedata)
 	}
 
 	if (DRW_state_is_fbo()) {
+#if 0 /* TODO, multisample */
 		const float *viewport_size = DRW_viewport_size_get();
 		DRWFboTexture tex = {&e_data.depth_dup, DRW_TEX_DEPTH_24_STENCIL_8, DRW_TEX_TEMP};
-		DRW_framebuffer_init(&fbl->dupli_depth, &draw_engine_clay_type,
+		DRW_framebuffer_init(&fbl->dupli_depth_fb, &draw_engine_clay_type,
 		                     (int)viewport_size[0], (int)viewport_size[1],
 		                     &tex, 1);
+#endif
+
+		const float *viewport_size = DRW_viewport_size_get();
+		DRWFboTexture texs[2] = {{&g_data->normal_tx, DRW_TEX_RG_8, DRW_TEX_TEMP},
+		                         {&g_data->id_tx, DRW_TEX_R_16I, DRW_TEX_TEMP}};
+		DRW_framebuffer_init(&fbl->prepass_fb, &draw_engine_clay_type,
+		                     (int)viewport_size[0], (int)viewport_size[1],
+		                     texs, 2);
 	}
 
 	/* SSAO setup */
@@ -453,14 +484,14 @@ static void clay_engine_init(void *vedata)
 
 		DRW_state_dfdy_factors_get(dfdyfacs);
 
-		e_data.ssao_params[0] = ssao_samples;
-		e_data.ssao_params[1] = size[0] / 64.0;
-		e_data.ssao_params[2] = size[1] / 64.0;
-		e_data.ssao_params[3] = dfdyfacs[1]; /* dfdy sign for offscreen */
+		g_data->ssao_params[0] = ssao_samples;
+		g_data->ssao_params[1] = size[0] / 64.0;
+		g_data->ssao_params[2] = size[1] / 64.0;
+		g_data->ssao_params[3] = dfdyfacs[1]; /* dfdy sign for offscreen */
 
 		/* invert the view matrix */
-		DRW_viewport_matrix_get(e_data.winmat, DRW_MAT_WIN);
-		invert_m4_m4(invproj, e_data.winmat);
+		DRW_viewport_matrix_get(g_data->winmat, DRW_MAT_WIN);
+		invert_m4_m4(invproj, g_data->winmat);
 
 		/* convert the view vectors to view space */
 		for (i = 0; i < 3; i++) {
@@ -472,19 +503,19 @@ static void clay_engine_init(void *vedata)
 				mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]);
 			viewvecs[i][3] = 1.0;
 
-			copy_v4_v4(e_data.viewvecs[i], viewvecs[i]);
+			copy_v4_v4(g_data->viewvecs[i], viewvecs[i]);
 		}
 
 		/* we need to store the differences */
-		e_data.viewvecs[1][0] -= e_data.viewvecs[0][0];
-		e_data.viewvecs[1][1] = e_data.viewvecs[2][1] - e_data.viewvecs[0][1];
+		g_data->viewvecs[1][0] -= g_data->viewvecs[0][0];
+		g_data->viewvecs[1][1] = g_data->viewvecs[2][1] - g_data->viewvecs[0][1];
 
 		/* calculate a depth offset as well */
 		if (!is_persp) {
 			float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f};
 			mul_m4_v4(invproj, vec_far);
 			mul_v3_fl(vec_far, 1.0f / vec_far[3]);
-			e_data.viewvecs[1][2] = vec_far[2] - e_data.viewvecs[0][2];
+			g_data->viewvecs[1][2] = vec_far[2] - g_data->viewvecs[0][2];
 		}
 
 		/* AO Samples Tex */
@@ -503,37 +534,56 @@ static void clay_engine_init(void *vedata)
 	}
 }
 
-static DRWShadingGroup *CLAY_shgroup_create(CLAY_Data *UNUSED(vedata), DRWPass *pass, int *material_id, bool use_flat)
+static DRWShadingGroup *CLAY_shgroup_create(DRWPass *pass, GPUShader *sh, int id)
 {
 	CLAY_ViewLayerData *sldata = CLAY_view_layer_data_get();
-	DRWShadingGroup *grp = DRW_shgroup_create(use_flat ? e_data.clay_flat_sh : e_data.clay_sh, pass);
-
-	DRW_shgroup_uniform_vec2(grp, "screenres", DRW_viewport_size_get(), 1);
-	DRW_shgroup_uniform_buffer(grp, "depthtex", &e_data.depth_dup);
+	DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
 	DRW_shgroup_uniform_texture(grp, "matcaps", e_data.matcap_array);
-	DRW_shgroup_uniform_mat4(grp, "WinMatrix", (float *)e_data.winmat);
-	DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)e_data.viewvecs, 3);
-	DRW_shgroup_uniform_vec4(grp, "ssao_params", e_data.ssao_params, 1);
+	DRW_shgroup_uniform_block(grp, "material_block", sldata->mat_ubo);
+	DRW_shgroup_uniform_block(grp, "matcaps_block", sldata->matcaps_ubo);
+	DRW_shgroup_uniform_int(grp, "mat_id", &e_data.ubo_mat_idxs[id], 1);
+	return grp;
+}
+
+static DRWShadingGroup *CLAY_shgroup_deferred_prepass_create(DRWPass *pass, GPUShader *sh, int id)
+{
+	DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
+	DRW_shgroup_stencil_mask(grp, 1);
+	DRW_shgroup_uniform_int(grp, "mat_id", &e_data.ubo_mat_idxs[id], 1);
 
-	DRW_shgroup_uniform_int(grp, "mat_id", material_id, 1);
+	return grp;
+}
 
+static DRWShadingGroup *CLAY_shgroup_deferred_shading_create(DRWPass *pass, CLAY_PrivateData *g_data)
+{
+	CLAY_ViewLayerData *sldata = CLAY_view_layer_data_get();
+	DRWShadingGroup *grp = DRW_shgroup_create(e_data.clay_deferred_shading_sh, pass);
+	DRW_shgroup_stencil_mask(grp, 1);


@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list