diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2018-12-05 04:07:23 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2018-12-05 04:51:48 +0300 |
commit | 7ffde286be0774e24ea04b4acaad6c6e4ae16bfe (patch) | |
tree | 2c4a3891df3438b24480651f157e07632f9cf15f | |
parent | 53685404316e05879bc9ff46837dd224ba3cce4f (diff) |
Workbench: Cleanups and reduce shader variations
Also optimize deferred engine by only outputing material data if needed.
This make the bare flat shading mode (no effects) only a depth prepass.
8 files changed, 197 insertions, 138 deletions
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl index b8c90162c51..7aa41e1a537 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl @@ -21,9 +21,11 @@ float bayer_dither_noise() { #ifdef WORKBENCH_ENCODE_NORMALS +#define WB_Normal vec2 + /* From http://aras-p.info/texts/CompactNormalStorage.html * Using Method #4: Spheremap Transform */ -vec3 workbench_normal_decode(vec2 enc) +vec3 workbench_normal_decode(WB_Normal enc) { vec2 fenc = enc.xy * 4.0 - 2.0; float f = dot(fenc, fenc); @@ -36,7 +38,7 @@ vec3 workbench_normal_decode(vec2 enc) /* From http://aras-p.info/texts/CompactNormalStorage.html * Using Method #4: Spheremap Transform */ -vec2 workbench_normal_encode(vec3 n) +WB_Normal workbench_normal_encode(vec3 n) { float p = sqrt(n.z * 8.0 + 8.0); n.xy = clamp(n.xy / p + 0.5, 0.0, 1.0); @@ -44,6 +46,7 @@ vec2 workbench_normal_encode(vec3 n) } #else +#define WB_Normal vec3 /* Well just do nothing... */ # define workbench_normal_encode(a) (a) # define workbench_normal_decode(a) (a) diff --git a/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl index 5a895ab65ec..40e166bc7ac 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl @@ -17,6 +17,8 @@ uniform float lightMultiplier; uniform float shadowShift = 0.1; uniform float shadowFocus = 1.0; +uniform vec3 materialSingleColor; + layout(std140) uniform world_block { WorldData world_data; }; @@ -26,8 +28,18 @@ void main() ivec2 texel = ivec2(gl_FragCoord.xy); vec2 uv_viewport = gl_FragCoord.xy * invertedViewportSize; + float roughness, metallic; + vec3 base_color; + +#ifndef MATDATA_PASS_ENABLED + base_color = materialSingleColor; + metallic = 0.0; + roughness = 0.5; +#else vec4 material_data = texelFetch(materialBuffer, texel, 0); - vec3 base_color = material_data.rgb; + base_color = material_data.rgb; + workbench_float_pair_decode(material_data.a, roughness, metallic); +#endif /* Do we need normals */ #ifdef NORMAL_VIEWPORT_PASS_ENABLED @@ -41,9 +53,8 @@ void main() vec3 shaded_color = base_color; #elif defined(V3D_LIGHTING_MATCAP) - /* When using matcaps, the material_data.a is the backface sign. */ - float flipped_nor = material_data.a; - normal_viewport = (flipped_nor > 0.0) ? normal_viewport : -normal_viewport; + /* When using matcaps, the metallic is the backface sign. */ + normal_viewport = (metallic > 0.0) ? normal_viewport : -normal_viewport; bool flipped = world_data.matcap_orientation != 0; vec2 matcap_uv = matcap_uv_compute(I_vs, normal_viewport, flipped); vec3 matcap = textureLod(matcapImage, matcap_uv, 0.0).rgb; @@ -52,12 +63,10 @@ void main() #elif defined(V3D_LIGHTING_STUDIO) # ifdef V3D_SHADING_SPECULAR_HIGHLIGHT - float roughness, metallic; - workbench_float_pair_decode(material_data.a, roughness, metallic); vec3 specular_color = mix(vec3(0.05), base_color, metallic); vec3 diffuse_color = mix(base_color, vec3(0.0), metallic); # else - float roughness = 0.0; + roughness = 0.0; vec3 specular_color = vec3(0.0); vec3 diffuse_color = base_color; # endif diff --git a/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl index 1d9f37274bd..cb5516ca34f 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl @@ -13,25 +13,23 @@ void main() { ivec2 texel = ivec2(gl_FragCoord.xy); vec2 uv_viewport = gl_FragCoord.xy * invertedViewportSize; - uint object_id = texelFetch(objectId, texel, 0).r; /* Listing 4 */ vec4 trans_accum = texelFetch(transparentAccum, texel, 0); float trans_revealage = trans_accum.a; trans_accum.a = texelFetch(transparentRevealage, texel, 0).r; -#ifdef V3D_SHADING_OBJECT_OUTLINE - float outline = calculate_object_outline(objectId, texel, object_id); -#else /* V3D_SHADING_OBJECT_OUTLINE */ - float outline = 1.0; -#endif /* V3D_SHADING_OBJECT_OUTLINE */ vec3 bg_color = background_color(world_data, uv_viewport.y); /* TODO: Bypass the whole shader if there is no xray pass and no outline pass. */ vec3 trans_color = trans_accum.rgb / clamp(trans_accum.a, 1e-4, 5e4); vec3 color = mix(trans_color, bg_color, trans_revealage); +#ifdef V3D_SHADING_OBJECT_OUTLINE + uint object_id = texelFetch(objectId, texel, 0).r; + float outline = calculate_object_outline(objectId, texel, object_id); color = mix(world_data.object_outline_color.rgb, color, outline); +#endif fragColor = vec4(color, 1.0); } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl index 93170037c4b..722add22a89 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl @@ -4,69 +4,70 @@ uniform vec3 materialDiffuseColor; uniform float materialMetallic; uniform float materialRoughness; -#ifdef V3D_SHADING_TEXTURE_COLOR uniform sampler2D image; uniform float ImageTransparencyCutoff = 0.1; -#endif - #ifdef NORMAL_VIEWPORT_PASS_ENABLED in vec3 normal_viewport; -#endif /* NORMAL_VIEWPORT_PASS_ENABLED */ +#endif #ifdef V3D_SHADING_TEXTURE_COLOR in vec2 uv_interp; -#endif /* V3D_SHADING_TEXTURE_COLOR */ +#endif #ifdef HAIR_SHADER flat in float hair_rand; #endif -layout(location=0) out uint objectId; -layout(location=1) out vec4 materialData; +#ifdef MATDATA_PASS_ENABLED +layout(location=0) out vec4 materialData; +#endif +#ifdef OBJECT_ID_PASS_ENABLED +layout(location=1) out uint objectId; +#endif #ifdef NORMAL_VIEWPORT_PASS_ENABLED -# ifdef WORKBENCH_ENCODE_NORMALS -layout(location=2) out vec2 normalViewport; -# else /* WORKBENCH_ENCODE_NORMALS */ -layout(location=2) out vec3 normalViewport; -# endif /* WORKBENCH_ENCODE_NORMALS */ -#endif /* NORMAL_VIEWPORT_PASS_ENABLED */ +layout(location=2) out WB_Normal normalViewport; +#endif void main() { - objectId = uint(object_id); +#ifdef MATDATA_PASS_ENABLED + float metallic, roughness; + vec4 color; - vec4 color_roughness; -#ifdef V3D_SHADING_TEXTURE_COLOR - color_roughness = texture(image, uv_interp); - if (color_roughness.a < ImageTransparencyCutoff) { +# ifdef V3D_SHADING_TEXTURE_COLOR + color = texture(image, uv_interp); + if (color.a < ImageTransparencyCutoff) { discard; } - color_roughness.a = materialRoughness; -#else - color_roughness = vec4(materialDiffuseColor, materialRoughness); -#endif /* V3D_SHADING_TEXTURE_COLOR */ - -#ifdef HAIR_SHADER - float hair_color_variation = hair_rand * 0.1; - color_roughness = clamp(color_roughness - hair_color_variation, 0.0, 1.0); -#endif - - float metallic; -#ifdef V3D_SHADING_SPECULAR_HIGHLIGHT -# ifdef HAIR_SHADER - metallic = clamp(materialMetallic - hair_color_variation, 0.0, 1.0); # else - metallic = materialMetallic; + color.rgb = materialDiffuseColor; # endif -#elif defined(V3D_LIGHTING_MATCAP) + +# ifdef V3D_LIGHTING_MATCAP /* Encode front facing in metallic channel. */ metallic = float(gl_FrontFacing); - color_roughness.a = 0.0; -#endif + roughness = 0.0; +# else + metallic = materialMetallic; + roughness = materialRoughness; +# endif - materialData.rgb = color_roughness.rgb; - materialData.a = workbench_float_pair_encode(color_roughness.a, metallic); +# ifdef HAIR_SHADER + /* Add some variation to the hairs to avoid uniform look. */ + float hair_variation = hair_rand * 0.1; + color = clamp(color - hair_variation, 0.0, 1.0); + metallic = clamp(materialMetallic - hair_variation, 0.0, 1.0); + roughness = clamp(materialRoughness - hair_variation, 0.0, 1.0); +# endif + + materialData.rgb = color.rgb; + materialData.a = workbench_float_pair_encode(roughness, metallic); +#endif /* MATDATA_PASS_ENABLED */ + +#ifdef OBJECT_ID_PASS_ENABLED + objectId = uint(object_id); +#endif #ifdef NORMAL_VIEWPORT_PASS_ENABLED vec3 n = (gl_FrontFacing) ? normal_viewport : -normal_viewport; diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c index 1e401b278be..7d551114f2e 100644 --- a/source/blender/draw/engines/workbench/workbench_deferred.c +++ b/source/blender/draw/engines/workbench/workbench_deferred.c @@ -46,6 +46,7 @@ #include "GPU_shader.h" #include "GPU_texture.h" +#include "GPU_extensions.h" #include "../eevee/eevee_lut.h" /* TODO find somewhere to share blue noise Table */ @@ -58,8 +59,8 @@ #endif static struct { - struct GPUShader *prepass_sh_cache[MAX_SHADERS]; - struct GPUShader *composite_sh_cache[MAX_SHADERS]; + struct GPUShader *prepass_sh_cache[MAX_PREPASS_SHADERS]; + struct GPUShader *composite_sh_cache[MAX_COMPOSITE_SHADERS]; struct GPUShader *cavity_sh[MAX_CAVITY_SHADERS]; struct GPUShader *background_sh[2]; struct GPUShader *ghost_resolve_sh; @@ -215,64 +216,63 @@ static GPUShader *workbench_cavity_shader_get(bool cavity, bool curvature) return *sh; } -static void ensure_deferred_shaders(WORKBENCH_PrivateData *wpd, int index, bool use_textures, bool is_hair) +static GPUShader *ensure_deferred_prepass_shader(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair) { + int index = workbench_material_get_prepass_shader_index(wpd, use_textures, is_hair); if (e_data.prepass_sh_cache[index] == NULL) { char *defines = workbench_material_build_defines(wpd, use_textures, is_hair); - char *composite_frag = workbench_build_composite_frag(wpd); char *prepass_vert = workbench_build_prepass_vert(is_hair); char *prepass_frag = workbench_build_prepass_frag(); e_data.prepass_sh_cache[index] = DRW_shader_create( prepass_vert, NULL, prepass_frag, defines); - if (!use_textures && !is_hair) { - e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines); - } MEM_freeN(prepass_vert); MEM_freeN(prepass_frag); + MEM_freeN(defines); + } + return e_data.prepass_sh_cache[index]; +} + +static GPUShader *ensure_deferred_composite_shader(WORKBENCH_PrivateData *wpd) +{ + int index = workbench_material_get_composite_shader_index(wpd); + if (e_data.composite_sh_cache[index] == NULL) { + char *defines = workbench_material_build_defines(wpd, false, false); + char *composite_frag = workbench_build_composite_frag(wpd); + e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines); MEM_freeN(composite_frag); MEM_freeN(defines); } + return e_data.composite_sh_cache[index]; } -static void ensure_background_shaders(const bool use_outline) +static GPUShader *ensure_background_shader(WORKBENCH_PrivateData *wpd) { - if (e_data.background_sh[use_outline] == NULL) { - const char *defines = (use_outline) ? "#define V3D_SHADING_OBJECT_OUTLINE\n" : NULL; + const int index = OBJECT_OUTLINE_ENABLED(wpd) ? 1 : 0; + if (e_data.background_sh[index] == NULL) { + const char *defines = (index) ? "#define V3D_SHADING_OBJECT_OUTLINE\n" : NULL; char *frag = BLI_string_joinN( datatoc_workbench_data_lib_glsl, datatoc_workbench_common_lib_glsl, datatoc_workbench_background_lib_glsl, datatoc_workbench_object_outline_lib_glsl, datatoc_workbench_deferred_background_frag_glsl); - e_data.background_sh[use_outline] = DRW_shader_create_fullscreen(frag, defines); + e_data.background_sh[index] = DRW_shader_create_fullscreen(frag, defines); MEM_freeN(frag); } + return e_data.background_sh[index]; } static void select_deferred_shaders(WORKBENCH_PrivateData *wpd) { - const bool use_outline = OBJECT_OUTLINE_ENABLED(wpd); - int index_solid = workbench_material_get_shader_index(wpd, false, false); - int index_solid_hair = workbench_material_get_shader_index(wpd, false, true); - int index_texture = workbench_material_get_shader_index(wpd, true, false); - int index_texture_hair = workbench_material_get_shader_index(wpd, true, true); - - ensure_deferred_shaders(wpd, index_solid, false, false); - ensure_deferred_shaders(wpd, index_solid_hair, false, true); - ensure_deferred_shaders(wpd, index_texture, true, false); - ensure_deferred_shaders(wpd, index_texture_hair, true, true); - ensure_background_shaders(use_outline); - - wpd->prepass_solid_sh = e_data.prepass_sh_cache[index_solid]; - wpd->prepass_solid_hair_sh = e_data.prepass_sh_cache[index_solid_hair]; - wpd->prepass_texture_sh = e_data.prepass_sh_cache[index_texture]; - wpd->prepass_texture_hair_sh = e_data.prepass_sh_cache[index_texture_hair]; - wpd->composite_sh = e_data.composite_sh_cache[index_solid]; - wpd->background_sh = e_data.background_sh[use_outline]; + wpd->prepass_solid_sh = ensure_deferred_prepass_shader(wpd, false, false); + wpd->prepass_solid_hair_sh = ensure_deferred_prepass_shader(wpd, false, true); + wpd->prepass_texture_sh = ensure_deferred_prepass_shader(wpd, true, false); + wpd->prepass_texture_hair_sh = ensure_deferred_prepass_shader(wpd, true, true); + wpd->composite_sh = ensure_deferred_composite_shader(wpd); + wpd->background_sh = ensure_background_shader(wpd); } - /* Using Hammersley distribution */ static float *create_disk_samples(int num_samples, int num_iterations) { @@ -346,8 +346,8 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata) } if (!e_data.next_object_id) { - memset(e_data.prepass_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS); - memset(e_data.composite_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS); + memset(e_data.prepass_sh_cache, 0, sizeof(e_data.prepass_sh_cache)); + memset(e_data.composite_sh_cache, 0, sizeof(e_data.composite_sh_cache)); e_data.next_object_id = 1; #ifdef DEBUG_SHADOW_VOLUME const char *shadow_frag = datatoc_workbench_shadow_debug_frag_glsl; @@ -411,9 +411,11 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata) e_data.normal_buffer_tx = NULL; e_data.cavity_buffer_tx = NULL; - e_data.color_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA8, &draw_engine_workbench_solid); e_data.composite_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], comp_tex_format, &draw_engine_workbench_solid); + if (MATDATA_PASS_ENABLED(wpd) || GPU_unused_fb_slot_workaround()) { + e_data.color_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA8, &draw_engine_workbench_solid); + } if (OBJECT_ID_PASS_ENABLED(wpd) || GPU_unused_fb_slot_workaround()) { e_data.object_id_tx = DRW_texture_pool_query_2D(size[0], size[1], id_tex_format, &draw_engine_workbench_solid); } @@ -426,8 +428,8 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata) GPU_framebuffer_ensure_config(&fbl->prepass_fb, { GPU_ATTACHMENT_TEXTURE(dtxl->depth), - GPU_ATTACHMENT_TEXTURE(e_data.object_id_tx), GPU_ATTACHMENT_TEXTURE(e_data.color_buffer_tx), + GPU_ATTACHMENT_TEXTURE(e_data.object_id_tx), GPU_ATTACHMENT_TEXTURE(e_data.normal_buffer_tx), }); GPU_framebuffer_ensure_config(&fbl->cavity_fb, { @@ -442,6 +444,11 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata) GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(e_data.composite_buffer_tx), }); + + if (!MATDATA_PASS_ENABLED(wpd) && !GPU_unused_fb_slot_workaround()) { + e_data.color_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA8, &draw_engine_workbench_solid); + } + GPU_framebuffer_ensure_config(&fbl->effect_fb, { GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(e_data.color_buffer_tx), @@ -543,8 +550,10 @@ static void workbench_setup_ghost_framebuffer(WORKBENCH_FramebufferList *fbl) void workbench_deferred_engine_free(void) { - for (int index = 0; index < MAX_SHADERS; index++) { + for (int index = 0; index < MAX_PREPASS_SHADERS; index++) { DRW_SHADER_FREE_SAFE(e_data.prepass_sh_cache[index]); + } + for (int index = 0; index < MAX_COMPOSITE_SHADERS; index++) { DRW_SHADER_FREE_SAFE(e_data.composite_sh_cache[index]); } for (int index = 0; index < MAX_CAVITY_SHADERS; ++index) { @@ -571,7 +580,12 @@ void workbench_deferred_engine_free(void) static void workbench_composite_uniforms(WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp) { DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo); - DRW_shgroup_uniform_texture_ref(grp, "materialBuffer", &e_data.color_buffer_tx); + if (MATDATA_PASS_ENABLED(wpd)) { + DRW_shgroup_uniform_texture_ref(grp, "materialBuffer", &e_data.color_buffer_tx); + } + else { + DRW_shgroup_uniform_vec3(grp, "materialSingleColor", wpd->shading.single_color, 1); + } if (OBJECT_OUTLINE_ENABLED(wpd)) { DRW_shgroup_uniform_texture_ref(grp, "objectId", &e_data.object_id_tx); } @@ -721,7 +735,7 @@ static WORKBENCH_MaterialData *get_or_create_material_data( workbench_material_copy(material, &material_template); DRW_shgroup_stencil_mask(material->shgrp, (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF); DRW_shgroup_uniform_int(material->shgrp, "object_id", &material->object_id, 1); - workbench_material_shgroup_uniform(wpd, material->shgrp, material, ob, true); + workbench_material_shgroup_uniform(wpd, material->shgrp, material, ob, true, true); BLI_ghash_insert(wpd->material_hash, POINTER_FROM_UINT(hash), material); } @@ -764,7 +778,7 @@ static void workbench_cache_populate_particles(WORKBENCH_Data *vedata, Object *o shader); DRW_shgroup_stencil_mask(shgrp, (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF); DRW_shgroup_uniform_int(shgrp, "object_id", &material->object_id, 1); - workbench_material_shgroup_uniform(wpd, shgrp, material, ob, true); + workbench_material_shgroup_uniform(wpd, shgrp, material, ob, true, true); } } } diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c index 36f94a6929a..70e26f79076 100644 --- a/source/blender/draw/engines/workbench/workbench_forward.c +++ b/source/blender/draw/engines/workbench/workbench_forward.c @@ -49,8 +49,8 @@ /* *********** STATIC *********** */ static struct { - struct GPUShader *composite_sh_cache[MAX_SHADERS]; - struct GPUShader *transparent_accum_sh_cache[MAX_SHADERS]; + struct GPUShader *composite_sh_cache[2]; + struct GPUShader *transparent_accum_sh_cache[MAX_ACCUM_SHADERS]; struct GPUShader *object_outline_sh; struct GPUShader *object_outline_texture_sh; struct GPUShader *object_outline_hair_sh; @@ -176,7 +176,7 @@ static WORKBENCH_MaterialData *get_or_create_material_data( DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); } - workbench_material_shgroup_uniform(wpd, grp, material, ob, false); + workbench_material_shgroup_uniform(wpd, grp, material, ob, false, false); material->shgrp = grp; /* Depth */ @@ -197,16 +197,9 @@ static WORKBENCH_MaterialData *get_or_create_material_data( return material; } -static void ensure_forward_shaders(WORKBENCH_PrivateData *wpd, int index, bool use_textures, bool is_hair) +static GPUShader *ensure_forward_accum_shaders(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair) { - if (e_data.composite_sh_cache[index] == NULL && !use_textures && !is_hair) { - char *defines = workbench_material_build_defines(wpd, use_textures, is_hair); - char *composite_frag = workbench_build_forward_composite_frag(); - e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines); - MEM_freeN(composite_frag); - MEM_freeN(defines); - } - + int index = workbench_material_get_accum_shader_index(wpd, use_textures, is_hair); if (e_data.transparent_accum_sh_cache[index] == NULL) { char *defines = workbench_material_build_defines(wpd, use_textures, is_hair); char *transparent_accum_vert = workbench_build_forward_vert(is_hair); @@ -218,25 +211,29 @@ static void ensure_forward_shaders(WORKBENCH_PrivateData *wpd, int index, bool u MEM_freeN(transparent_accum_frag); MEM_freeN(defines); } + return e_data.transparent_accum_sh_cache[index]; +} + +static GPUShader *ensure_forward_composite_shaders(WORKBENCH_PrivateData *wpd) +{ + int index = OBJECT_OUTLINE_ENABLED(wpd) ? 1 : 0; + if (e_data.composite_sh_cache[index] == NULL) { + char *defines = workbench_material_build_defines(wpd, false, false); + char *composite_frag = workbench_build_forward_composite_frag(); + e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines); + MEM_freeN(composite_frag); + MEM_freeN(defines); + } + return e_data.composite_sh_cache[index]; } static void select_forward_shaders(WORKBENCH_PrivateData *wpd) { - int index_solid = workbench_material_get_shader_index(wpd, false, false); - int index_solid_hair = workbench_material_get_shader_index(wpd, false, true); - int index_texture = workbench_material_get_shader_index(wpd, true, false); - int index_texture_hair = workbench_material_get_shader_index(wpd, true, true); - - ensure_forward_shaders(wpd, index_solid, false, false); - ensure_forward_shaders(wpd, index_solid_hair, false, true); - ensure_forward_shaders(wpd, index_texture, true, false); - ensure_forward_shaders(wpd, index_texture_hair, true, true); - - wpd->composite_sh = e_data.composite_sh_cache[index_solid]; - wpd->transparent_accum_sh = e_data.transparent_accum_sh_cache[index_solid]; - wpd->transparent_accum_hair_sh = e_data.transparent_accum_sh_cache[index_solid_hair]; - wpd->transparent_accum_texture_sh = e_data.transparent_accum_sh_cache[index_texture]; - wpd->transparent_accum_texture_hair_sh = e_data.transparent_accum_sh_cache[index_texture_hair]; + wpd->composite_sh = ensure_forward_composite_shaders(wpd); + wpd->transparent_accum_sh = ensure_forward_accum_shaders(wpd, false, false); + wpd->transparent_accum_hair_sh = ensure_forward_accum_shaders(wpd, false, true); + wpd->transparent_accum_texture_sh = ensure_forward_accum_shaders(wpd, true, false); + wpd->transparent_accum_texture_hair_sh = ensure_forward_accum_shaders(wpd, true, true); } /* public functions */ @@ -264,8 +261,8 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) if (!e_data.next_object_id) { e_data.next_object_id = 1; - memset(e_data.composite_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS); - memset(e_data.transparent_accum_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS); + memset(e_data.composite_sh_cache, 0x00, sizeof(e_data.composite_sh_cache)); + memset(e_data.transparent_accum_sh_cache, 0x00, sizeof(e_data.transparent_accum_sh_cache)); char *defines = workbench_material_build_defines(wpd, false, false); char *defines_texture = workbench_material_build_defines(wpd, true, false); @@ -391,8 +388,10 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) void workbench_forward_engine_free() { - for (int index = 0; index < MAX_SHADERS; index++) { + for (int index = 0; index < 2; index++) { DRW_SHADER_FREE_SAFE(e_data.composite_sh_cache[index]); + } + for (int index = 0; index < MAX_ACCUM_SHADERS; index++) { DRW_SHADER_FREE_SAFE(e_data.transparent_accum_sh_cache[index]); } DRW_SHADER_FREE_SAFE(e_data.object_outline_sh); @@ -444,7 +443,7 @@ static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, O psl->transparent_accum_pass, shader); DRW_shgroup_uniform_block(shgrp, "world_block", wpd->world_ubo); - workbench_material_shgroup_uniform(wpd, shgrp, material, ob, false); + workbench_material_shgroup_uniform(wpd, shgrp, material, ob, false, false); DRW_shgroup_uniform_vec4(shgrp, "viewvecs[0]", (float *)wpd->viewvecs, 3); /* Hairs have lots of layer and can rapidly become the most prominent surface. * So lower their alpha artificially. */ diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c index 2d74c7f0c82..c4ab39897f3 100644 --- a/source/blender/draw/engines/workbench/workbench_materials.c +++ b/source/blender/draw/engines/workbench/workbench_materials.c @@ -81,6 +81,12 @@ char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, bool use_text if (MATCAP_ENABLED(wpd)) { BLI_dynstr_appendf(ds, "#define V3D_LIGHTING_MATCAP\n"); } + if (OBJECT_ID_PASS_ENABLED(wpd)) { + BLI_dynstr_appendf(ds, "#define OBJECT_ID_PASS_ENABLED\n"); + } + if (MATDATA_PASS_ENABLED(wpd)) { + BLI_dynstr_appendf(ds, "#define MATDATA_PASS_ENABLED\n"); + } if (NORMAL_VIEWPORT_PASS_ENABLED(wpd)) { BLI_dynstr_appendf(ds, "#define NORMAL_VIEWPORT_PASS_ENABLED\n"); } @@ -127,21 +133,41 @@ uint workbench_material_get_hash(WORKBENCH_MaterialData *material_template, bool return result; } -int workbench_material_get_shader_index(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair) +int workbench_material_get_composite_shader_index(WORKBENCH_PrivateData *wpd) { - /* NOTE: change MAX_SHADERS accordingly when modifying this function. */ + /* NOTE: change MAX_COMPOSITE_SHADERS accordingly when modifying this function. */ int index = 0; - /* 1 bit V3D_SHADING_TEXTURE_COLOR */ - SET_FLAG_FROM_TEST(index, use_textures, 1 << 0); /* 2 bits FLAT/STUDIO/MATCAP + Specular highlight */ - int ligh_flag = SPECULAR_HIGHLIGHT_ENABLED(wpd) ? 3 : wpd->shading.light; - SET_FLAG_FROM_TEST(index, wpd->shading.light, ligh_flag << 1); - /* 3 bits for flags */ - SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_SHADOW, 1 << 3); - SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_CAVITY, 1 << 4); - SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE, 1 << 5); - /* 1 bit for hair */ - SET_FLAG_FROM_TEST(index, is_hair, 1 << 6); + index = SPECULAR_HIGHLIGHT_ENABLED(wpd) ? 3 : wpd->shading.light; + SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_SHADOW, 1 << 2); + SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_CAVITY, 1 << 3); + SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE, 1 << 4); + SET_FLAG_FROM_TEST(index, MATDATA_PASS_ENABLED(wpd), 1 << 5); + return index; +} + +int workbench_material_get_prepass_shader_index( + WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair) +{ + /* NOTE: change MAX_PREPASS_SHADERS accordingly when modifying this function. */ + int index = 0; + SET_FLAG_FROM_TEST(index, is_hair, 1 << 0); + SET_FLAG_FROM_TEST(index, MATDATA_PASS_ENABLED(wpd), 1 << 1); + SET_FLAG_FROM_TEST(index, OBJECT_ID_PASS_ENABLED(wpd), 1 << 2); + SET_FLAG_FROM_TEST(index, NORMAL_VIEWPORT_PASS_ENABLED(wpd), 1 << 3); + SET_FLAG_FROM_TEST(index, MATCAP_ENABLED(wpd), 1 << 4); + SET_FLAG_FROM_TEST(index, use_textures, 1 << 5); + return index; +} + +int workbench_material_get_accum_shader_index(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair) +{ + /* NOTE: change MAX_ACCUM_SHADERS accordingly when modifying this function. */ + int index = 0; + /* 2 bits FLAT/STUDIO/MATCAP + Specular highlight */ + index = SPECULAR_HIGHLIGHT_ENABLED(wpd) ? 3 : wpd->shading.light; + SET_FLAG_FROM_TEST(index, use_textures, 1 << 2); + SET_FLAG_FROM_TEST(index, is_hair, 1 << 3); return index; } @@ -156,8 +182,12 @@ int workbench_material_determine_color_type(WORKBENCH_PrivateData *wpd, Image *i void workbench_material_shgroup_uniform( WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp, WORKBENCH_MaterialData *material, Object *ob, - const bool use_metallic) + const bool use_metallic, const bool deferred) { + if (deferred && !MATDATA_PASS_ENABLED(wpd)) { + return; + } + if (workbench_material_determine_color_type(wpd, material->ima, ob) == V3D_SHADING_TEXTURE_COLOR) { GPUTexture *tex = GPU_texture_from_blender(material->ima, NULL, GL_TEXTURE_2D, false, 0.0f); DRW_shgroup_uniform_texture(grp, "image", tex); diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index 9fa7304e1ef..080817c7f53 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -40,7 +40,9 @@ #define WORKBENCH_ENGINE "BLENDER_WORKBENCH" #define M_GOLDEN_RATION_CONJUGATE 0.618033988749895 -#define MAX_SHADERS (1 << 7) +#define MAX_COMPOSITE_SHADERS (1 << 6) +#define MAX_PREPASS_SHADERS (1 << 6) +#define MAX_ACCUM_SHADERS (1 << 4) #define MAX_CAVITY_SHADERS (1 << 3) #define TEXTURE_DRAWING_ENABLED(wpd) (wpd->shading.color_type & V3D_SHADING_TEXTURE_COLOR) @@ -65,6 +67,7 @@ #define SPECULAR_HIGHLIGHT_ENABLED(wpd) (STUDIOLIGHT_ENABLED(wpd) && (wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT) && (!STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd))) #define OBJECT_OUTLINE_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE) #define OBJECT_ID_PASS_ENABLED(wpd) (OBJECT_OUTLINE_ENABLED(wpd) || CURVATURE_ENABLED(wpd)) +#define MATDATA_PASS_ENABLED(wpd) (wpd->shading.color_type != V3D_SHADING_SINGLE_COLOR || MATCAP_ENABLED(wpd)) #define NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd) (MATCAP_ENABLED(wpd) || STUDIOLIGHT_ENABLED(wpd) || SHADOW_ENABLED(wpd)) #define NORMAL_VIEWPORT_PASS_ENABLED(wpd) (NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd) || SSAO_ENABLED(wpd) || CURVATURE_ENABLED(wpd)) #define NORMAL_ENCODING_ENABLED() (true) @@ -298,10 +301,12 @@ int workbench_material_determine_color_type(WORKBENCH_PrivateData *wpd, Image *i char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair); void workbench_material_update_data(WORKBENCH_PrivateData *wpd, Object *ob, Material *mat, WORKBENCH_MaterialData *data); uint workbench_material_get_hash(WORKBENCH_MaterialData *material_template, bool is_ghost); -int workbench_material_get_shader_index(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair); +int workbench_material_get_composite_shader_index(WORKBENCH_PrivateData *wpd); +int workbench_material_get_prepass_shader_index(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair); +int workbench_material_get_accum_shader_index(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair); void workbench_material_shgroup_uniform( WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp, WORKBENCH_MaterialData *material, Object *ob, - const bool use_metallic); + const bool use_metallic, const bool deferred); void workbench_material_copy(WORKBENCH_MaterialData *dest_material, const WORKBENCH_MaterialData *source_material); /* workbench_studiolight.c */ |