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).
This commit is contained in:
parent
e22bc559b0
commit
b4209b138f
|
@ -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)
|
||||
|
|
|
@ -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_int(grp, "mat_id", material_id, 1);
|
||||
|
||||
DRW_shgroup_uniform_texture(grp, "ssao_jitter", sldata->jitter_tx);
|
||||
DRW_shgroup_uniform_block(grp, "samples_block", sldata->sampling_ubo);
|
||||
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);
|
||||
|
||||
return grp;
|
||||
}
|
||||
|
||||
static DRWShadingGroup *CLAY_hair_shgroup_create(CLAY_Data *UNUSED(vedata), DRWPass *pass, int *material_id)
|
||||
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.hair_sh, pass);
|
||||
|
||||
DRWShadingGroup *grp = DRW_shgroup_create(e_data.clay_deferred_shading_sh, pass);
|
||||
DRW_shgroup_stencil_mask(grp, 1);
|
||||
DRW_shgroup_uniform_buffer(grp, "depthtex", &g_data->depth_dup);
|
||||
DRW_shgroup_uniform_buffer(grp, "normaltex", &g_data->normal_tx);
|
||||
DRW_shgroup_uniform_buffer(grp, "idtex", &g_data->id_tx);
|
||||
DRW_shgroup_uniform_texture(grp, "matcaps", e_data.matcap_array);
|
||||
DRW_shgroup_uniform_int(grp, "mat_id", material_id, 1);
|
||||
DRW_shgroup_uniform_texture(grp, "ssao_jitter", sldata->jitter_tx);
|
||||
DRW_shgroup_uniform_block(grp, "samples_block", sldata->sampling_ubo);
|
||||
DRW_shgroup_uniform_block(grp, "material_block", sldata->mat_ubo);
|
||||
DRW_shgroup_uniform_block(grp, "matcaps_block", sldata->matcaps_ubo);
|
||||
/* TODO put in ubo */
|
||||
DRW_shgroup_uniform_mat4(grp, "WinMatrix", (float *)g_data->winmat);
|
||||
DRW_shgroup_uniform_vec2(grp, "invscreenres", DRW_viewport_invert_size_get(), 1);
|
||||
DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)g_data->viewvecs, 3);
|
||||
DRW_shgroup_uniform_vec4(grp, "ssao_params", g_data->ssao_params, 1);
|
||||
return grp;
|
||||
}
|
||||
|
||||
static DRWShadingGroup *CLAY_hair_shgroup_create(DRWPass *pass, int id)
|
||||
{
|
||||
CLAY_ViewLayerData *sldata = CLAY_view_layer_data_get();
|
||||
|
||||
DRWShadingGroup *grp = DRW_shgroup_create(e_data.hair_sh, pass);
|
||||
DRW_shgroup_uniform_texture(grp, "matcaps", e_data.matcap_array);
|
||||
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;
|
||||
}
|
||||
|
@ -568,25 +618,17 @@ static int search_hair_mat_to_ubo(CLAY_Storage *storage, const CLAY_HAIR_UBO_Mat
|
|||
|
||||
static int push_mat_to_ubo(CLAY_Storage *storage, const CLAY_UBO_Material *mat_ubo_test)
|
||||
{
|
||||
int id = storage->ubo_current_id;
|
||||
CLAY_UBO_Material *ubo = &storage->mat_storage.materials[id];
|
||||
|
||||
*ubo = *mat_ubo_test;
|
||||
|
||||
storage->ubo_current_id++;
|
||||
|
||||
int id = storage->ubo_current_id++;
|
||||
id = min_ii(MAX_CLAY_MAT, id);
|
||||
storage->mat_storage.materials[id] = *mat_ubo_test;
|
||||
return id;
|
||||
}
|
||||
|
||||
static int push_hair_mat_to_ubo(CLAY_Storage *storage, const CLAY_HAIR_UBO_Material *hair_mat_ubo_test)
|
||||
{
|
||||
int id = storage->hair_ubo_current_id;
|
||||
CLAY_HAIR_UBO_Material *ubo = &storage->hair_mat_storage.materials[id];
|
||||
|
||||
*ubo = *hair_mat_ubo_test;
|
||||
|
||||
storage->hair_ubo_current_id++;
|
||||
|
||||
int id = storage->hair_ubo_current_id++;
|
||||
id = min_ii(MAX_CLAY_MAT, id);
|
||||
storage->hair_mat_storage.materials[id] = *hair_mat_ubo_test;
|
||||
return id;
|
||||
}
|
||||
|
||||
|
@ -616,11 +658,11 @@ static int hair_mat_in_ubo(CLAY_Storage *storage, const CLAY_HAIR_UBO_Material *
|
|||
return id;
|
||||
}
|
||||
|
||||
static void ubo_mat_from_object(Object *ob, CLAY_UBO_Material *r_ubo, bool *r_needs_ao)
|
||||
static void ubo_mat_from_object(CLAY_Storage *storage, Object *ob, bool *r_needs_ao, int *r_id)
|
||||
{
|
||||
IDProperty *props = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_CLAY);
|
||||
|
||||
/* Default Settings */
|
||||
int matcap_icon = BKE_collection_engine_property_value_get_int(props, "matcap_icon");
|
||||
float matcap_rot = BKE_collection_engine_property_value_get_float(props, "matcap_rotation");
|
||||
float matcap_hue = BKE_collection_engine_property_value_get_float(props, "matcap_hue");
|
||||
float matcap_sat = BKE_collection_engine_property_value_get_float(props, "matcap_saturation");
|
||||
|
@ -629,41 +671,45 @@ static void ubo_mat_from_object(Object *ob, CLAY_UBO_Material *r_ubo, bool *r_ne
|
|||
float ssao_factor_cavity = BKE_collection_engine_property_value_get_float(props, "ssao_factor_cavity");
|
||||
float ssao_factor_edge = BKE_collection_engine_property_value_get_float(props, "ssao_factor_edge");
|
||||
float ssao_attenuation = BKE_collection_engine_property_value_get_float(props, "ssao_attenuation");
|
||||
int matcap_icon = BKE_collection_engine_property_value_get_int(props, "matcap_icon");
|
||||
|
||||
CLAY_UBO_Material r_ubo = {{0.0f}};
|
||||
|
||||
if (((ssao_factor_cavity > 0.0) || (ssao_factor_edge > 0.0)) &&
|
||||
(ssao_distance > 0.0))
|
||||
{
|
||||
*r_needs_ao = true;
|
||||
|
||||
r_ubo.ssao_params_var[0] = ssao_distance;
|
||||
r_ubo.ssao_params_var[1] = ssao_factor_cavity;
|
||||
r_ubo.ssao_params_var[2] = ssao_factor_edge;
|
||||
r_ubo.ssao_params_var[3] = ssao_attenuation;
|
||||
}
|
||||
else {
|
||||
*r_needs_ao = false;
|
||||
}
|
||||
|
||||
memset(r_ubo, 0x0, sizeof(*r_ubo));
|
||||
r_ubo.matcap_rot[0] = cosf(matcap_rot * 3.14159f * 2.0f);
|
||||
r_ubo.matcap_rot[1] = sinf(matcap_rot * 3.14159f * 2.0f);
|
||||
|
||||
r_ubo->matcap_rot[0] = cosf(matcap_rot * 3.14159f * 2.0f);
|
||||
r_ubo->matcap_rot[1] = sinf(matcap_rot * 3.14159f * 2.0f);
|
||||
r_ubo.matcap_hsv[0] = matcap_hue + 0.5f;
|
||||
r_ubo.matcap_hsv[1] = matcap_sat * 2.0f;
|
||||
r_ubo.matcap_hsv[2] = matcap_val * 2.0f;
|
||||
|
||||
r_ubo->matcap_hsv[0] = matcap_hue + 0.5f;
|
||||
r_ubo->matcap_hsv[1] = matcap_sat * 2.0f;
|
||||
r_ubo->matcap_hsv[2] = matcap_val * 2.0f;
|
||||
r_ubo.matcap_id = matcap_to_index(matcap_icon);
|
||||
|
||||
r_ubo->ssao_params_var[0] = ssao_distance;
|
||||
r_ubo->ssao_params_var[1] = ssao_factor_cavity;
|
||||
r_ubo->ssao_params_var[2] = ssao_factor_edge;
|
||||
r_ubo->ssao_params_var[3] = ssao_attenuation;
|
||||
r_ubo->matcap_id = matcap_to_index(matcap_icon);
|
||||
*r_id = mat_in_ubo(storage, &r_ubo);
|
||||
}
|
||||
|
||||
static void hair_ubo_mat_from_object(Object *ob, CLAY_HAIR_UBO_Material *r_ubo)
|
||||
static void hair_ubo_mat_from_object(Object *ob, CLAY_HAIR_UBO_Material *r_ubo)
|
||||
{
|
||||
IDProperty *props = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_CLAY);
|
||||
|
||||
/* Default Settings */
|
||||
int matcap_icon = BKE_collection_engine_property_value_get_int(props, "matcap_icon");
|
||||
float matcap_rot = BKE_collection_engine_property_value_get_float(props, "matcap_rotation");
|
||||
float matcap_hue = BKE_collection_engine_property_value_get_float(props, "matcap_hue");
|
||||
float matcap_sat = BKE_collection_engine_property_value_get_float(props, "matcap_saturation");
|
||||
float matcap_val = BKE_collection_engine_property_value_get_float(props, "matcap_value");
|
||||
float hair_randomness = BKE_collection_engine_property_value_get_float(props, "hair_brightness_randomness");
|
||||
int matcap_icon = BKE_collection_engine_property_value_get_int(props, "matcap_icon");
|
||||
|
||||
memset(r_ubo, 0x0, sizeof(*r_ubo));
|
||||
|
||||
|
@ -676,25 +722,55 @@ static void hair_ubo_mat_from_object(Object *ob, CLAY_HAIR_UBO_Material *r_ubo)
|
|||
r_ubo->matcap_id = matcap_to_index(matcap_icon);
|
||||
}
|
||||
|
||||
static DRWShadingGroup *CLAY_object_shgrp_get(
|
||||
CLAY_Data *vedata, Object *ob, CLAY_StorageList *stl, CLAY_PassList *psl, bool use_flat)
|
||||
static DRWShadingGroup *CLAY_object_shgrp_get(CLAY_Data *vedata, Object *ob, bool use_flat, bool cull)
|
||||
{
|
||||
DRWShadingGroup **shgrps = use_flat ? stl->storage->shgrps_flat : stl->storage->shgrps;
|
||||
CLAY_UBO_Material mat_ubo_test;
|
||||
bool prepass; int id;
|
||||
CLAY_PassList *psl = vedata->psl;
|
||||
CLAY_Storage *storage = vedata->stl->storage;
|
||||
DRWShadingGroup **shgrps;
|
||||
DRWPass *pass; GPUShader *sh;
|
||||
|
||||
ubo_mat_from_object(ob, &mat_ubo_test, &stl->g_data->enable_ao);
|
||||
ubo_mat_from_object(storage, ob, &prepass, &id);
|
||||
|
||||
int id = mat_in_ubo(stl->storage, &mat_ubo_test);
|
||||
if (prepass) {
|
||||
if (use_flat) {
|
||||
shgrps = storage->shgrps_pre_flat;
|
||||
pass = (cull) ? psl->clay_flat_pre_cull_ps : psl->clay_flat_pre_ps;
|
||||
sh = e_data.clay_prepass_flat_sh;
|
||||
}
|
||||
else {
|
||||
shgrps = storage->shgrps_pre;
|
||||
pass = (cull) ? psl->clay_pre_cull_ps : psl->clay_pre_ps;
|
||||
sh = e_data.clay_prepass_sh;
|
||||
}
|
||||
|
||||
if (shgrps[id] == NULL) {
|
||||
shgrps[id] = CLAY_shgroup_create(
|
||||
vedata, use_flat ? psl->clay_pass_flat : psl->clay_pass, &e_data.ubo_mat_idxs[id], use_flat);
|
||||
if (shgrps[id] == NULL) {
|
||||
shgrps[id] = CLAY_shgroup_deferred_prepass_create(pass, sh, id);
|
||||
}
|
||||
|
||||
vedata->stl->g_data->enable_deferred_path = true;
|
||||
}
|
||||
else {
|
||||
if (use_flat) {
|
||||
shgrps = storage->shgrps_flat;
|
||||
pass = (cull) ? psl->clay_flat_cull_ps : psl->clay_flat_ps;
|
||||
sh = e_data.clay_flat_sh;
|
||||
}
|
||||
else {
|
||||
shgrps = storage->shgrps;
|
||||
pass = (cull) ? psl->clay_cull_ps : psl->clay_ps;
|
||||
sh = e_data.clay_sh;
|
||||
}
|
||||
|
||||
if (shgrps[id] == NULL) {
|
||||
shgrps[id] = CLAY_shgroup_create(pass, sh, id);
|
||||
}
|
||||
}
|
||||
|
||||
return shgrps[id];
|
||||
}
|
||||
|
||||
static DRWShadingGroup *CLAY_hair_shgrp_get(CLAY_Data *vedata, Object *ob, CLAY_StorageList *stl, CLAY_PassList *psl)
|
||||
static DRWShadingGroup *CLAY_hair_shgrp_get(CLAY_Data *UNUSED(vedata), Object *ob, CLAY_StorageList *stl, CLAY_PassList *psl)
|
||||
{
|
||||
DRWShadingGroup **hair_shgrps = stl->storage->hair_shgrps;
|
||||
|
||||
|
@ -704,54 +780,45 @@ static DRWShadingGroup *CLAY_hair_shgrp_get(CLAY_Data *vedata, Object *ob, CLAY_
|
|||
int hair_id = hair_mat_in_ubo(stl->storage, &hair_mat_ubo_test);
|
||||
|
||||
if (hair_shgrps[hair_id] == NULL) {
|
||||
hair_shgrps[hair_id] = CLAY_hair_shgroup_create(vedata, psl->hair_pass, &e_data.ubo_mat_idxs[hair_id]);
|
||||
hair_shgrps[hair_id] = CLAY_hair_shgroup_create(psl->hair_pass, hair_id);
|
||||
}
|
||||
|
||||
return hair_shgrps[hair_id];
|
||||
}
|
||||
|
||||
static DRWShadingGroup *CLAY_object_shgrp_default_mode_get(
|
||||
CLAY_Data *vedata, Object *ob, CLAY_StorageList *stl, CLAY_PassList *psl)
|
||||
{
|
||||
bool use_flat = DRW_object_is_flat_normal(ob);
|
||||
return CLAY_object_shgrp_get(vedata, ob, stl, psl, use_flat);
|
||||
}
|
||||
|
||||
static void clay_cache_init(void *vedata)
|
||||
{
|
||||
CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
|
||||
CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
|
||||
|
||||
if (!stl->g_data) {
|
||||
/* Alloc transient pointers */
|
||||
stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
|
||||
}
|
||||
const bool multisample = false;
|
||||
|
||||
/* Disable AO unless a material needs it. */
|
||||
stl->g_data->enable_ao = false;
|
||||
stl->g_data->enable_deferred_path = false;
|
||||
|
||||
/* Depth Pass */
|
||||
/* Reset UBO datas, shgrp pointers and material id counters. */
|
||||
memset(stl->storage, 0, sizeof(*stl->storage));
|
||||
|
||||
/* Solid Passes */
|
||||
{
|
||||
psl->depth_pass = DRW_pass_create("Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
|
||||
stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass);
|
||||
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
|
||||
psl->clay_ps = DRW_pass_create("Clay", state);
|
||||
psl->clay_cull_ps = DRW_pass_create("Clay Culled", state | DRW_STATE_CULL_BACK);
|
||||
psl->clay_flat_ps = DRW_pass_create("Clay Flat", state);
|
||||
psl->clay_flat_cull_ps = DRW_pass_create("Clay Flat Culled", state | DRW_STATE_CULL_BACK);
|
||||
|
||||
psl->depth_pass_cull = DRW_pass_create(
|
||||
"Depth Pass Cull",
|
||||
DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_CULL_BACK);
|
||||
stl->g_data->depth_shgrp_cull = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass_cull);
|
||||
}
|
||||
DRWState prepass_state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS |
|
||||
((multisample) ? DRW_STATE_WRITE_STENCIL : 0);
|
||||
DRWState prepass_cull_state = prepass_state | DRW_STATE_CULL_BACK;
|
||||
psl->clay_pre_ps = DRW_pass_create("Clay Deferred Pre", prepass_state);
|
||||
psl->clay_pre_cull_ps = DRW_pass_create("Clay Deferred Pre Culled", prepass_cull_state);
|
||||
psl->clay_flat_pre_ps = DRW_pass_create("Clay Deferred Flat Pre", prepass_state);
|
||||
psl->clay_flat_pre_cull_ps = DRW_pass_create("Clay Deferred Flat Pre Culled", prepass_cull_state);
|
||||
|
||||
/* Clay Pass */
|
||||
{
|
||||
psl->clay_pass = DRW_pass_create("Clay Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
|
||||
stl->storage->ubo_current_id = 0;
|
||||
memset(stl->storage->shgrps, 0, sizeof(DRWShadingGroup *) * MAX_CLAY_MAT);
|
||||
}
|
||||
DRWState deferred_state = DRW_STATE_WRITE_COLOR | ((multisample) ? DRW_STATE_STENCIL_EQUAL : 0);
|
||||
psl->clay_deferred_ps = DRW_pass_create("Clay Deferred Shading", deferred_state);
|
||||
|
||||
/* Clay Pass (Flat) */
|
||||
{
|
||||
psl->clay_pass_flat = DRW_pass_create("Clay Pass Flat", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
|
||||
memset(stl->storage->shgrps_flat, 0, sizeof(DRWShadingGroup *) * MAX_CLAY_MAT);
|
||||
DRWShadingGroup *grp = CLAY_shgroup_deferred_shading_create(psl->clay_deferred_ps, stl->g_data);
|
||||
DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
|
||||
}
|
||||
|
||||
/* Hair Pass */
|
||||
|
@ -759,8 +826,6 @@ static void clay_cache_init(void *vedata)
|
|||
psl->hair_pass = DRW_pass_create(
|
||||
"Hair Pass",
|
||||
DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_WIRE);
|
||||
stl->storage->hair_ubo_current_id = 0;
|
||||
memset(stl->storage->hair_shgrps, 0, sizeof(DRWShadingGroup *) * MAX_CLAY_MAT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -795,9 +860,6 @@ static void clay_cache_populate_particles(void *vedata, Object *ob)
|
|||
|
||||
static void clay_cache_populate(void *vedata, Object *ob)
|
||||
{
|
||||
CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
|
||||
CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
|
||||
|
||||
DRWShadingGroup *clay_shgrp;
|
||||
|
||||
if (!DRW_object_is_renderable(ob))
|
||||
|
@ -825,26 +887,9 @@ static void clay_cache_populate(void *vedata, Object *ob)
|
|||
IDProperty *ces_mode_ob = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_OBJECT, "");
|
||||
const bool do_cull = BKE_collection_engine_property_value_get_bool(ces_mode_ob, "show_backface_culling");
|
||||
const bool is_sculpt_mode = is_active && (draw_ctx->object_mode & OB_MODE_SCULPT) != 0;
|
||||
const bool is_default_mode_shader = is_sculpt_mode;
|
||||
const bool use_flat = is_sculpt_mode && DRW_object_is_flat_normal(ob);
|
||||
|
||||
/* Depth Prepass */
|
||||
{
|
||||
DRWShadingGroup *depth_shgrp = do_cull ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp;
|
||||
if (is_sculpt_mode) {
|
||||
DRW_shgroup_call_sculpt_add(depth_shgrp, ob, ob->obmat);
|
||||
}
|
||||
else {
|
||||
DRW_shgroup_call_object_add(depth_shgrp, geom, ob);
|
||||
}
|
||||
}
|
||||
|
||||
/* Shading */
|
||||
if (is_default_mode_shader) {
|
||||
clay_shgrp = CLAY_object_shgrp_default_mode_get(vedata, ob, stl, psl);
|
||||
}
|
||||
else {
|
||||
clay_shgrp = CLAY_object_shgrp_get(vedata, ob, stl, psl, false);
|
||||
}
|
||||
clay_shgrp = CLAY_object_shgrp_get(vedata, ob, use_flat, do_cull);
|
||||
|
||||
if (is_sculpt_mode) {
|
||||
DRW_shgroup_call_sculpt_add(clay_shgrp, ob, ob->obmat);
|
||||
|
@ -870,37 +915,53 @@ static void clay_draw_scene(void *vedata)
|
|||
CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
|
||||
CLAY_FramebufferList *fbl = ((CLAY_Data *)vedata)->fbl;
|
||||
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
|
||||
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
|
||||
const bool multisample = false;
|
||||
|
||||
/* Pass 1 : Depth pre-pass */
|
||||
if (stl->g_data->enable_ao) {
|
||||
DRW_draw_pass(psl->depth_pass);
|
||||
DRW_draw_pass(psl->depth_pass_cull);
|
||||
}
|
||||
else {
|
||||
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
|
||||
DRW_pass_state_set(psl->clay_pass, state);
|
||||
DRW_pass_state_set(psl->clay_pass_flat, state);
|
||||
}
|
||||
|
||||
/* Pass 2 : Duplicate depth */
|
||||
/* Unless we go for deferred shading we need this to avoid manual depth test and artifacts */
|
||||
if (DRW_state_is_fbo() && stl->g_data->enable_ao) {
|
||||
/* attach temp textures */
|
||||
DRW_framebuffer_texture_attach(fbl->dupli_depth, e_data.depth_dup, 0, 0);
|
||||
|
||||
DRW_framebuffer_blit(dfbl->default_fb, fbl->dupli_depth, true, false);
|
||||
|
||||
/* detach temp textures */
|
||||
DRW_framebuffer_texture_detach(e_data.depth_dup);
|
||||
|
||||
/* restore default fb */
|
||||
DRW_framebuffer_bind(dfbl->default_fb);
|
||||
}
|
||||
|
||||
/* Pass 3 : Shading */
|
||||
DRW_draw_pass(psl->clay_pass);
|
||||
DRW_draw_pass(psl->clay_pass_flat);
|
||||
/* Passes are ordered to have less _potential_ overdraw */
|
||||
DRW_draw_pass(psl->clay_cull_ps);
|
||||
DRW_draw_pass(psl->clay_flat_cull_ps);
|
||||
DRW_draw_pass(psl->clay_ps);
|
||||
DRW_draw_pass(psl->clay_flat_ps);
|
||||
DRW_draw_pass(psl->hair_pass);
|
||||
|
||||
if (stl->g_data->enable_deferred_path) {
|
||||
if (DRW_state_is_fbo()) {
|
||||
DRW_framebuffer_texture_detach(dtxl->depth);
|
||||
DRW_framebuffer_texture_attach(fbl->prepass_fb, dtxl->depth, 0, 0);
|
||||
DRW_framebuffer_texture_attach(fbl->prepass_fb, stl->g_data->normal_tx, 0, 0);
|
||||
DRW_framebuffer_texture_attach(fbl->prepass_fb, stl->g_data->id_tx, 1, 0);
|
||||
DRW_framebuffer_bind(fbl->prepass_fb);
|
||||
/* We need to clear the id texture unfortunately. */
|
||||
DRW_framebuffer_clear(true, false, false, (float[4]){0.0f, 0.0f, 0.0f, 0.0f}, 0.0f);
|
||||
}
|
||||
|
||||
DRW_draw_pass(psl->clay_pre_cull_ps);
|
||||
DRW_draw_pass(psl->clay_flat_pre_cull_ps);
|
||||
DRW_draw_pass(psl->clay_pre_ps);
|
||||
DRW_draw_pass(psl->clay_flat_pre_ps);
|
||||
|
||||
if (DRW_state_is_fbo()) {
|
||||
DRW_framebuffer_texture_detach(dtxl->depth);
|
||||
|
||||
if (multisample) {
|
||||
/* For multisample, we need to copy the depth tex (all samples). */
|
||||
DRW_framebuffer_texture_attach(fbl->dupli_depth_fb, stl->g_data->depth_dup, 0, 0);
|
||||
DRW_framebuffer_blit(dfbl->default_fb, fbl->dupli_depth_fb, true, false);
|
||||
DRW_framebuffer_texture_detach(stl->g_data->depth_dup);
|
||||
}
|
||||
else {
|
||||
stl->g_data->depth_dup = dtxl->depth;
|
||||
}
|
||||
|
||||
DRW_framebuffer_bind(dfbl->default_fb);
|
||||
|
||||
DRW_draw_pass(psl->clay_deferred_ps);
|
||||
|
||||
DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0);
|
||||
DRW_framebuffer_bind(dfbl->default_fb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void clay_layer_collection_settings_create(RenderEngine *UNUSED(engine), IDProperty *props)
|
||||
|
@ -935,6 +996,9 @@ static void clay_engine_free(void)
|
|||
{
|
||||
DRW_SHADER_FREE_SAFE(e_data.clay_sh);
|
||||
DRW_SHADER_FREE_SAFE(e_data.clay_flat_sh);
|
||||
DRW_SHADER_FREE_SAFE(e_data.clay_prepass_flat_sh);
|
||||
DRW_SHADER_FREE_SAFE(e_data.clay_prepass_sh);
|
||||
DRW_SHADER_FREE_SAFE(e_data.clay_deferred_shading_sh);
|
||||
DRW_SHADER_FREE_SAFE(e_data.hair_sh);
|
||||
DRW_TEXTURE_FREE_SAFE(e_data.matcap_array);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
uniform vec2 screenres;
|
||||
uniform sampler2D depthtex;
|
||||
uniform vec2 invscreenres;
|
||||
uniform mat4 WinMatrix;
|
||||
|
||||
/* Matcap */
|
||||
|
@ -33,7 +32,14 @@ layout(std140) uniform material_block {
|
|||
Material matcaps_param[MAX_MATERIAL];
|
||||
};
|
||||
|
||||
#ifdef DEFERRED_SHADING
|
||||
uniform sampler2D depthtex;
|
||||
uniform sampler2D normaltex;
|
||||
uniform isampler2D idtex;
|
||||
int mat_id; /* global */
|
||||
#else
|
||||
uniform int mat_id;
|
||||
#endif
|
||||
|
||||
/* Aliases */
|
||||
#define ssao_samples_num ssao_params.x
|
||||
|
@ -44,10 +50,12 @@ uniform int mat_id;
|
|||
#define matcap_index matcaps_param[mat_id].matcap_hsv_id.w
|
||||
#define matcap_rotation matcaps_param[mat_id].matcap_rot.xy
|
||||
|
||||
#ifdef USE_FLAT_NORMAL
|
||||
#ifndef DEFERRED_SHADING
|
||||
# ifdef USE_FLAT_NORMAL
|
||||
flat in vec3 normal;
|
||||
#else
|
||||
# else
|
||||
in vec3 normal;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
out vec4 fragColor;
|
||||
|
@ -169,24 +177,33 @@ void ssao_factors(
|
|||
out float cavities, out float edges);
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
vec2 screenco = vec2(gl_FragCoord.xy) / screenres;
|
||||
float depth = texture(depthtex, screenco).r;
|
||||
|
||||
vec3 position = get_view_space_from_depth(screenco, depth);
|
||||
/* From http://aras-p.info/texts/CompactNormalStorage.html
|
||||
* Using Method #4: Spheremap Transform */
|
||||
vec3 normal_decode(vec2 enc)
|
||||
{
|
||||
vec2 fenc = enc * 4.0 - 2.0;
|
||||
float f = dot(fenc, fenc);
|
||||
float g = sqrt(1.0 - f / 4.0);
|
||||
vec3 n;
|
||||
n.xy = fenc*g;
|
||||
n.z = 1 - f / 2;
|
||||
return n;
|
||||
}
|
||||
|
||||
vec3 shade(vec3 N, vec3 position, float depth, vec2 screenco)
|
||||
{
|
||||
#ifdef USE_ROTATION
|
||||
/* Rotate texture coordinates */
|
||||
vec2 rotY = vec2(-matcap_rotation.y, matcap_rotation.x);
|
||||
vec2 texco = abs(vec2(dot(normal.xy, matcap_rotation), dot(normal.xy, rotY)) * .49 + 0.5);
|
||||
vec2 texco = abs(vec2(dot(N.xy, matcap_rotation), dot(N.xy, rotY)) * .49 + 0.5);
|
||||
#else
|
||||
vec2 texco = abs(normal.xy * .49 + 0.5);
|
||||
vec2 texco = abs(N.xy * .49 + 0.5);
|
||||
#endif
|
||||
vec3 col = texture(matcaps, vec3(texco, matcap_index)).rgb;
|
||||
|
||||
#ifdef USE_AO
|
||||
float cavity, edges;
|
||||
ssao_factors(depth, normal, position, screenco, cavity, edges);
|
||||
float cavity = 0.0, edges = 0.0;
|
||||
ssao_factors(depth, N, position, screenco, cavity, edges);
|
||||
|
||||
col *= mix(vec3(1.0), matcaps_color[int(matcap_index)].rgb, cavity);
|
||||
#endif
|
||||
|
@ -200,5 +217,35 @@ void main() {
|
|||
col *= edges + 1.0;
|
||||
#endif
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 screenco = vec2(gl_FragCoord.xy) * invscreenres;
|
||||
|
||||
#ifdef DEFERRED_SHADING
|
||||
mat_id = texture(idtex, screenco).r;
|
||||
|
||||
/* early out (manual stencil test) */
|
||||
if (mat_id == 0)
|
||||
discard;
|
||||
|
||||
float depth = texture(depthtex, screenco).r;
|
||||
vec3 N = normal_decode(texture(normaltex, screenco).rg);
|
||||
/* see the prepass for explanations. */
|
||||
if (mat_id < 0) {
|
||||
N = -N;
|
||||
}
|
||||
mat_id = abs(mat_id) - 1;
|
||||
#else
|
||||
float depth = gl_FragCoord.z;
|
||||
vec3 N = normal;
|
||||
#endif
|
||||
|
||||
vec3 position = get_view_space_from_depth(screenco, depth);
|
||||
|
||||
vec3 col = shade(N, position, depth, screenco);
|
||||
|
||||
fragColor = vec4(col, 1.0);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
uniform int mat_id;
|
||||
|
||||
#ifdef USE_FLAT_NORMAL
|
||||
flat in vec3 normal;
|
||||
#else
|
||||
in vec3 normal;
|
||||
#endif
|
||||
|
||||
layout(location = 0) out vec2 outNormals;
|
||||
layout(location = 1) out int outIndex;
|
||||
|
||||
/* From http://aras-p.info/texts/CompactNormalStorage.html
|
||||
* Using Method #4: Spheremap Transform */
|
||||
vec2 normal_encode(vec3 n)
|
||||
{
|
||||
float p = sqrt(n.z * 8.0 + 8.0);
|
||||
return n.xy / p + 0.5;
|
||||
}
|
||||
|
||||
/* 4x4 bayer matrix prepared for 8bit UNORM precision error. */
|
||||
#define P(x) (((x + 0.5) * (1.0 / 16.0) - 0.5) * (1.0 / 255.0))
|
||||
const mat4 dither_mat = mat4(
|
||||
vec4( P(0.0), P(8.0), P(2.0), P(10.0)),
|
||||
vec4(P(12.0), P(4.0), P(14.0), P(6.0)),
|
||||
vec4( P(3.0), P(11.0), P(1.0), P(9.0)),
|
||||
vec4(P(15.0), P(7.0), P(13.0), P(5.0))
|
||||
);
|
||||
|
||||
void main() {
|
||||
outIndex = (mat_id + 1); /* 0 is clear color */
|
||||
/**
|
||||
* To fix the normal buffer precision issue for backfaces,
|
||||
* we invert normals and use the sign of the index buffer
|
||||
* to tag them, and re-invert in deferred pass.
|
||||
**/
|
||||
vec3 N = (gl_FrontFacing) ? normal : -normal;
|
||||
outIndex = (gl_FrontFacing) ? outIndex : -outIndex;
|
||||
|
||||
outNormals = normal_encode(N);
|
||||
|
||||
/* Dither the output to fight low quality. */
|
||||
ivec2 tx = ivec2(gl_FragCoord.xy) % 4;
|
||||
outNormals += dither_mat[tx.x][tx.y];
|
||||
}
|
Loading…
Reference in New Issue