diff options
Diffstat (limited to 'source/blender/draw/engines/clay/clay.c')
-rw-r--r-- | source/blender/draw/engines/clay/clay.c | 626 |
1 files changed, 263 insertions, 363 deletions
diff --git a/source/blender/draw/engines/clay/clay.c b/source/blender/draw/engines/clay/clay.c index 0572f4a0dc9..23cfe82276f 100644 --- a/source/blender/draw/engines/clay/clay.c +++ b/source/blender/draw/engines/clay/clay.c @@ -22,6 +22,7 @@ #include "DRW_render.h" #include "BKE_icons.h" +#include "BKE_idprop.h" #include "BKE_main.h" #include "BLI_dynstr.h" @@ -42,9 +43,8 @@ extern char datatoc_clay_frag_glsl[]; extern char datatoc_clay_vert_glsl[]; extern char datatoc_ssao_alchemy_glsl[]; -extern char datatoc_ssao_groundtruth_glsl[]; -/* Storage */ +/* *********** LISTS *********** */ /* UBOs data needs to be 16 byte aligned (size of vec4) */ /* Reminder : float, int, bool are 4 bytes */ @@ -64,24 +64,6 @@ typedef struct CLAY_UBO_Storage { CLAY_UBO_Material materials[MAX_CLAY_MAT]; } CLAY_UBO_Storage; -static struct CLAY_data { - /* Depth Pre Pass */ - struct GPUShader *depth_sh; - /* Shading Pass */ - struct GPUShader *clay_sh; - - /* Matcap textures */ - struct GPUTexture *matcap_array; - float matcap_colors[24][3]; - - /* Ssao */ - float winmat[4][4]; - float viewvecs[3][4]; - float ssao_params[4]; - struct GPUTexture *jitter_tx; - struct GPUTexture *sampling_tx; -} data = {NULL}; - /* GPUViewport.storage * Is freed everytime the viewport engine changes */ typedef struct CLAY_Storage { @@ -91,52 +73,78 @@ typedef struct CLAY_Storage { DRWShadingGroup *shgrps[MAX_CLAY_MAT]; } CLAY_Storage; -/* Just a serie of int from 0 to MAX_CLAY_MAT-1 */ -static int ubo_mat_idxs[MAX_CLAY_MAT] = {0}; - /* keep it under MAX_STORAGE */ typedef struct CLAY_StorageList { struct CLAY_Storage *storage; struct GPUUniformBuffer *mat_ubo; + struct g_data *g_data; } CLAY_StorageList; /* keep it under MAX_BUFFERS */ -typedef struct CLAY_FramebufferList{ +typedef struct CLAY_FramebufferList { /* default */ struct GPUFrameBuffer *default_fb; /* engine specific */ - struct GPUFrameBuffer *downsample_depth; + struct GPUFrameBuffer *dupli_depth; } CLAY_FramebufferList; /* keep it under MAX_TEXTURES */ -typedef struct CLAY_TextureList{ +typedef struct CLAY_TextureList { /* default */ struct GPUTexture *color; struct GPUTexture *depth; /* engine specific */ - struct GPUTexture *depth_low; + struct GPUTexture *depth_dup; } CLAY_TextureList; -/* for clarity follow the same layout as CLAY_TextureList */ -enum { - SCENE_COLOR, - SCENE_DEPTH, - SCENE_DEPTH_LOW, -}; - /* keep it under MAX_PASSES */ -typedef struct CLAY_PassList{ - /* default */ - struct DRWPass *non_meshes_pass; - struct DRWPass *ob_center_pass; - /* engine specific */ +typedef struct CLAY_PassList { struct DRWPass *depth_pass; + struct DRWPass *depth_pass_cull; struct DRWPass *clay_pass; - struct DRWPass *wire_overlay_pass; - struct DRWPass *wire_outline_pass; + struct g_data *g_data; } CLAY_PassList; -//#define GTAO +typedef struct CLAY_Data { + void *engine_type; + CLAY_FramebufferList *fbl; + CLAY_TextureList *txl; + CLAY_PassList *psl; + CLAY_StorageList *stl; +} CLAY_Data; + +/* *********** STATIC *********** */ + +static struct { + /* Depth Pre Pass */ + struct GPUShader *depth_sh; + /* Shading Pass */ + struct GPUShader *clay_sh; + + /* Matcap textures */ + struct GPUTexture *matcap_array; + float matcap_colors[24][3]; + + /* Ssao */ + float winmat[4][4]; + float viewvecs[3][4]; + float ssao_params[4]; + int cached_sample_num; + struct GPUTexture *jitter_tx; + struct GPUTexture *sampling_tx; + + /* Just a serie of int from 0 to MAX_CLAY_MAT-1 */ + int ubo_mat_idxs[MAX_CLAY_MAT]; +} e_data = {NULL}; /* Engine data */ + +typedef struct g_data { + DRWShadingGroup *depth_shgrp; + DRWShadingGroup *depth_shgrp_select; + DRWShadingGroup *depth_shgrp_active; + DRWShadingGroup *depth_shgrp_cull; + DRWShadingGroup *depth_shgrp_cull_select; + DRWShadingGroup *depth_shgrp_cull_active; +} g_data; /* Transient data */ /* Functions */ @@ -151,15 +159,15 @@ static void add_icon_to_rect(PreviewImage *prv, float *final_rect, int layer) /* Find overall color */ for (int y = 0; y < 4; ++y) { for (int x = 0; x < 4; ++x) { - data.matcap_colors[layer][0] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 0]; - data.matcap_colors[layer][1] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 1]; - data.matcap_colors[layer][2] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 2]; + e_data.matcap_colors[layer][0] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 0]; + e_data.matcap_colors[layer][1] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 1]; + e_data.matcap_colors[layer][2] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 2]; } } - data.matcap_colors[layer][0] /= 16.0f * 2.0f; /* the * 2 is to darken for shadows */ - data.matcap_colors[layer][1] /= 16.0f * 2.0f; - data.matcap_colors[layer][2] /= 16.0f * 2.0f; + e_data.matcap_colors[layer][0] /= 16.0f * 2.0f; /* the * 2 is to darken for shadows */ + e_data.matcap_colors[layer][1] /= 16.0f * 2.0f; + e_data.matcap_colors[layer][2] /= 16.0f * 2.0f; } static struct GPUTexture *load_matcaps(PreviewImage *prv[24], int nbr) @@ -237,56 +245,22 @@ static struct GPUTexture *create_jitter_texture(void) /* TODO replace by something more evenly distributed like blue noise */ for (i = 0; i < 64 * 64; i++) { -#ifdef GTAO - jitter[i][0] = BLI_frand(); - jitter[i][1] = BLI_frand(); -#else jitter[i][0] = 2.0f * BLI_frand() - 1.0f; jitter[i][1] = 2.0f * BLI_frand() - 1.0f; normalize_v2(jitter[i]); -#endif } return DRW_texture_create_2D(64, 64, DRW_TEX_RG_16, DRW_TEX_FILTER | DRW_TEX_WRAP, &jitter[0][0]); } -static void clay_material_settings_init(MaterialEngineSettingsClay *ma) -{ - ma->matcap_icon = ICON_MATCAP_01; - ma->matcap_rot = 0.0f; - ma->matcap_hue = 0.5f; - ma->matcap_sat = 0.5f; - ma->matcap_val = 0.5f; - ma->ssao_distance = 0.2; - ma->ssao_attenuation = 1.0f; - ma->ssao_factor_cavity = 1.0f; - ma->ssao_factor_edge = 1.0f; -} - -RenderEngineSettings *CLAY_render_settings_create(void) +static void CLAY_engine_init(void *vedata) { - RenderEngineSettingsClay *settings = MEM_callocN(sizeof(RenderEngineSettingsClay), "RenderEngineSettingsClay"); + CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl; + CLAY_TextureList *txl = ((CLAY_Data *)vedata)->txl; + CLAY_FramebufferList *fbl = ((CLAY_Data *)vedata)->fbl; - clay_material_settings_init((MaterialEngineSettingsClay *)settings); - - settings->ssao_samples = 32; - - return (RenderEngineSettings *)settings; -} - -MaterialEngineSettings *CLAY_material_settings_create(void) -{ - MaterialEngineSettingsClay *settings = MEM_callocN(sizeof(MaterialEngineSettingsClay), "MaterialEngineSettingsClay"); - - clay_material_settings_init(settings); - - return (MaterialEngineSettings *)settings; -} - -static void CLAY_engine_init(CLAY_StorageList *stl) -{ /* Create Texture Array */ - if (!data.matcap_array) { + if (!e_data.matcap_array) { PreviewImage *prv[24]; /* For now use all of the 24 internal matcaps */ /* TODO only load used matcaps */ @@ -315,27 +289,22 @@ static void CLAY_engine_init(CLAY_StorageList *stl) prv[22] = UI_icon_to_preview(ICON_MATCAP_23); prv[23] = UI_icon_to_preview(ICON_MATCAP_24); - data.matcap_array = load_matcaps(prv, 24); + e_data.matcap_array = load_matcaps(prv, 24); } /* AO Jitter */ - if (!data.jitter_tx) { - data.jitter_tx = create_jitter_texture(); + if (!e_data.jitter_tx) { + e_data.jitter_tx = create_jitter_texture(); } - /* AO Samples */ - /* TODO use hammersley sequence */ - if (!data.sampling_tx) { - data.sampling_tx = create_spiral_sample_texture(500); - } /* Depth prepass */ - if (!data.depth_sh) { - data.depth_sh = DRW_shader_create_3D_depth_only(); + if (!e_data.depth_sh) { + e_data.depth_sh = DRW_shader_create_3D_depth_only(); } /* Shading pass */ - if (!data.clay_sh) { + if (!e_data.clay_sh) { DynStr *ds = BLI_dynstr_new(); const char *max_mat = "#define MAX_MATERIAL 512\n" @@ -345,15 +314,11 @@ static void CLAY_engine_init(CLAY_StorageList *stl) char *matcap_with_ao; BLI_dynstr_append(ds, datatoc_clay_frag_glsl); -#ifdef GTAO - BLI_dynstr_append(ds, datatoc_ssao_groundtruth_glsl); -#else BLI_dynstr_append(ds, datatoc_ssao_alchemy_glsl); -#endif matcap_with_ao = BLI_dynstr_get_cstring(ds); - data.clay_sh = DRW_shader_create(datatoc_clay_vert_glsl, NULL, matcap_with_ao, max_mat); + e_data.clay_sh = DRW_shader_create(datatoc_clay_vert_glsl, NULL, matcap_with_ao, max_mat); BLI_dynstr_free(ds); MEM_freeN(matcap_with_ao); @@ -367,86 +332,103 @@ static void CLAY_engine_init(CLAY_StorageList *stl) stl->mat_ubo = DRW_uniformbuffer_create(sizeof(CLAY_UBO_Storage), NULL); } - if (ubo_mat_idxs[1] == 0) { + if (e_data.ubo_mat_idxs[1] == 0) { /* Just int to have pointers to them */ for (int i = 0; i < MAX_CLAY_MAT; ++i) { - ubo_mat_idxs[i] = i; + e_data.ubo_mat_idxs[i] = i; } } -} -static void CLAY_ssao_setup(void) -{ - float invproj[4][4]; - float dfdyfacs[2]; - bool is_persp = DRW_viewport_is_persp_get(); - /* view vectors for the corners of the view frustum. Can be used to recreate the world space position easily */ - float viewvecs[3][4] = { - {-1.0f, -1.0f, -1.0f, 1.0f}, - {1.0f, -1.0f, -1.0f, 1.0f}, - {-1.0f, 1.0f, -1.0f, 1.0f} - }; - int i; - float *size = DRW_viewport_size_get(); - RenderEngineSettingsClay *settings = DRW_render_settings_get(NULL, RE_engine_id_BLENDER_CLAY); - - DRW_get_dfdy_factors(dfdyfacs); - - data.ssao_params[0] = settings->ssao_samples; - data.ssao_params[1] = size[0] / 64.0; - data.ssao_params[2] = size[1] / 64.0; - data.ssao_params[3] = dfdyfacs[1]; /* dfdy sign for offscreen */ - - /* invert the view matrix */ - DRW_viewport_matrix_get(data.winmat, DRW_MAT_WIN); - invert_m4_m4(invproj, data.winmat); - - /* convert the view vectors to view space */ - for (i = 0; i < 3; i++) { - mul_m4_v4(invproj, viewvecs[i]); - /* normalized trick see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */ - mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]); - if (is_persp) - mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]); - viewvecs[i][3] = 1.0; - - copy_v4_v4(data.viewvecs[i], viewvecs[i]); + { + float *viewport_size = DRW_viewport_size_get(); + DRWFboTexture tex = {&txl->depth_dup, DRW_BUF_DEPTH_24}; + DRW_framebuffer_init(&fbl->dupli_depth, + (int)viewport_size[0], (int)viewport_size[1], + &tex, 1); } - /* we need to store the differences */ - data.viewvecs[1][0] -= data.viewvecs[0][0]; - data.viewvecs[1][1] = data.viewvecs[2][1] - data.viewvecs[0][1]; + /* SSAO setup */ + { + int ssao_samples = 32; /* XXX get from render settings */ + float invproj[4][4]; + float dfdyfacs[2]; + bool is_persp = DRW_viewport_is_persp_get(); + /* view vectors for the corners of the view frustum. Can be used to recreate the world space position easily */ + float viewvecs[3][4] = { + {-1.0f, -1.0f, -1.0f, 1.0f}, + {1.0f, -1.0f, -1.0f, 1.0f}, + {-1.0f, 1.0f, -1.0f, 1.0f} + }; + int i; + float *size = DRW_viewport_size_get(); + + DRW_get_dfdy_factors(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 */ + + /* invert the view matrix */ + DRW_viewport_matrix_get(e_data.winmat, DRW_MAT_WIN); + invert_m4_m4(invproj, e_data.winmat); + + /* convert the view vectors to view space */ + for (i = 0; i < 3; i++) { + mul_m4_v4(invproj, viewvecs[i]); + /* normalized trick see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */ + mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]); + if (is_persp) + mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]); + viewvecs[i][3] = 1.0; + + copy_v4_v4(e_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]; + + /* 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]; + } - /* 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]); - data.viewvecs[1][2] = vec_far[2] - data.viewvecs[0][2]; + /* AO Samples Tex */ + if (e_data.sampling_tx && (e_data.cached_sample_num != ssao_samples)) { + DRW_texture_free(e_data.sampling_tx); + e_data.sampling_tx = NULL; + } + + if (!e_data.sampling_tx) { + e_data.sampling_tx = create_spiral_sample_texture(ssao_samples); + e_data.cached_sample_num = ssao_samples; + } } } -static DRWShadingGroup *CLAY_shgroup_create(DRWPass *pass, int *material_id) +static DRWShadingGroup *CLAY_shgroup_create(CLAY_Data *vedata, DRWPass *pass, int *material_id) { + CLAY_TextureList *txl = ((CLAY_Data *)vedata)->txl; const int depthloc = 0, matcaploc = 1, jitterloc = 2, sampleloc = 3; - //CLAY_UBO_Material *mat = &data.mat_storage.materials[0]; - DRWShadingGroup *grp = DRW_shgroup_create(data.clay_sh, pass); + DRWShadingGroup *grp = DRW_shgroup_create(e_data.clay_sh, pass); DRW_shgroup_uniform_vec2(grp, "screenres", DRW_viewport_size_get(), 1); - DRW_shgroup_uniform_buffer(grp, "depthtex", SCENE_DEPTH, depthloc); - DRW_shgroup_uniform_texture(grp, "matcaps", data.matcap_array, matcaploc); - DRW_shgroup_uniform_mat4(grp, "WinMatrix", (float *)data.winmat); - DRW_shgroup_uniform_vec4(grp, "viewvecs", (float *)data.viewvecs, 3); - DRW_shgroup_uniform_vec4(grp, "ssao_params", data.ssao_params, 1); - DRW_shgroup_uniform_vec3(grp, "matcaps_color", (float *)data.matcap_colors, 24); + DRW_shgroup_uniform_buffer(grp, "depthtex", &txl->depth_dup, depthloc); + DRW_shgroup_uniform_texture(grp, "matcaps", e_data.matcap_array, matcaploc); + DRW_shgroup_uniform_mat4(grp, "WinMatrix", (float *)e_data.winmat); + DRW_shgroup_uniform_vec4(grp, "viewvecs", (float *)e_data.viewvecs, 3); + DRW_shgroup_uniform_vec4(grp, "ssao_params", e_data.ssao_params, 1); + DRW_shgroup_uniform_vec3(grp, "matcaps_color", (float *)e_data.matcap_colors, 24); DRW_shgroup_uniform_int(grp, "mat_id", material_id, 1); -#ifndef GTAO - DRW_shgroup_uniform_texture(grp, "ssao_jitter", data.jitter_tx, jitterloc); - DRW_shgroup_uniform_texture(grp, "ssao_samples", data.sampling_tx, sampleloc); -#endif + DRW_shgroup_uniform_texture(grp, "ssao_jitter", e_data.jitter_tx, jitterloc); + DRW_shgroup_uniform_texture(grp, "ssao_samples", e_data.sampling_tx, sampleloc); return grp; } @@ -457,8 +439,7 @@ static int search_mat_to_ubo(CLAY_Storage *storage, float matcap_rot, float matc { /* For now just use a linear search and test all parameters */ /* TODO make a hash table */ - for (int i = 0; i < storage->ubo_current_id; ++i) - { + for (int i = 0; i < storage->ubo_current_id; ++i) { CLAY_UBO_Material *ubo = &storage->mat_storage.materials[i]; if ((ubo->matcap_rot[0] == cosf(matcap_rot * 3.14159f * 2.0f)) && @@ -492,7 +473,8 @@ static int push_mat_to_ubo(CLAY_Storage *storage, float matcap_rot, float matcap ubo->matcap_hsv[1] = matcap_sat * 2.0f; ubo->matcap_hsv[2] = matcap_val * 2.0f; - ubo->ssao_params_var[0] = ssao_distance; + /* small optimisation : make samples not spread if we don't need ssao */ + ubo->ssao_params_var[0] = (ssao_factor_cavity + ssao_factor_edge > 0.0f) ? ssao_distance : 0.0f; ubo->ssao_params_var[1] = ssao_factor_cavity; ubo->ssao_params_var[2] = ssao_factor_edge; ubo->ssao_params_var[3] = ssao_attenuation; @@ -504,269 +486,187 @@ static int push_mat_to_ubo(CLAY_Storage *storage, float matcap_rot, float matcap return id; } -static int mat_in_ubo(CLAY_Storage *storage, struct GPUUniformBuffer *ubo, DRWPass *pass, - float matcap_rot, float matcap_hue, float matcap_sat, +static int mat_in_ubo(CLAY_Storage *storage, float matcap_rot, float matcap_hue, float matcap_sat, float matcap_val, float ssao_distance, float ssao_factor_cavity, float ssao_factor_edge, float ssao_attenuation, int matcap_icon) { - int id; - /* Search material in UBO */ - id = search_mat_to_ubo(storage, matcap_rot, matcap_hue, matcap_sat, matcap_val, - ssao_distance, ssao_factor_cavity, ssao_factor_edge, - ssao_attenuation, matcap_icon); + int id = search_mat_to_ubo(storage, matcap_rot, matcap_hue, matcap_sat, matcap_val, + ssao_distance, ssao_factor_cavity, ssao_factor_edge, + ssao_attenuation, matcap_icon); /* if not found create it */ if (id == -1) { id = push_mat_to_ubo(storage, matcap_rot, matcap_hue, matcap_sat, matcap_val, ssao_distance, ssao_factor_cavity, ssao_factor_edge, ssao_attenuation, matcap_icon); - - storage->shgrps[id] = CLAY_shgroup_create(pass, &ubo_mat_idxs[id]); - - /* if it's the first shgrp, pass bind the material UBO */ - if (storage->ubo_current_id == 1) { - DRW_shgroup_uniform_block(storage->shgrps[0], "material_block", ubo, 0); - } } return id; } -/* Safe way to get override values */ -static void override_setting(CollectionEngineSettings *ces, const char *name, void *ret) +static DRWShadingGroup *CLAY_object_shgrp_get(CLAY_Data *vedata, Object *ob, CLAY_StorageList *stl, CLAY_PassList *psl) { - CollectionEngineProperty *cep = BKE_collection_engine_property_get(ces, name); - - if (cep == NULL) { - return; - } + DRWShadingGroup **shgrps = stl->storage->shgrps; + IDProperty *props = BKE_object_collection_engine_get(ob, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_CLAY); - if ((cep->flag & COLLECTION_PROP_USE) == 0) { - return; + /* Default Settings */ + 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 ssao_distance = BKE_collection_engine_property_value_get_float(props, "ssao_distance"); + 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"); + + int id = mat_in_ubo(stl->storage, matcap_rot, matcap_hue, matcap_sat, matcap_val, + ssao_distance, ssao_factor_cavity, ssao_factor_edge, + ssao_attenuation, matcap_icon); + + if (shgrps[id] == NULL) { + shgrps[id] = CLAY_shgroup_create(vedata, psl->clay_pass, &e_data.ubo_mat_idxs[id]); + /* if it's the first shgrp, pass bind the material UBO */ + if (stl->storage->ubo_current_id == 1) { + DRW_shgroup_uniform_block(shgrps[0], "material_block", stl->mat_ubo, 0); + } } - if (cep->type == COLLECTION_PROP_TYPE_INT) { - CollectionEnginePropertyInt *prop = (CollectionEnginePropertyInt *)cep; - *((int *)ret) = prop->value; - } - else { - CollectionEnginePropertyFloat *prop = (CollectionEnginePropertyFloat *)cep; - *((float *)ret) = prop->value; - } + return shgrps[id]; } -static DRWShadingGroup *CLAY_object_shgrp_get(Object *ob, CLAY_StorageList *stl, DRWPass *pass) +static void CLAY_cache_init(void *vedata) { - MaterialEngineSettingsClay *settings = DRW_render_settings_get(NULL, RE_engine_id_BLENDER_CLAY); - CollectionEngineSettings *ces = ob->collection_settings; + CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl; + CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl; - /* Default Settings */ - float matcap_rot = settings->matcap_rot; - float matcap_hue = settings->matcap_hue; - float matcap_sat = settings->matcap_sat; - float matcap_val = settings->matcap_val; - float ssao_distance = settings->ssao_distance; - float ssao_factor_cavity = settings->ssao_factor_cavity; - float ssao_factor_edge = settings->ssao_factor_edge; - float ssao_attenuation = settings->ssao_attenuation; - int matcap_icon = settings->matcap_icon; - - /* Override settings */ - if (ces) { - override_setting(ces, "matcap_rotation", &matcap_rot); - override_setting(ces, "matcap_hue", &matcap_hue); - override_setting(ces, "matcap_saturation", &matcap_sat); - override_setting(ces, "matcap_value", &matcap_val); - override_setting(ces, "ssao_distance", &ssao_distance); - override_setting(ces, "ssao_factor_cavity", &ssao_factor_cavity); - override_setting(ces, "ssao_factor_edge", &ssao_factor_edge); - override_setting(ces, "ssao_attenuation", &ssao_attenuation); - override_setting(ces, "matcap_icon", &matcap_icon); - }; - - - int index = mat_in_ubo(stl->storage, stl->mat_ubo, pass, - matcap_rot, matcap_hue, matcap_sat, matcap_val, - ssao_distance, ssao_factor_cavity, ssao_factor_edge, - ssao_attenuation, matcap_icon); - - return stl->storage->shgrps[index]; -} - -static void CLAY_create_cache(CLAY_PassList *passes, CLAY_StorageList *stl, const struct bContext *C) -{ - SceneLayer *sl = CTX_data_scene_layer(C); - DRWShadingGroup *clay_shgrp; - DRWShadingGroup *depth_shgrp; + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(g_data), "g_data"); + } /* Depth Pass */ { - passes->depth_pass = DRW_pass_create("Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS); + 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); - depth_shgrp = DRW_shgroup_create(data.depth_sh, passes->depth_pass); + 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); } /* Clay Pass */ { - passes->clay_pass = DRW_pass_create("Clay Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS); + 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); } +} - /* Object Mode */ - { - DRW_pass_setup_common(&passes->wire_overlay_pass, - &passes->wire_outline_pass, - &passes->non_meshes_pass, - &passes->ob_center_pass); - } - - /* TODO Create hash table of batch based on material id*/ - Object *ob; - DEG_OBJECT_ITER(sl, CLAY_ENGINE, ob); - { - if ((ob->base_flag & BASE_VISIBLED) == 0) { - continue; - } - - struct Batch *geom; - //bool do_outlines; - - switch (ob->type) { - case OB_MESH: - clay_shgrp = CLAY_object_shgrp_get(ob, stl, passes->clay_pass); - geom = DRW_cache_surface_get(ob); +static void CLAY_cache_populate(void *vedata, Object *ob) +{ + CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl; + CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl; - /* Add everything for now */ - DRW_shgroup_call_add(depth_shgrp, geom, ob->obmat); + struct Batch *geom; + DRWShadingGroup *clay_shgrp; - if (clay_shgrp) - DRW_shgroup_call_add(clay_shgrp, geom, ob->obmat); + if (!DRW_is_object_renderable(ob)) + return; - //DRW_shgroup_wire_overlay(passes->wire_overlay_pass, ob); + IDProperty *ces_mode_ob = BKE_object_collection_engine_get(ob, COLLECTION_MODE_OBJECT, ""); + bool do_cull = BKE_collection_engine_property_value_get_bool(ces_mode_ob, "show_backface_culling"); - //do_outlines = ((ob->base_flag & BASE_SELECTED) != 0); - //DRW_shgroup_wire_outline(passes->wire_outline_pass, ob, false, false, do_outlines); + /* TODO all renderable */ + if (ob->type == OB_MESH) { + geom = DRW_cache_surface_get(ob); - /* When encountering a new material : - * - Create new Batch - * - Initialize Batch - * - Push it to the hash table - * - The pass takes care of inserting it - * next to the same shader calls */ + /* Depth Prepass */ + DRW_shgroup_call_add((do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp, geom, ob->obmat); - /* Free hash table */ - break; - case OB_LAMP: - case OB_CAMERA: - case OB_EMPTY: - default: - DRW_shgroup_non_meshes(passes->non_meshes_pass, ob); - break; - } - - DRW_shgroup_object_center(passes->ob_center_pass, ob); - DRW_shgroup_relationship_lines(passes->non_meshes_pass, ob); + /* Shading */ + clay_shgrp = CLAY_object_shgrp_get(vedata, ob, stl, psl); + DRW_shgroup_call_add(clay_shgrp, geom, ob->obmat); } - DEG_OBJECT_ITER_END +} + +static void CLAY_cache_finish(void *vedata) +{ + CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl; DRW_uniformbuffer_update(stl->mat_ubo, &stl->storage->mat_storage); } -static void CLAY_view_draw(RenderEngine *UNUSED(engine), const bContext *context) +static void CLAY_draw_scene(void *vedata) { - /* This function may run for multiple viewports - * so get the current viewport buffers */ - CLAY_FramebufferList *buffers = NULL; - CLAY_TextureList *textures = NULL; - CLAY_PassList *passes = NULL; - CLAY_StorageList *storage = NULL; - - DRW_viewport_init(context, (void **)&buffers, (void **)&textures, (void **)&passes, (void **)&storage); - - CLAY_engine_init(storage); - - /* TODO : tag to refresh by the deps graph */ - /* ideally only refresh when objects are added/removed */ - /* or render properties / materials change */ -#ifdef WITH_VIEWPORT_CACHE_TEST - static bool once = false; -#endif - if (DRW_viewport_cache_is_dirty() -#ifdef WITH_VIEWPORT_CACHE_TEST - && !once -#endif - ) { -#ifdef WITH_VIEWPORT_CACHE_TEST - once = true; -#endif - CLAY_create_cache(passes, storage, context); - } - /* Start Drawing */ - DRW_draw_background(); + CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl; + CLAY_FramebufferList *fbl = ((CLAY_Data *)vedata)->fbl; + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); /* Pass 1 : Depth pre-pass */ - DRW_draw_pass(passes->depth_pass); + DRW_draw_pass(psl->depth_pass); + DRW_draw_pass(psl->depth_pass_cull); - /* Pass 2 (Optionnal) : Separated Downsampled AO */ - DRW_framebuffer_texture_detach(textures->depth); - /* TODO */ + /* Pass 2 : Duplicate depth */ + /* Unless we go for deferred shading we need this to avoid manual depth test and artifacts */ + DRW_framebuffer_blit(dfbl->default_fb, fbl->dupli_depth, true); /* Pass 3 : Shading */ - CLAY_ssao_setup(); - DRW_draw_pass(passes->clay_pass); - - /* Pass 4 : Overlays */ - DRW_framebuffer_texture_attach(buffers->default_fb, textures->depth, 0); - //DRW_draw_pass(passes->wire_overlay_pass); - //DRW_draw_pass(passes->wire_outline_pass); - DRW_draw_pass(passes->non_meshes_pass); - DRW_draw_pass(passes->ob_center_pass); - - /* Always finish by this */ - DRW_state_reset(); + DRW_draw_pass(psl->clay_pass); } -static void CLAY_collection_settings_create(RenderEngine *UNUSED(engine), CollectionEngineSettings *ces) +static void CLAY_collection_settings_create(RenderEngine *UNUSED(engine), IDProperty *props) { - BLI_assert(ces); - BKE_collection_engine_property_add_int(ces, "matcap_icon", ICON_MATCAP_01); - BKE_collection_engine_property_add_int(ces, "type", CLAY_MATCAP_NONE); - BKE_collection_engine_property_add_float(ces, "matcap_rotation", 0.0f); - BKE_collection_engine_property_add_float(ces, "matcap_hue", 0.5f); - BKE_collection_engine_property_add_float(ces, "matcap_saturation", 0.5f); - BKE_collection_engine_property_add_float(ces, "matcap_value", 0.5f); - BKE_collection_engine_property_add_float(ces, "ssao_distance", 0.2f); - BKE_collection_engine_property_add_float(ces, "ssao_attenuation", 1.0f); - BKE_collection_engine_property_add_float(ces, "ssao_factor_cavity", 1.0f); - BKE_collection_engine_property_add_float(ces, "ssao_factor_edge", 1.0f); + BLI_assert(props && + props->type == IDP_GROUP && + props->subtype == IDP_GROUP_SUB_ENGINE_RENDER); + + BKE_collection_engine_property_add_int(props, "matcap_icon", ICON_MATCAP_01); + BKE_collection_engine_property_add_int(props, "type", CLAY_MATCAP_NONE); + BKE_collection_engine_property_add_float(props, "matcap_rotation", 0.0f); + BKE_collection_engine_property_add_float(props, "matcap_hue", 0.5f); + BKE_collection_engine_property_add_float(props, "matcap_saturation", 0.5f); + BKE_collection_engine_property_add_float(props, "matcap_value", 0.5f); + BKE_collection_engine_property_add_float(props, "ssao_distance", 0.2f); + BKE_collection_engine_property_add_float(props, "ssao_attenuation", 1.0f); + BKE_collection_engine_property_add_float(props, "ssao_factor_cavity", 1.0f); + BKE_collection_engine_property_add_float(props, "ssao_factor_edge", 1.0f); } -void clay_engine_free(void) +static void CLAY_engine_free(void) { - /* data.depth_sh Is builtin so it's automaticaly freed */ - if (data.clay_sh) { - DRW_shader_free(data.clay_sh); + if (e_data.clay_sh) { + DRW_shader_free(e_data.clay_sh); } - - if (data.matcap_array) { - DRW_texture_free(data.matcap_array); + if (e_data.matcap_array) { + DRW_texture_free(e_data.matcap_array); } - - if (data.jitter_tx) { - DRW_texture_free(data.jitter_tx); + if (e_data.jitter_tx) { + DRW_texture_free(e_data.jitter_tx); } - - if (data.sampling_tx) { - DRW_texture_free(data.sampling_tx); + if (e_data.sampling_tx) { + DRW_texture_free(e_data.sampling_tx); } } +DrawEngineType draw_engine_clay_type = { + NULL, NULL, + N_("Clay"), + &CLAY_engine_init, + &CLAY_engine_free, + &CLAY_cache_init, + &CLAY_cache_populate, + &CLAY_cache_finish, + NULL, + &CLAY_draw_scene +}; + RenderEngineType viewport_clay_type = { NULL, NULL, CLAY_ENGINE, N_("Clay"), RE_INTERNAL | RE_USE_OGL_PIPELINE, - NULL, NULL, NULL, NULL, &CLAY_view_draw, NULL, &CLAY_collection_settings_create, + NULL, NULL, NULL, NULL, NULL, NULL, &CLAY_collection_settings_create, + &draw_engine_clay_type, {NULL, NULL, NULL} }; |