diff --git a/source/blender/draw/engines/clay/clay_engine.c b/source/blender/draw/engines/clay/clay_engine.c index c2b7a3a7258..4ac54386f61 100644 --- a/source/blender/draw/engines/clay/clay_engine.c +++ b/source/blender/draw/engines/clay/clay_engine.c @@ -104,6 +104,7 @@ typedef struct CLAY_Storage { int ubo_current_id; int hair_ubo_current_id; DRWShadingGroup *shgrps[MAX_CLAY_MAT]; + DRWShadingGroup *shgrps_flat[MAX_CLAY_MAT]; DRWShadingGroup *hair_shgrps[MAX_CLAY_MAT]; } CLAY_Storage; @@ -125,6 +126,7 @@ typedef struct CLAY_PassList { struct DRWPass *depth_pass; struct DRWPass *depth_pass_cull; struct DRWPass *clay_pass; + struct DRWPass *clay_pass_flat; struct DRWPass *hair_pass; } CLAY_PassList; @@ -143,6 +145,7 @@ static struct { struct GPUShader *depth_sh; /* Shading Pass */ struct GPUShader *clay_sh; + struct GPUShader *clay_flat_sh; struct GPUShader *hair_sh; /* Matcap textures */ @@ -338,8 +341,6 @@ static void CLAY_engine_init(void *vedata) /* Shading pass */ if (!e_data.clay_sh) { DynStr *ds = BLI_dynstr_new(); - const char *max_mat = - SHADER_DEFINES; char *matcap_with_ao; BLI_dynstr_append(ds, datatoc_clay_frag_glsl); @@ -347,7 +348,13 @@ 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, max_mat); + e_data.clay_sh = DRW_shader_create( + datatoc_clay_vert_glsl, NULL, matcap_with_ao, + SHADER_DEFINES); + e_data.clay_flat_sh = DRW_shader_create( + datatoc_clay_vert_glsl, NULL, matcap_with_ao, + SHADER_DEFINES + "#define USE_FLAT_NORMAL\n"); BLI_dynstr_free(ds); MEM_freeN(matcap_with_ao); @@ -452,9 +459,9 @@ static void CLAY_engine_init(void *vedata) } } -static DRWShadingGroup *CLAY_shgroup_create(CLAY_Data *UNUSED(vedata), DRWPass *pass, int *material_id) +static DRWShadingGroup *CLAY_shgroup_create(CLAY_Data *UNUSED(vedata), DRWPass *pass, int *material_id, bool use_flat) { - DRWShadingGroup *grp = DRW_shgroup_create(e_data.clay_sh, pass); + 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); @@ -614,9 +621,10 @@ 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) +static DRWShadingGroup *CLAY_object_shgrp_get( + CLAY_Data *vedata, Object *ob, CLAY_StorageList *stl, CLAY_PassList *psl, bool use_flat) { - DRWShadingGroup **shgrps = stl->storage->shgrps; + DRWShadingGroup **shgrps = use_flat ? stl->storage->shgrps_flat : stl->storage->shgrps; CLAY_UBO_Material mat_ubo_test; ubo_mat_from_object(ob, &mat_ubo_test); @@ -624,7 +632,8 @@ static DRWShadingGroup *CLAY_object_shgrp_get(CLAY_Data *vedata, Object *ob, CLA int id = mat_in_ubo(stl->storage, &mat_ubo_test); if (shgrps[id] == NULL) { - shgrps[id] = CLAY_shgroup_create(vedata, psl->clay_pass, &e_data.ubo_mat_idxs[id]); + shgrps[id] = CLAY_shgroup_create( + vedata, use_flat ? psl->clay_pass_flat : psl->clay_pass, &e_data.ubo_mat_idxs[id], use_flat); /* 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); @@ -654,6 +663,13 @@ static DRWShadingGroup *CLAY_hair_shgrp_get(Object *ob, CLAY_StorageList *stl, C 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; @@ -682,6 +698,12 @@ static void CLAY_cache_init(void *vedata) memset(stl->storage->shgrps, 0, sizeof(DRWShadingGroup *) * MAX_CLAY_MAT); } + /* 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); + } + /* Hair Pass */ { psl->hair_pass = DRW_pass_create( @@ -715,6 +737,7 @@ 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 && (ob->mode & OB_MODE_SCULPT) != 0; + const bool is_default_mode_shader = is_sculpt_mode; /* Depth Prepass */ { @@ -728,7 +751,12 @@ static void CLAY_cache_populate(void *vedata, Object *ob) } /* Shading */ - clay_shgrp = CLAY_object_shgrp_get(vedata, ob, stl, psl); + 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); + } if (is_sculpt_mode) { DRW_shgroup_call_sculpt_add(clay_shgrp, ob, ob->obmat); @@ -809,6 +837,7 @@ static void CLAY_draw_scene(void *vedata) /* Pass 3 : Shading */ DRW_draw_pass(psl->clay_pass); + DRW_draw_pass(psl->clay_pass_flat); DRW_draw_pass(psl->hair_pass); } @@ -842,6 +871,7 @@ static void CLAY_scene_layer_settings_create(RenderEngine *UNUSED(engine), IDPro 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.hair_sh); DRW_TEXTURE_FREE_SAFE(e_data.matcap_array); DRW_TEXTURE_FREE_SAFE(e_data.jitter_tx); diff --git a/source/blender/draw/engines/clay/shaders/clay_frag.glsl b/source/blender/draw/engines/clay/shaders/clay_frag.glsl index 8eb0f6e7827..033db365337 100644 --- a/source/blender/draw/engines/clay/shaders/clay_frag.glsl +++ b/source/blender/draw/engines/clay/shaders/clay_frag.glsl @@ -38,7 +38,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 +flat in vec3 normal; +#else in vec3 normal; +#endif + out vec4 fragColor; /* TODO Move this to SSAO modules */ diff --git a/source/blender/draw/engines/clay/shaders/clay_vert.glsl b/source/blender/draw/engines/clay/shaders/clay_vert.glsl index 557445d5ef9..8f8866b3839 100644 --- a/source/blender/draw/engines/clay/shaders/clay_vert.glsl +++ b/source/blender/draw/engines/clay/shaders/clay_vert.glsl @@ -3,7 +3,12 @@ uniform mat3 NormalMatrix; in vec3 pos; in vec3 nor; + +#ifdef USE_FLAT_NORMAL +flat out vec3 normal; +#else out vec3 normal; +#endif void main() { diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index 209584426bf..8d87ec94b5a 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -52,6 +52,7 @@ static struct { char *frag_shader_lib; struct GPUShader *default_lit; + struct GPUShader *default_lit_flat; struct GPUShader *default_world; struct GPUShader *default_background; struct GPUShader *depth_sh; @@ -253,6 +254,12 @@ static void EEVEE_engine_init(void *ved) e_data.default_lit = DRW_shader_create( datatoc_lit_surface_vert_glsl, NULL, frag_str, SHADER_DEFINES "#define MESH_SHADER\n"); + e_data.default_lit_flat = DRW_shader_create( + datatoc_lit_surface_vert_glsl, NULL, frag_str, + SHADER_DEFINES + "#define MESH_SHADER\n" + "#define USE_FLAT_NORMAL\n"); + MEM_freeN(frag_str); } @@ -515,17 +522,32 @@ static void EEVEE_cache_init(void *vedata) DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL; psl->default_pass = DRW_pass_create("Default Shader Pass", state); - stl->g_data->default_lit_grp = DRW_shgroup_create(e_data.default_lit, psl->default_pass); - DRW_shgroup_uniform_block(stl->g_data->default_lit_grp, "light_block", stl->light_ubo); - DRW_shgroup_uniform_block(stl->g_data->default_lit_grp, "shadow_block", stl->shadow_ubo); - DRW_shgroup_uniform_int(stl->g_data->default_lit_grp, "light_count", &stl->lamps->num_light, 1); - DRW_shgroup_uniform_float(stl->g_data->default_lit_grp, "lodMax", &stl->probes->lodmax, 1); - DRW_shgroup_uniform_vec3(stl->g_data->default_lit_grp, "shCoefs[0]", (float *)stl->probes->shcoefs, 9); - DRW_shgroup_uniform_vec3(stl->g_data->default_lit_grp, "cameraPos", e_data.camera_pos, 1); - DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "ltcMat", e_data.ltc_mat); - DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "brdfLut", e_data.brdf_lut); - DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "probeFiltered", txl->probe_pool); - /* NOTE : Adding Shadow Map textures uniform in EEVEE_cache_finish */ + for (uint j = 0; j < 2; j++) { + struct GPUShader *shader; + struct DRWShadingGroup *shgrp; + + if (j == 0) { + shader = e_data.default_lit; + shgrp = DRW_shgroup_create(shader, psl->default_pass); + stl->g_data->default_lit_grp = shgrp; + } + else { + shader = e_data.default_lit_flat; + shgrp = DRW_shgroup_create(shader, psl->default_pass); + stl->g_data->default_lit_grp_flat = shgrp; + } + + DRW_shgroup_uniform_block(shgrp, "light_block", stl->light_ubo); + DRW_shgroup_uniform_block(shgrp, "shadow_block", stl->shadow_ubo); + DRW_shgroup_uniform_int(shgrp, "light_count", &stl->lamps->num_light, 1); + DRW_shgroup_uniform_float(shgrp, "lodMax", &stl->probes->lodmax, 1); + DRW_shgroup_uniform_vec3(shgrp, "shCoefs[0]", (float *)stl->probes->shcoefs, 9); + DRW_shgroup_uniform_vec3(shgrp, "cameraPos", e_data.camera_pos, 1); + DRW_shgroup_uniform_texture(shgrp, "ltcMat", e_data.ltc_mat); + DRW_shgroup_uniform_texture(shgrp, "brdfLut", e_data.brdf_lut); + DRW_shgroup_uniform_texture(shgrp, "probeFiltered", txl->probe_pool); + /* NOTE : Adding Shadow Map textures uniform in EEVEE_cache_finish */ + } } { @@ -558,6 +580,7 @@ static void EEVEE_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 && (ob->mode & OB_MODE_SCULPT) != 0; + const bool is_default_mode_shader = is_sculpt_mode; /* Depth Prepass */ { @@ -573,6 +596,17 @@ static void EEVEE_cache_populate(void *vedata, Object *ob) /* Get per-material split surface */ struct Batch **mat_geom = DRW_cache_object_surface_material_get(ob); if (mat_geom) { + struct GPUShader *default_shader = e_data.default_lit; + struct DRWShadingGroup *default_shgrp = stl->g_data->default_lit_grp; + + if (is_default_mode_shader) { + if (is_sculpt_mode) { + bool use_flat = DRW_object_is_flat_normal(ob); + default_shader = use_flat ? e_data.default_lit_flat : e_data.default_lit; + default_shgrp = use_flat ? stl->g_data->default_lit_grp_flat : stl->g_data->default_lit_grp; + } + } + for (int i = 0; i < MAX2(1, (is_sculpt_mode ? 1 : ob->totcol)); ++i) { Material *ma = give_current_material(ob, i + 1); @@ -610,14 +644,14 @@ static void EEVEE_cache_populate(void *vedata, Object *ob) static float col[3] = {1.0f, 0.0f, 1.0f}; static float half = 0.5f; - shgrp = DRW_shgroup_create(e_data.default_lit, psl->default_pass); + shgrp = DRW_shgroup_create(default_shader, psl->default_pass); DRW_shgroup_uniform_vec3(shgrp, "basecol", col, 1); DRW_shgroup_uniform_float(shgrp, "metallic", &half, 1); DRW_shgroup_uniform_float(shgrp, "specular", &half, 1); DRW_shgroup_uniform_float(shgrp, "roughness", &half, 1); - DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "ltcMat", e_data.ltc_mat); - DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "brdfLut", e_data.brdf_lut); - DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "probeFiltered", txl->probe_pool); + DRW_shgroup_uniform_texture(default_shgrp, "ltcMat", e_data.ltc_mat); + DRW_shgroup_uniform_texture(default_shgrp, "brdfLut", e_data.brdf_lut); + DRW_shgroup_uniform_texture(default_shgrp, "probeFiltered", txl->probe_pool); if (is_sculpt_mode) { DRW_shgroup_call_sculpt_add(shgrp, ob, ob->obmat); @@ -628,14 +662,14 @@ static void EEVEE_cache_populate(void *vedata, Object *ob) } } else { - DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit, psl->default_pass); + DRWShadingGroup *shgrp = DRW_shgroup_create(default_shader, psl->default_pass); DRW_shgroup_uniform_vec3(shgrp, "basecol", &ma->r, 1); DRW_shgroup_uniform_float(shgrp, "metallic", &ma->ray_mirror, 1); DRW_shgroup_uniform_float(shgrp, "specular", &ma->spec, 1); DRW_shgroup_uniform_float(shgrp, "roughness", &ma->gloss_mir, 1); - DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "ltcMat", e_data.ltc_mat); - DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "brdfLut", e_data.brdf_lut); - DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "probeFiltered", txl->probe_pool); + DRW_shgroup_uniform_texture(default_shgrp, "ltcMat", e_data.ltc_mat); + DRW_shgroup_uniform_texture(default_shgrp, "brdfLut", e_data.brdf_lut); + DRW_shgroup_uniform_texture(default_shgrp, "probeFiltered", txl->probe_pool); if (is_sculpt_mode) { DRW_shgroup_call_sculpt_add(shgrp, ob, ob->obmat); diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 9e095b9c784..b9b8287c1f4 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -253,6 +253,7 @@ typedef struct EEVEE_LampEngineData { typedef struct EEVEE_PrivateData { struct DRWShadingGroup *default_lit_grp; + struct DRWShadingGroup *default_lit_grp_flat; struct DRWShadingGroup *shadow_shgrp; struct DRWShadingGroup *depth_shgrp; struct DRWShadingGroup *depth_shgrp_cull; diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl index 769d8dcd7bb..fe460e73477 100644 --- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl @@ -27,8 +27,14 @@ layout(std140) uniform shadow_block { in vec3 worldPosition; in vec3 viewPosition; + +#ifdef USE_FLAT_NORMAL +flat in vec3 worldNormal; +flat in vec3 viewNormal; +#else in vec3 worldNormal; in vec3 viewNormal; +#endif /* type */ #define POINT 0.0 diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl index 7f1c32c8edf..cf5c8a311f1 100644 --- a/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl @@ -12,8 +12,14 @@ in vec3 nor; out vec3 worldPosition; out vec3 viewPosition; + +#ifdef USE_FLAT_NORMAL +flat out vec3 worldNormal; +flat out vec3 viewNormal; +#else out vec3 worldNormal; out vec3 viewNormal; +#endif void main() { gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index 6f214440bdd..a48f850b987 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -325,6 +325,7 @@ void DRW_lamp_engine_data_free(struct LampEngineData *led); /* Settings */ bool DRW_object_is_renderable(struct Object *ob); +bool DRW_object_is_flat_normal(struct Object *ob); /* Draw commands */ void DRW_draw_pass(DRWPass *pass); diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index e787d77819b..7b953be1009 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -47,6 +47,8 @@ #include "DNA_camera_types.h" #include "DNA_view3d_types.h" #include "DNA_screen_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" #include "ED_space_api.h" #include "ED_screen.h" @@ -1880,6 +1882,18 @@ bool DRW_object_is_renderable(Object *ob) return true; } + +bool DRW_object_is_flat_normal(Object *ob) +{ + if (ob->type == OB_MESH) { + Mesh *me = ob->data; + if (me->mpoly && me->mpoly[0].flag & ME_SMOOTH) { + return false; + } + } + return true; +} + /** \} */