[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