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 | |
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.
14 files changed, 393 insertions, 92 deletions
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py index 367bd824cec..5dcedc152ef 100644 --- a/release/scripts/startup/bl_ui/properties_render.py +++ b/release/scripts/startup/bl_ui/properties_render.py @@ -710,6 +710,24 @@ class RENDER_PT_eevee_volumetric(RenderButtonsPanel, Panel): col.prop(props, "volumetric_colored_transmittance") +class RENDER_PT_eevee_shading(RenderButtonsPanel, Panel): + bl_label = "Shading" + COMPAT_ENGINES = {'BLENDER_EEVEE'} + + @classmethod + def poll(cls, context): + scene = context.scene + return scene and (scene.render.engine in cls.COMPAT_ENGINES) + + def draw(self, context): + layout = self.layout + scene = context.scene + props = scene.layer_properties['BLENDER_EEVEE'] + + col = layout.column() + col.prop(props, "ssr_enable") + + classes = ( RENDER_MT_presets, RENDER_MT_ffmpeg_presets, @@ -730,6 +748,7 @@ classes = ( RENDER_PT_eevee_poststack_settings, RENDER_PT_eevee_postprocess_settings, RENDER_PT_eevee_volumetric, + RENDER_PT_eevee_shading, ) if __name__ == "__main__": # only for live edit. diff --git a/release/scripts/startup/bl_ui/properties_render_layer.py b/release/scripts/startup/bl_ui/properties_render_layer.py index 450e3863965..be39de65964 100644 --- a/release/scripts/startup/bl_ui/properties_render_layer.py +++ b/release/scripts/startup/bl_ui/properties_render_layer.py @@ -250,6 +250,26 @@ class RENDERLAYER_PT_eevee_volumetric(RenderLayerButtonsPanel, Panel): col.template_override_property(layer_props, scene_props, "volumetric_colored_transmittance") +class RENDERLAYER_PT_eevee_shading(RenderLayerButtonsPanel, Panel): + bl_label = "Shading" + COMPAT_ENGINES = {'BLENDER_EEVEE'} + + @classmethod + def poll(cls, context): + scene = context.scene + return scene and (scene.render.engine in cls.COMPAT_ENGINES) + + def draw(self, context): + layout = self.layout + scene = context.scene + scene_props = scene.layer_properties['BLENDER_EEVEE'] + layer = bpy.context.render_layer + layer_props = layer.engine_overrides['BLENDER_EEVEE'] + + col = layout.column() + col.template_override_property(layer_props, scene_props, "ssr_enable") + + classes = ( RENDERLAYER_UL_renderlayers, RENDERLAYER_PT_layers, @@ -258,6 +278,7 @@ classes = ( RENDERLAYER_PT_clay_settings, RENDERLAYER_PT_eevee_poststack_settings, RENDERLAYER_PT_eevee_postprocess_settings, + RENDERLAYER_PT_eevee_shading, RENDERLAYER_PT_eevee_volumetric, ) diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 4b760f68705..d27979a458d 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -139,6 +139,7 @@ data_to_c_simple(engines/eevee/shaders/effect_dof_vert.glsl SRC) data_to_c_simple(engines/eevee/shaders/effect_dof_geom.glsl SRC) data_to_c_simple(engines/eevee/shaders/effect_dof_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/effect_motion_blur_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/effect_ssr_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/lightprobe_planar_downsample_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/lightprobe_planar_downsample_geom.glsl SRC) data_to_c_simple(engines/eevee/shaders/lightprobe_planar_downsample_vert.glsl SRC) 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; } diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index f319cfd82c6..09cd300c0b2 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -2663,6 +2663,8 @@ void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out Closure result) { #ifdef EEVEE_ENGINE vec3 L = eevee_surface_diffuse_lit(N, vec3(1.0), 1.0); + + result = Closure(L * color.rgb, 1.0, vec4(0.0), vec2(0.0), -1); #else /* ambient light */ vec3 L = vec3(0.2); @@ -2675,15 +2677,18 @@ void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out Closure result) float bsdf = max(dot(N, light_position), 0.0); L += light_diffuse * bsdf; } -#endif result = Closure(L * color.rgb, 1.0); +#endif } -void node_bsdf_glossy(vec4 color, float roughness, vec3 N, out Closure result) +void node_bsdf_glossy(vec4 color, float roughness, vec3 N, float ssr_id, out Closure result) { #ifdef EEVEE_ENGINE - vec3 L = eevee_surface_glossy_lit(N, vec3(1.0), roughness, 1.0); + vec3 ssr_spec; + vec3 L = eevee_surface_glossy_lit(N, vec3(1.0), roughness, 1.0, int(ssr_id), ssr_spec); + vec3 vN = mat3(ViewMatrix) * N; + result = Closure(L * color.rgb, 1.0, vec4(ssr_spec * color.rgb, roughness), vN.xy, int(ssr_id)); #else /* ambient light */ vec3 L = vec3(0.2); @@ -2702,9 +2707,9 @@ void node_bsdf_glossy(vec4 color, float roughness, vec3 N, out Closure result) bsdf += 0.5 * max(dot(N, light_position), 0.0); L += light_specular * bsdf; } -#endif result = Closure(L * color.rgb, 1.0); +#endif } void node_bsdf_anisotropic( @@ -2724,6 +2729,7 @@ void node_bsdf_toon(vec4 color, float size, float tsmooth, vec3 N, out Closure r node_bsdf_diffuse(color, 0.0, N, result); } +#ifndef EEVEE_ENGINE void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular, float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat, float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, out Closure result) @@ -2821,16 +2827,19 @@ void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_rad result = Closure(L, 1.0); } +#endif void node_bsdf_principled_simple(vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular, float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat, float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, float ssr_id, out Closure result) { #ifdef EEVEE_ENGINE - vec3 diffuse, f0; + vec3 diffuse, f0, ssr_spec; convert_metallic_to_specular_tinted(base_color.rgb, metallic, specular, specular_tint, diffuse, f0); - result = Closure(eevee_surface_lit(N, diffuse, f0, roughness, 1.0, ssr_id), 1.0); + vec3 L = eevee_surface_lit(N, diffuse, f0, roughness, 1.0, int(ssr_id), ssr_spec); + vec3 vN = mat3(ViewMatrix) * N; + result = Closure(L, 1.0, vec4(ssr_spec, roughness), vN.xy, int(ssr_id)); #else node_bsdf_principled(base_color, subsurface, subsurface_radius, subsurface_color, metallic, specular, specular_tint, roughness, anisotropic, anisotropic_rotation, sheen, sheen_tint, clearcoat, @@ -2843,7 +2852,7 @@ void node_bsdf_principled_clearcoat(vec4 base_color, float subsurface, vec3 subs float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, float ssr_id, out Closure result) { #ifdef EEVEE_ENGINE - vec3 diffuse, f0; + vec3 diffuse, f0, ssr_spec; convert_metallic_to_specular_tinted(base_color.rgb, metallic, specular, specular_tint, diffuse, f0); clearcoat *= 0.25; @@ -2871,7 +2880,10 @@ void node_bsdf_principled_clearcoat(vec4 base_color, float subsurface, vec3 subs } result = Closure(surface_color.rgb / surface_color.a, 1.0); #else - result = Closure(eevee_surface_clearcoat_lit(N, diffuse, f0, roughness, CN, clearcoat, clearcoat_roughness, 1.0, ssr_id), 1.0); + + vec3 L = eevee_surface_clearcoat_lit(N, diffuse, f0, roughness, CN, clearcoat, clearcoat_roughness, 1.0, int(ssr_id), ssr_spec); + vec3 vN = mat3(ViewMatrix) * N; + result = Closure(L, 1.0, vec4(ssr_spec, roughness), vN.xy, int(ssr_id)); #endif #else @@ -2905,6 +2917,8 @@ void node_subsurface_scattering( node_bsdf_diffuse(color, 0.0, N, result); } +/* Unsupported for now */ +#ifndef EEVEE_ENGINE void node_bsdf_hair(vec4 color, float offset, float roughnessu, float roughnessv, vec3 tangent, out Closure result) { result = Closure(color.rgb, color.a); @@ -2919,6 +2933,8 @@ void node_ambient_occlusion(vec4 color, out Closure result) { result = Closure(color.rgb, color.a); } +#endif /* EEVEE_ENGINE */ + #endif /* VOLUMETRICS */ /* emission */ @@ -2927,7 +2943,11 @@ void node_emission(vec4 color, float strength, vec3 N, out Closure result) { #ifndef VOLUMETRICS color *= strength; +#ifdef EEVEE_ENGINE + result = Closure(color.rgb, color.a, vec4(0.0), vec2(0.0), -1); +#else result = Closure(color.rgb, color.a); +#endif #else result = Closure(vec3(0.0), vec3(0.0), color.rgb * strength, 0.0); #endif @@ -2952,7 +2972,11 @@ void node_background(vec4 color, float strength, out Closure result) { #ifndef VOLUMETRICS color *= strength; +#ifdef EEVEE_ENGINE + result = Closure(color.rgb, color.a, vec4(0.0), vec2(0.0), -1); +#else result = Closure(color.rgb, color.a); +#endif #else result = CLOSURE_DEFAULT; #endif @@ -3995,7 +4019,11 @@ uniform float backgroundAlpha; void node_output_world(Closure surface, Closure volume, out Closure result) { #ifndef VOLUMETRICS +#ifdef EEVEE_ENGINE + result = Closure(surface.radiance, backgroundAlpha, vec4(0.0), vec2(0.0), -1); +#else result = Closure(surface.radiance, backgroundAlpha); +#endif #else result = volume; #endif /* VOLUMETRICS */ @@ -4015,10 +4043,12 @@ void node_eevee_metallic( float clearcoat, float clearcoat_roughness, vec3 clearcoat_normal, float occlusion, float ssr_id, out Closure result) { - vec3 diffuse, f0; + vec3 diffuse, f0, ssr_spec; convert_metallic_to_specular(basecol.rgb, metallic, specular, diffuse, f0); - result = Closure(eevee_surface_lit(normal, diffuse, f0, roughness, occlusion, ssr_id) + emissive.rgb, 1.0 - transp); + vec3 L = eevee_surface_lit(normal, diffuse, f0, roughness, occlusion, int(ssr_id), ssr_spec); + vec3 vN = mat3(ViewMatrix) * normal; + result = Closure(L + emissive.rgb, 1.0 - transp, vec4(ssr_spec, roughness), vN.xy, int(ssr_id)); } void node_eevee_specular( @@ -4026,7 +4056,11 @@ void node_eevee_specular( float clearcoat, float clearcoat_roughness, vec3 clearcoat_normal, float occlusion, float ssr_id, out Closure result) { - result = Closure(eevee_surface_lit(normal, diffuse.rgb, specular.rgb, roughness, occlusion, ssr_id) + emissive.rgb, 1.0 - transp); + vec3 ssr_spec; + + vec3 L = eevee_surface_lit(normal, diffuse.rgb, specular.rgb, roughness, occlusion, int(ssr_id), ssr_spec); + vec3 vN = mat3(ViewMatrix) * normal; + result = Closure(L + emissive.rgb, 1.0 - transp, vec4(ssr_spec, roughness), vN.xy, int(ssr_id)); } void node_output_eevee_material(Closure surface, out Closure result) @@ -4034,7 +4068,8 @@ void node_output_eevee_material(Closure surface, out Closure result) #if defined(USE_ALPHA_HASH) || defined(USE_ALPHA_CLIP) || defined(USE_ALPHA_BLEND) result = surface; #else - result = Closure(surface.radiance, length(viewPosition)); + result = surface; + result.opacity = length(viewPosition); #endif } diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index a16644207cf..a0f8f500d26 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -2622,6 +2622,7 @@ RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(volumetric_light_clamp) RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(volumetric_shadows) RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(volumetric_shadow_samples) RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(volumetric_colored_transmittance) +RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(ssr_enable) /* object engine */ RNA_LAYER_MODE_OBJECT_GET_SET_BOOL(show_wire) @@ -6176,6 +6177,14 @@ static void rna_def_scene_layer_engine_settings_eevee(BlenderRNA *brna) /* see RNA_LAYER_ENGINE_GET_SET macro */ + /* Screen Space Reflection */ + prop = RNA_def_property(srna, "ssr_enable", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_ssr_enable_get", + "rna_LayerEngineSettings_Eevee_ssr_enable_set"); + RNA_def_property_ui_text(prop, "SSR", "Enable screen space reflection"); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_SceneLayerEngineSettings_update"); + /* Volumetrics */ prop = RNA_def_property(srna, "volumetric_enable", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_volumetric_enable_get", diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c index 456c000a39b..35121b2afed 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c @@ -51,7 +51,7 @@ static int node_shader_gpu_bsdf_glossy(GPUMaterial *mat, bNode *node, bNodeExecD if (!in[2].link) GPU_link(mat, "world_normals_get", &in[2].link); - return GPU_stack_link(mat, node, "node_bsdf_glossy", in, out); + return GPU_stack_link(mat, node, "node_bsdf_glossy", in, out, GPU_uniform(&node->ssr_id)); } /* node type definition */ |