diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2017-07-17 00:49:25 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2017-07-24 16:28:27 +0300 |
commit | 2a84331f02d08092aa42b3870693d09b18744b4b (patch) | |
tree | f3d0a3d83f39bf43b2a69e651cde177ae2e95c95 /source/blender/draw/engines/eevee | |
parent | 04f8e1b21c716b6d4eefed6678d036cd0c96d4d2 (diff) |
Eevee: SSR: Output ssr datas to buffers.
Output in 2 buffers Normals, Specular Color and roughness.
This way we can raytrace in a defered fashion and blend the exact contribution of the specular lobe on top of the opaque pass.
Diffstat (limited to 'source/blender/draw/engines/eevee')
8 files changed, 295 insertions, 79 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index ee16f4e5e02..6c190d8b917 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -73,9 +73,14 @@ static struct { /* Volumetric */ struct GPUShader *volumetric_upsample_sh; + /* Screen Space Reflection */ + struct GPUShader *ssr_raytrace_sh; + struct GPUShader *ssr_resolve_sh; + struct GPUTexture *depth_src; } e_data = {NULL}; /* Engine data */ +extern char datatoc_effect_ssr_frag_glsl[]; extern char datatoc_effect_minmaxz_frag_glsl[]; extern char datatoc_effect_motion_blur_frag_glsl[]; extern char datatoc_effect_bloom_frag_glsl[]; @@ -158,6 +163,9 @@ void EEVEE_effects_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata) /* Shaders */ if (!e_data.motion_blur_sh) { + e_data.ssr_raytrace_sh = DRW_shader_create_fullscreen(datatoc_effect_ssr_frag_glsl, "#define STEP_RAYTRACE\n"); + e_data.ssr_resolve_sh = DRW_shader_create_fullscreen(datatoc_effect_ssr_frag_glsl, "#define STEP_RESOLVE\n"); + e_data.volumetric_upsample_sh = DRW_shader_create_fullscreen(datatoc_volumetric_frag_glsl, "#define STEP_UPSAMPLE\n"); e_data.minmaxz_downlevel_sh = DRW_shader_create_fullscreen(datatoc_effect_minmaxz_frag_glsl, NULL); @@ -478,6 +486,43 @@ void EEVEE_effects_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata) } } } + + if (BKE_collection_engine_property_value_get_bool(props, "ssr_enable")) { + effects->enabled_effects |= EFFECT_SSR; + + int tracing_res[2] = {(int)viewport_size[0] / 2, (int)viewport_size[1] / 2}; + const bool record_two_hit = false; + const bool high_qual_input = true; /* TODO dither low quality input */ + + /* MRT for the shading pass in order to output needed data for the SSR pass. */ + /* TODO create one texture layer per lobe */ + if (txl->ssr_normal_input == NULL) { + DRWTextureFormat nor_format = DRW_TEX_RG_16; + txl->ssr_normal_input = DRW_texture_create_2D((int)viewport_size[0], (int)viewport_size[1], nor_format, 0, NULL); + DRW_framebuffer_texture_attach(fbl->main, txl->ssr_normal_input, 1, 0); + } + + if (txl->ssr_specrough_input == NULL) { + DRWTextureFormat specrough_format = (high_qual_input) ? DRW_TEX_RGBA_16 : DRW_TEX_RGBA_8; + txl->ssr_specrough_input = DRW_texture_create_2D((int)viewport_size[0], (int)viewport_size[1], specrough_format, 0, NULL); + DRW_framebuffer_texture_attach(fbl->main, txl->ssr_specrough_input, 2, 0); + } + + /* Raytracing output */ + /* TODO try integer format for hit coord to increase precision */ + DRWFboTexture tex_output[2] = {{&txl->ssr_hit_output, (record_two_hit) ? DRW_TEX_RGBA_16 : DRW_TEX_RG_16, 0}, + {&txl->ssr_pdf_output, (record_two_hit) ? DRW_TEX_RG_16 : DRW_TEX_R_16, 0}}; + + DRW_framebuffer_init(&fbl->screen_tracing_fb, &draw_engine_eevee_type, tracing_res[0], tracing_res[1], tex_output, 2); + } + else { + /* Cleanup to release memory */ + DRW_TEXTURE_FREE_SAFE(txl->ssr_normal_input); + DRW_TEXTURE_FREE_SAFE(txl->ssr_specrough_input); + DRW_TEXTURE_FREE_SAFE(txl->ssr_hit_output); + DRW_TEXTURE_FREE_SAFE(txl->ssr_pdf_output); + DRW_FRAMEBUFFER_FREE_SAFE(fbl->screen_tracing_fb); + } } static DRWShadingGroup *eevee_create_bloom_pass(const char *name, EEVEE_EffectsInfo *effects, struct GPUShader *sh, DRWPass **pass, bool upsample) @@ -566,6 +611,24 @@ void EEVEE_effects_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata) } } + if ((effects->enabled_effects & EFFECT_SSR) != 0) { + psl->ssr_raytrace = DRW_pass_create("Raytrace", DRW_STATE_WRITE_COLOR); + DRWShadingGroup *grp = DRW_shgroup_create(e_data.ssr_raytrace_sh, psl->ssr_raytrace); + DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src); + DRW_shgroup_uniform_buffer(grp, "normalBuffer", &stl->g_data->minmaxz); + DRW_shgroup_uniform_buffer(grp, "specRoughBuffer", &stl->g_data->minmaxz); + DRW_shgroup_call_add(grp, quad, NULL); + + psl->ssr_resolve = DRW_pass_create("Raytrace", DRW_STATE_WRITE_COLOR); + grp = DRW_shgroup_create(e_data.ssr_resolve_sh, psl->ssr_resolve); + DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src); + DRW_shgroup_uniform_buffer(grp, "normalBuffer", &txl->ssr_normal_input); + DRW_shgroup_uniform_buffer(grp, "specroughBuffer", &txl->ssr_specrough_input); + DRW_shgroup_uniform_buffer(grp, "hitBuffer", &txl->ssr_hit_output); + DRW_shgroup_uniform_buffer(grp, "pdfBuffer", &txl->ssr_pdf_output); + DRW_shgroup_call_add(grp, quad, NULL); + } + { psl->minmaxz_downlevel = DRW_pass_create("HiZ Down Level", DRW_STATE_WRITE_COLOR); DRWShadingGroup *grp = DRW_shgroup_create(e_data.minmaxz_downlevel_sh, psl->minmaxz_downlevel); @@ -726,6 +789,7 @@ void EEVEE_effects_do_volumetrics(EEVEE_SceneLayerData *sldata, EEVEE_Data *veda EEVEE_EffectsInfo *effects = stl->effects; if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) { + return; DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); e_data.depth_src = dtxl->depth; @@ -758,6 +822,35 @@ void EEVEE_effects_do_volumetrics(EEVEE_SceneLayerData *sldata, EEVEE_Data *veda } } +void EEVEE_effects_do_ssr(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_EffectsInfo *effects = stl->effects; + + if ((effects->enabled_effects & EFFECT_SSR) != 0) { + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + /* Raytrace at halfres. */ + DRW_framebuffer_bind(fbl->screen_tracing_fb); + DRW_draw_pass(psl->ssr_raytrace); + + /* Resolve at fullres */ + DRW_framebuffer_texture_detach(dtxl->depth); + DRW_framebuffer_texture_detach(txl->ssr_normal_input); + DRW_framebuffer_texture_detach(txl->ssr_specrough_input); + DRW_framebuffer_bind(fbl->main); + DRW_draw_pass(psl->ssr_resolve); + + /* Restore */ + DRW_framebuffer_texture_attach(fbl->main, dtxl->depth, 0, 0); + DRW_framebuffer_texture_attach(fbl->main, txl->ssr_normal_input, 1, 0); + DRW_framebuffer_texture_attach(fbl->main, txl->ssr_specrough_input, 2, 0); + } +} + void EEVEE_draw_effects(EEVEE_Data *vedata) { EEVEE_PassList *psl = vedata->psl; @@ -881,6 +974,9 @@ void EEVEE_draw_effects(EEVEE_Data *vedata) void EEVEE_effects_free(void) { + DRW_SHADER_FREE_SAFE(e_data.ssr_raytrace_sh); + DRW_SHADER_FREE_SAFE(e_data.ssr_resolve_sh); + DRW_SHADER_FREE_SAFE(e_data.volumetric_upsample_sh); DRW_SHADER_FREE_SAFE(e_data.minmaxz_downlevel_sh); diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index 480bb1b12ad..c8dc8c67c04 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -155,6 +155,7 @@ static void EEVEE_draw_scene(void *vedata) DRW_framebuffer_bind(fbl->main); DRW_framebuffer_clear(false, true, false, NULL, 1.0f); + /* TODO move background after depth pass to cut some overdraw */ DRW_draw_pass(psl->background_pass); /* Depth prepass */ @@ -172,6 +173,9 @@ static void EEVEE_draw_scene(void *vedata) EEVEE_draw_default_passes(psl); DRW_draw_pass(psl->material_pass); + /* Screen Space Reflections */ + EEVEE_effects_do_ssr(sldata, vedata); + /* Volumetrics */ EEVEE_effects_do_volumetrics(sldata, vedata); @@ -206,6 +210,8 @@ static void EEVEE_scene_layer_settings_create(RenderEngine *UNUSED(engine), IDPr props->type == IDP_GROUP && props->subtype == IDP_GROUP_SUB_ENGINE_RENDER); + BKE_collection_engine_property_add_bool(props, "ssr_enable", false); + BKE_collection_engine_property_add_bool(props, "volumetric_enable", false); BKE_collection_engine_property_add_float(props, "volumetric_start", 0.1f); BKE_collection_engine_property_add_float(props, "volumetric_end", 100.0f); diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index a526bdbefb5..e7c066404e2 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -253,8 +253,15 @@ static char *eevee_get_volume_defines(int options) return str; } -static void add_standard_uniforms(DRWShadingGroup *shgrp, EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata) +/** + * ssr_id can be null to disable ssr contribution. + **/ +static void add_standard_uniforms(DRWShadingGroup *shgrp, EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata, int *ssr_id) { + if (ssr_id == NULL) { + static int no_ssr = -1.0f; + ssr_id = &no_ssr; + } DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo); DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo); DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo); @@ -273,6 +280,7 @@ static void add_standard_uniforms(DRWShadingGroup *shgrp, EEVEE_SceneLayerData * DRW_shgroup_uniform_buffer(shgrp, "irradianceGrid", &sldata->irradiance_pool); DRW_shgroup_uniform_buffer(shgrp, "shadowCubes", &sldata->shadow_depth_cube_pool); DRW_shgroup_uniform_buffer(shgrp, "shadowCascades", &sldata->shadow_depth_cascade_pool); + DRW_shgroup_uniform_int(shgrp, "outputSsrId", ssr_id, 1); if (vedata->stl->effects->use_ao) { DRW_shgroup_uniform_vec4(shgrp, "viewvecs[0]", (float *)&vedata->stl->g_data->viewvecs, 2); DRW_shgroup_uniform_buffer(shgrp, "minMaxDepthTex", &vedata->stl->g_data->minmaxz); @@ -583,8 +591,10 @@ struct GPUMaterial *EEVEE_material_hair_get( **/ static struct DRWShadingGroup *EEVEE_default_shading_group_create( EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata, DRWPass *pass, - bool is_hair, bool is_flat_normal, bool use_ao, bool use_bent_normals, bool use_blend) + bool is_hair, bool is_flat_normal, bool use_ao, bool use_bent_normals, bool use_blend, bool use_ssr) { + static int ssr_id; + ssr_id = (use_ssr) ? 0 : -1; int options = VAR_MAT_MESH; if (is_hair) options |= VAR_MAT_HAIR; @@ -598,7 +608,7 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_create( } DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], pass); - add_standard_uniforms(shgrp, sldata, vedata); + add_standard_uniforms(shgrp, sldata, vedata, &ssr_id); return shgrp; } @@ -608,8 +618,10 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_create( **/ static struct DRWShadingGroup *EEVEE_default_shading_group_get( EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata, - bool is_hair, bool is_flat_normal, bool use_ao, bool use_bent_normals) + bool is_hair, bool is_flat_normal, bool use_ao, bool use_bent_normals, bool use_ssr) { + static int ssr_id; + ssr_id = (use_ssr) ? 0 : -1; int options = VAR_MAT_MESH; if (is_hair) options |= VAR_MAT_HAIR; @@ -626,7 +638,7 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_get( vedata->psl->default_pass[options] = DRW_pass_create("Default Lit Pass", state); DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], vedata->psl->default_pass[options]); - add_standard_uniforms(shgrp, sldata, vedata); + add_standard_uniforms(shgrp, sldata, vedata, &ssr_id); } return DRW_shgroup_create(e_data.default_lit[options], vedata->psl->default_pass[options]); @@ -638,12 +650,14 @@ void EEVEE_materials_cache_init(EEVEE_Data *vedata) EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; { - /* Global AO Switch*/ const DRWContextState *draw_ctx = DRW_context_state_get(); SceneLayer *scene_layer = draw_ctx->scene_layer; IDProperty *props = BKE_scene_layer_engine_evaluated_get(scene_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE); + /* Global AO Switch*/ stl->effects->use_ao = BKE_collection_engine_property_value_get_bool(props, "gtao_enable"); stl->effects->use_bent_normals = BKE_collection_engine_property_value_get_bool(props, "gtao_use_bent_normals"); + /* SSR switch */ + stl->effects->use_ssr = BKE_collection_engine_property_value_get_bool(props, "ssr_enable"); } /* Create Material Ghash */ @@ -781,7 +795,9 @@ static void material_opaque( *shgrp = DRW_shgroup_material_create(*gpumat, psl->material_pass); if (*shgrp) { - add_standard_uniforms(*shgrp, sldata, vedata); + static int ssr_id; + ssr_id = (stl->effects->use_ssr) ? 0 : -1; + add_standard_uniforms(*shgrp, sldata, vedata, &ssr_id); } else { /* Shader failed : pink color */ @@ -813,7 +829,7 @@ static void material_opaque( /* Fallback to default shader */ if (*shgrp == NULL) { *shgrp = EEVEE_default_shading_group_get(sldata, vedata, false, use_flat_nor, - stl->effects->use_ao, stl->effects->use_bent_normals); + stl->effects->use_ao, stl->effects->use_bent_normals, stl->effects->use_ssr); DRW_shgroup_uniform_vec3(*shgrp, "basecol", color_p, 1); DRW_shgroup_uniform_float(*shgrp, "metallic", metal_p, 1); DRW_shgroup_uniform_float(*shgrp, "specular", spec_p, 1); @@ -855,7 +871,8 @@ static void material_transparent( *shgrp = DRW_shgroup_material_create(*gpumat, psl->transparent_pass); if (*shgrp) { - add_standard_uniforms(*shgrp, sldata, vedata); + static int ssr_id = -1; /* TODO transparent SSR */ + add_standard_uniforms(*shgrp, sldata, vedata, &ssr_id); } else { /* Shader failed : pink color */ @@ -871,7 +888,7 @@ static void material_transparent( if (*shgrp == NULL) { *shgrp = EEVEE_default_shading_group_create( sldata, vedata, psl->transparent_pass, - false, use_flat_nor, stl->effects->use_ao, stl->effects->use_bent_normals, true); + false, use_flat_nor, stl->effects->use_ao, stl->effects->use_bent_normals, true, false); DRW_shgroup_uniform_vec3(*shgrp, "basecol", color_p, 1); DRW_shgroup_uniform_float(*shgrp, "metallic", metal_p, 1); DRW_shgroup_uniform_float(*shgrp, "specular", spec_p, 1); @@ -1089,7 +1106,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_SceneLayerData *sl shgrp = DRW_shgroup_material_create(gpumat, psl->material_pass); if (shgrp) { - add_standard_uniforms(shgrp, sldata, vedata); + add_standard_uniforms(shgrp, sldata, vedata, NULL); BLI_ghash_insert(material_hash, ma, shgrp); @@ -1108,7 +1125,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_SceneLayerData *sl /* Fallback to default shader */ if (shgrp == NULL) { shgrp = EEVEE_default_shading_group_get(sldata, vedata, true, false, - stl->effects->use_ao, stl->effects->use_bent_normals); + stl->effects->use_ao, stl->effects->use_bent_normals, stl->effects->use_ssr); DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1); DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1); DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1); diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 53605304e47..f773c48dc32 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -109,6 +109,8 @@ typedef struct EEVEE_PassList { struct DRWPass *volumetric_integrate_ps; struct DRWPass *volumetric_resolve_ps; struct DRWPass *volumetric_resolve_transmit_ps; + struct DRWPass *ssr_raytrace; + struct DRWPass *ssr_resolve; struct DRWPass *depth_pass; struct DRWPass *depth_pass_cull; @@ -131,6 +133,7 @@ typedef struct EEVEE_FramebufferList { struct GPUFrameBuffer *dof_scatter_far_fb; struct GPUFrameBuffer *dof_scatter_near_fb; struct GPUFrameBuffer *volumetric_fb; + struct GPUFrameBuffer *screen_tracing_fb; struct GPUFrameBuffer *planarref_fb; @@ -149,6 +152,11 @@ typedef struct EEVEE_TextureList { struct GPUTexture *bloom_downsample[MAX_BLOOM_STEP]; /* R16_G16_B16 */ struct GPUTexture *bloom_upsample[MAX_BLOOM_STEP-1]; /* R16_G16_B16 */ + struct GPUTexture *ssr_normal_input; + struct GPUTexture *ssr_specrough_input; + struct GPUTexture *ssr_hit_output; + struct GPUTexture *ssr_pdf_output; + struct GPUTexture *planar_pool; struct GPUTexture *color; /* R16_G16_B16 */ @@ -300,6 +308,9 @@ enum { typedef struct EEVEE_EffectsInfo { int enabled_effects; + /* SSR */ + bool use_ssr; + /* Ambient Occlusion */ bool use_ao, use_bent_normals; float ao_dist, ao_samples, ao_factor; @@ -339,6 +350,7 @@ enum { EFFECT_BLOOM = (1 << 1), EFFECT_DOF = (1 << 2), EFFECT_VOLUMETRIC = (1 << 3), + EFFECT_SSR = (1 << 4), }; /* ************** SCENE LAYER DATA ************** */ @@ -486,6 +498,7 @@ void EEVEE_effects_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata); void EEVEE_effects_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata); void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, struct GPUTexture *depth_src); void EEVEE_effects_do_volumetrics(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_effects_do_ssr(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata); void EEVEE_draw_effects(EEVEE_Data *vedata); void EEVEE_effects_free(void); diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl index f3f9d8af7f0..50b3309e93b 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl @@ -66,13 +66,28 @@ Closure closure_add(Closure cl1, Closure cl2) struct Closure { vec3 radiance; float opacity; + vec4 ssr_data; + vec2 ssr_normal; + int ssr_id; }; -#define CLOSURE_DEFAULT Closure(vec3(0.0), 1.0) +#define CLOSURE_DEFAULT Closure(vec3(0.0), 1.0, vec4(0.0), vec2(0.0), -1) + +uniform int outputSsrId; Closure closure_mix(Closure cl1, Closure cl2, float fac) { Closure cl; + if (cl1.ssr_id == outputSsrId) { + cl.ssr_data = mix(cl1.ssr_data.xyzw, vec4(vec3(0.0), cl1.ssr_data.w), fac); /* do not blend roughness */ + cl.ssr_normal = cl1.ssr_normal; + cl.ssr_id = cl1.ssr_id; + } + else { + cl.ssr_data = mix(vec4(vec3(0.0), cl2.ssr_data.w), cl2.ssr_data.xyzw, fac); /* do not blend roughness */ + cl.ssr_normal = cl2.ssr_normal; + cl.ssr_id = cl2.ssr_id; + } cl.radiance = mix(cl1.radiance, cl2.radiance, fac); cl.opacity = mix(cl1.opacity, cl2.opacity, fac); return cl; @@ -80,12 +95,30 @@ Closure closure_mix(Closure cl1, Closure cl2, float fac) Closure closure_add(Closure cl1, Closure cl2) { - Closure cl; + Closure cl = (cl1.ssr_id == outputSsrId) ? cl1 : cl2; cl.radiance = cl1.radiance + cl2.radiance; cl.opacity = cl1.opacity + cl2.opacity; return cl; } +#if defined(MESH_SHADER) && !defined(SHADOW_SHADER) +layout(location = 0) out vec4 fragColor; +layout(location = 1) out vec4 ssrNormals; +layout(location = 2) out vec4 ssrData; + +Closure nodetree_exec(void); /* Prototype */ + +#define NODETREE_EXEC +void main() +{ + Closure cl = nodetree_exec(); + fragColor = vec4(cl.radiance, cl.opacity); + ssrNormals = cl.ssr_normal.xyyy; + ssrData = cl.ssr_data; +} + +#endif /* MESH_SHADER && !SHADOW_SHADER */ + #endif /* VOLUMETRICS */ Closure nodetree_exec(void); /* Prototype */ @@ -101,7 +134,6 @@ void main() Closure cl = nodetree_exec(); fragColor = vec4(mix(vec3(1.0), cl.radiance, cl.opacity), 1.0); } - #endif struct LightData { diff --git a/source/blender/draw/engines/eevee/shaders/default_frag.glsl b/source/blender/draw/engines/eevee/shaders/default_frag.glsl index b50eb481f94..db8ed2d04fe 100644 --- a/source/blender/draw/engines/eevee/shaders/default_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/default_frag.glsl @@ -4,17 +4,19 @@ uniform float metallic; uniform float specular; uniform float roughness; -out vec4 FragColor; - -void main() +Closure nodetree_exec(void) { vec3 dielectric = vec3(0.034) * specular * 2.0; vec3 diffuse = mix(basecol, vec3(0.0), metallic); vec3 f0 = mix(dielectric, basecol, metallic); - vec3 radiance = eevee_surface_lit((gl_FrontFacing) ? worldNormal : -worldNormal, diffuse, f0, roughness, 1.0); -#if defined(USE_ALPHA_BLEND) - FragColor = vec4(radiance, 1.0); -#else - FragColor = vec4(radiance, length(viewPosition)); + vec3 ssr_spec; + vec3 radiance = eevee_surface_lit((gl_FrontFacing) ? worldNormal : -worldNormal, diffuse, f0, roughness, 1.0, 0, ssr_spec); + + Closure result = Closure(radiance, 1.0, vec4(ssr_spec, roughness), viewNormal.xy, 0); + +#if !defined(USE_ALPHA_BLEND) + result.opacity = length(viewPosition); #endif + + return result; } diff --git a/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl new file mode 100644 index 00000000000..bbf33661ef5 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl @@ -0,0 +1,36 @@ + +#ifdef STEP_RAYTRACE + +uniform sampler2D depthBuffer; +uniform sampler2D normalBuffer; +uniform sampler2D specroughBuffer; + +layout(location = 0) out vec4 hitData; +layout(location = 1) out vec4 pdfData; + +void main() +{ + hitData = vec4(0.2); + pdfData = vec4(0.5); +} + +#else /* STEP_RESOLVE */ + +uniform sampler2D depthBuffer; +uniform sampler2D normalBuffer; +uniform sampler2D specroughBuffer; + +uniform sampler2D hitBuffer; +uniform sampler2D pdfBuffer; + +out vec4 fragColor; + +void main() +{ + ivec2 halfres_texel = ivec2(gl_FragCoord.xy / 2.0); + ivec2 fullres_texel = ivec2(gl_FragCoord.xy); + + fragColor = vec4(texelFetch(specroughBuffer, fullres_texel, 0).aaa, 1.0); +} + +#endif 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 4241eeb8b8e..9a851ac6bad 100644 --- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl @@ -24,7 +24,7 @@ in vec3 viewNormal; /* ----------- default ----------- */ -vec3 eevee_surface_lit(vec3 N, vec3 albedo, vec3 f0, float roughness, float ao, float ssr_id) +vec3 eevee_surface_lit(vec3 N, vec3 albedo, vec3 f0, float roughness, float ao, int ssr_id, out vec3 ssr_spec) { /* Zero length vectors cause issues, see: T51979. */ #if 0 @@ -89,37 +89,40 @@ vec3 eevee_surface_lit(vec3 N, vec3 albedo, vec3 f0, float roughness, float ao, /* Accumulate light from all sources until accumulator is full. Then apply Occlusion and BRDF. */ vec4 spec_accum = vec4(0.0); - /* Planar Reflections */ - for (int i = 0; i < MAX_PLANAR && i < planar_count && spec_accum.a < 0.999; ++i) { - PlanarData pd = planars_data[i]; + /* SSR lobe is applied later in a defered style */ + if (ssr_id != outputSsrId) { + /* Planar Reflections */ + for (int i = 0; i < MAX_PLANAR && i < planar_count && spec_accum.a < 0.999; ++i) { + PlanarData pd = planars_data[i]; - float fade = probe_attenuation_planar(pd, worldPosition, N); + float fade = probe_attenuation_planar(pd, worldPosition, N); - if (fade > 0.0) { - vec3 spec = probe_evaluate_planar(float(i), pd, worldPosition, N, V, rand.r, cameraPos, roughness, fade); - accumulate_light(spec, fade, spec_accum); + if (fade > 0.0) { + vec3 spec = probe_evaluate_planar(float(i), pd, worldPosition, N, V, rand.r, cameraPos, roughness, fade); + accumulate_light(spec, fade, spec_accum); + } } - } - /* Specular probes */ - vec3 spec_dir = get_specular_dominant_dir(N, V, roughnessSquared); + /* Specular probes */ + vec3 spec_dir = get_specular_dominant_dir(N, V, roughnessSquared); - /* Starts at 1 because 0 is world probe */ - for (int i = 1; i < MAX_PROBE && i < probe_count && spec_accum.a < 0.999; ++i) { - CubeData cd = probes_data[i]; + /* Starts at 1 because 0 is world probe */ + for (int i = 1; i < MAX_PROBE && i < probe_count && spec_accum.a < 0.999; ++i) { + CubeData cd = probes_data[i]; - float fade = probe_attenuation_cube(cd, worldPosition); + float fade = probe_attenuation_cube(cd, worldPosition); - if (fade > 0.0) { - vec3 spec = probe_evaluate_cube(float(i), cd, worldPosition, spec_dir, roughness); - accumulate_light(spec, fade, spec_accum); + if (fade > 0.0) { + vec3 spec = probe_evaluate_cube(float(i), cd, worldPosition, spec_dir, roughness); + accumulate_light(spec, fade, spec_accum); + } } - } - /* World Specular */ - if (spec_accum.a < 0.999) { - vec3 spec = probe_evaluate_world_spec(spec_dir, roughness); - accumulate_light(spec, 1.0, spec_accum); + /* World Specular */ + if (spec_accum.a < 0.999) { + vec3 spec = probe_evaluate_world_spec(spec_dir, roughness); + accumulate_light(spec, 1.0, spec_accum); + } } /* Ambient Occlusion */ @@ -130,7 +133,8 @@ vec3 eevee_surface_lit(vec3 N, vec3 albedo, vec3 f0, float roughness, float ao, vec2 uv = lut_coords(dot(N, V), roughness); vec2 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rg; - out_light += spec_accum.rgb * F_ibl(f0, brdf_lut) * specular_occlusion(dot(N, V), final_ao, roughness) * float(specToggle); + ssr_spec = F_ibl(f0, brdf_lut) * specular_occlusion(dot(N, V), final_ao, roughness); + out_light += spec_accum.rgb * ssr_spec * float(specToggle); /* ---------------- DIFFUSE ENVIRONMENT LIGHTING ----------------- */ @@ -166,7 +170,7 @@ vec3 eevee_surface_lit(vec3 N, vec3 albedo, vec3 f0, float roughness, float ao, vec3 eevee_surface_clearcoat_lit( vec3 N, vec3 albedo, vec3 f0, float roughness, vec3 C_N, float C_intensity, float C_roughness, /* Clearcoat params */ - float ao, float ssr_id) + float ao, int ssr_id, out vec3 ssr_spec) { roughness = clamp(roughness, 1e-8, 0.9999); float roughnessSquared = roughness * roughness; @@ -233,8 +237,10 @@ vec3 eevee_surface_clearcoat_lit( float fade = probe_attenuation_planar(pd, worldPosition, worldNormal); if (fade > 0.0) { - vec3 spec = probe_evaluate_planar(float(i), pd, worldPosition, N, V, rand.r, cameraPos, roughness, fade); - accumulate_light(spec, fade, spec_accum); + if (ssr_id != outputSsrId) { + vec3 spec = probe_evaluate_planar(float(i), pd, worldPosition, N, V, rand.r, cameraPos, roughness, fade); + accumulate_light(spec, fade, spec_accum); + } vec3 C_spec = probe_evaluate_planar(float(i), pd, worldPosition, C_N, V, rand.r, cameraPos, C_roughness, fade); accumulate_light(C_spec, fade, C_spec_accum); @@ -252,8 +258,10 @@ vec3 eevee_surface_clearcoat_lit( float fade = probe_attenuation_cube(cd, worldPosition); if (fade > 0.0) { - vec3 spec = probe_evaluate_cube(float(i), cd, worldPosition, spec_dir, roughness); - accumulate_light(spec, fade, spec_accum); + if (ssr_id != outputSsrId) { + vec3 spec = probe_evaluate_cube(float(i), cd, worldPosition, spec_dir, roughness); + accumulate_light(spec, fade, spec_accum); + } vec3 C_spec = probe_evaluate_cube(float(i), cd, worldPosition, C_spec_dir, C_roughness); accumulate_light(C_spec, fade, C_spec_accum); @@ -262,8 +270,10 @@ vec3 eevee_surface_clearcoat_lit( /* World Specular */ if (spec_accum.a < 0.999) { - vec3 spec = probe_evaluate_world_spec(spec_dir, roughness); - accumulate_light(spec, 1.0, spec_accum); + if (ssr_id != outputSsrId) { + vec3 spec = probe_evaluate_world_spec(spec_dir, roughness); + accumulate_light(spec, 1.0, spec_accum); + } vec3 C_spec = probe_evaluate_world_spec(C_spec_dir, C_roughness); accumulate_light(C_spec, 1.0, C_spec_accum); @@ -277,7 +287,8 @@ vec3 eevee_surface_clearcoat_lit( vec2 uv = lut_coords(dot(N, V), roughness); vec2 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rg; - out_light += spec_accum.rgb * F_ibl(f0, brdf_lut) * specular_occlusion(dot(N, V), final_ao, roughness) * float(specToggle); + ssr_spec = F_ibl(f0, brdf_lut) * specular_occlusion(dot(N, V), final_ao, roughness); + out_light += spec_accum.rgb * ssr_spec * float(specToggle); uv = lut_coords(dot(C_N, V), C_roughness); brdf_lut = texture(utilTex, vec3(uv, 1.0)).rg; @@ -392,7 +403,7 @@ vec3 eevee_surface_diffuse_lit(vec3 N, vec3 albedo, float ao) /* ----------- Glossy ----------- */ -vec3 eevee_surface_glossy_lit(vec3 N, vec3 f0, float roughness, float ao) +vec3 eevee_surface_glossy_lit(vec3 N, vec3 f0, float roughness, float ao, int ssr_id, out vec3 ssr_spec) { roughness = clamp(roughness, 1e-8, 0.9999); float roughnessSquared = roughness * roughness; @@ -442,37 +453,39 @@ vec3 eevee_surface_glossy_lit(vec3 N, vec3 f0, float roughness, float ao) /* Accumulate light from all sources until accumulator is full. Then apply Occlusion and BRDF. */ vec4 spec_accum = vec4(0.0); - /* Planar Reflections */ - for (int i = 0; i < MAX_PLANAR && i < planar_count && spec_accum.a < 0.999; ++i) { - PlanarData pd = planars_data[i]; + if (ssr_id != outputSsrId) { + /* Planar Reflections */ + for (int i = 0; i < MAX_PLANAR && i < planar_count && spec_accum.a < 0.999; ++i) { + PlanarData pd = planars_data[i]; - float fade = probe_attenuation_planar(pd, worldPosition, N); + float fade = probe_attenuation_planar(pd, worldPosition, N); - if (fade > 0.0) { - vec3 spec = probe_evaluate_planar(float(i), pd, worldPosition, N, V, rand.r, cameraPos, roughness, fade); - accumulate_light(spec, fade, spec_accum); + if (fade > 0.0) { + vec3 spec = probe_evaluate_planar(float(i), pd, worldPosition, N, V, rand.r, cameraPos, roughness, fade); + accumulate_light(spec, fade, spec_accum); + } } - } - /* Specular probes */ - vec3 spec_dir = get_specular_dominant_dir(N, V, roughnessSquared); + /* Specular probes */ + vec3 spec_dir = get_specular_dominant_dir(N, V, roughnessSquared); - /* Starts at 1 because 0 is world probe */ - for (int i = 1; i < MAX_PROBE && i < probe_count && spec_accum.a < 0.999; ++i) { - CubeData cd = probes_data[i]; + /* Starts at 1 because 0 is world probe */ + for (int i = 1; i < MAX_PROBE && i < probe_count && spec_accum.a < 0.999; ++i) { + CubeData cd = probes_data[i]; - float fade = probe_attenuation_cube(cd, worldPosition); + float fade = probe_attenuation_cube(cd, worldPosition); - if (fade > 0.0) { - vec3 spec = probe_evaluate_cube(float(i), cd, worldPosition, spec_dir, roughness); - accumulate_light(spec, fade, spec_accum); + if (fade > 0.0) { + vec3 spec = probe_evaluate_cube(float(i), cd, worldPosition, spec_dir, roughness); + accumulate_light(spec, fade, spec_accum); + } } - } - /* World Specular */ - if (spec_accum.a < 0.999) { - vec3 spec = probe_evaluate_world_spec(spec_dir, roughness); - accumulate_light(spec, 1.0, spec_accum); + /* World Specular */ + if (spec_accum.a < 0.999) { + vec3 spec = probe_evaluate_world_spec(spec_dir, roughness); + accumulate_light(spec, 1.0, spec_accum); + } } /* Ambient Occlusion */ @@ -483,7 +496,8 @@ vec3 eevee_surface_glossy_lit(vec3 N, vec3 f0, float roughness, float ao) vec2 uv = lut_coords(dot(N, V), roughness); vec2 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rg; - out_light += spec_accum.rgb * F_ibl(f0, brdf_lut) * specular_occlusion(dot(N, V), final_ao, roughness) * float(specToggle); + ssr_spec = F_ibl(f0, brdf_lut) * specular_occlusion(dot(N, V), final_ao, roughness); + out_light += spec_accum.rgb * ssr_spec * float(specToggle); return out_light; } |