From c87e9e17118ef87a7b1af1c9b1fe7cd2a6ed97f9 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Sat, 25 Apr 2020 18:30:40 +0200 Subject: [PATCH] Only modulate down ambient pass with SSAO --- base/renderprogs/BRDF.inc.hlsl | 2 +- base/renderprogs/ambient_lighting_IBL.ps.hlsl | 20 ++- neo/renderer/RenderBackend.cpp | 158 +++++++++++------- neo/renderer/RenderBackend.h | 2 +- neo/renderer/RenderProgs_embedded.h | 22 ++- 5 files changed, 126 insertions(+), 78 deletions(-) diff --git a/base/renderprogs/BRDF.inc.hlsl b/base/renderprogs/BRDF.inc.hlsl index d2a2706d..7286a669 100644 --- a/base/renderprogs/BRDF.inc.hlsl +++ b/base/renderprogs/BRDF.inc.hlsl @@ -69,7 +69,7 @@ half3 Fresnel_SchlickRoughness( half3 specularColor, half vDotN, half roughness // Sébastien Lagarde proposes an empirical approach to derive the specular occlusion term from the diffuse occlusion term in [Lagarde14]. // The result does not have any physical basis but produces visually pleasant results. // See Sébastien Lagarde and Charles de Rousiers. 2014. Moving Frostbite to PBR. -float ComputeSpecularAO( float vDotN, float ao, float roughness) +float ComputeSpecularAO( float vDotN, float ao, float roughness ) { return clamp( pow( vDotN + ao, exp2( -16.0 * roughness - 1.0) ) - 1.0 + ao, 0.0, 1.0 ); } diff --git a/base/renderprogs/ambient_lighting_IBL.ps.hlsl b/base/renderprogs/ambient_lighting_IBL.ps.hlsl index 929902bc..69ebb570 100644 --- a/base/renderprogs/ambient_lighting_IBL.ps.hlsl +++ b/base/renderprogs/ambient_lighting_IBL.ps.hlsl @@ -35,7 +35,7 @@ uniform sampler2D samp0 : register(s0); // texture 1 is the per-surface normal m uniform sampler2D samp1 : register(s1); // texture 3 is the per-surface specular or roughness/metallic/AO mixer map uniform sampler2D samp2 : register(s2); // texture 2 is the per-surface baseColor map uniform sampler2D samp3 : register(s3); // texture 4 is the BRDF LUT -uniform sampler2D samp4 : register(s4); // texture 5 is unused +uniform sampler2D samp4 : register(s4); // texture 5 is SSAO uniform samplerCUBE samp7 : register(s7); // texture 6 is the irradiance cube map uniform samplerCUBE samp8 : register(s8); // texture 7 is the radiance cube map @@ -156,12 +156,20 @@ void main( PS_IN fragment, out PS_OUT result ) #endif - float3 ao = float3( 1.0, 1.0, 1.0 ); + //diffuseColor = half3( 1.0, 1.0, 1.0 ); + //diffuseColor = half3( 0.0, 0.0, 0.0 ); + + // calculate the screen texcoord in the 0.0 to 1.0 range + //float2 screenTexCoord = vposToScreenPosTexCoord( fragment.position.xy ); + float2 screenTexCoord = fragment.position.xy * rpScreenCorrectionFactor.xy; + + float ao = tex2D( samp4, screenTexCoord ).r; + //diffuseColor.rgb *= ao; // evaluate diffuse IBL float3 irradiance = texCUBE( samp7, globalNormal ).rgb; - float3 diffuseLight = ( kD * irradiance * diffuseColor ) * ( rpDiffuseModifier.xyz * 3.0 ); + float3 diffuseLight = ( kD * irradiance * diffuseColor ) * ao * ( rpDiffuseModifier.xyz * 3.0 ); // evaluate specular IBL @@ -170,9 +178,7 @@ void main( PS_IN fragment, out PS_OUT result ) float mip = clamp( ( roughness * MAX_REFLECTION_LOD ) + 0.0, 0.0, 10.0 ); float3 radiance = textureLod( samp8, reflectionVector, mip ).rgb; - // our LUT is upside down float2 envBRDF = texture( samp3, float2( max( vDotN, 0.0 ), roughness ) ).rg; - //float2 envBRDF = texture( samp3, float2( max( vDotN, 0.0), 1.0 - roughness ) ).rg; #if 0 result.color.rgb = float3( envBRDF.x, envBRDF.y, 0.0 ); @@ -180,7 +186,8 @@ void main( PS_IN fragment, out PS_OUT result ) return; #endif - float3 specularLight = radiance * ( kS * envBRDF.x + float3( envBRDF.y ) ) * ( rpSpecularModifier.xyz * 0.75 ); + float specAO = ComputeSpecularAO( vDotN, ao, roughness ); + float3 specularLight = radiance * ( kS * envBRDF.x + float3( envBRDF.y ) ) * specAO * ( rpSpecularModifier.xyz * 0.75 ); #if 0 // Marmoset Horizon Fade trick @@ -199,5 +206,6 @@ void main( PS_IN fragment, out PS_OUT result ) //result.color.rgb = localNormal.xyz * 0.5 + 0.5; //result.color.xyz = ( ( diffuseColor + specularColor ) * halfLdotN * lightColor ) * fragment.color.rgb; //result.color = ( ( diffuseColor + specularColor ) * halfLdotN * lightColor + rimColor ) * fragment.color.rgba; + //result.color.rgb = float3( ao ); result.color.w = fragment.color.a; } diff --git a/neo/renderer/RenderBackend.cpp b/neo/renderer/RenderBackend.cpp index c0048971..044851ac 100644 --- a/neo/renderer/RenderBackend.cpp +++ b/neo/renderer/RenderBackend.cpp @@ -1198,14 +1198,14 @@ GENERAL INTERACTION RENDERING const int INTERACTION_TEXUNIT_BUMP = 0; const int INTERACTION_TEXUNIT_SPECULARMIX = 1; const int INTERACTION_TEXUNIT_BASECOLOR = 2; -const int INTERACTION_TEXUNIT_FALLOFF = 3; -const int INTERACTION_TEXUNIT_PROJECTION = 4; +const int INTERACTION_TEXUNIT_FALLOFF = 3; // RB: also _brdfLut +const int INTERACTION_TEXUNIT_PROJECTION = 4; // RB: also SSAO render target const int INTERACTION_TEXUNIT_SHADOWMAPS = 5; const int INTERACTION_TEXUNIT_JITTER = 6; #if defined( USE_VULKAN ) - const int INTERACTION_TEXUNIT_AMBIENT_CUBE1 = 4; - const int INTERACTION_TEXUNIT_SPECULAR_CUBE1 = 5; + const int INTERACTION_TEXUNIT_AMBIENT_CUBE1 = 5; + const int INTERACTION_TEXUNIT_SPECULAR_CUBE1 = 6; #else const int INTERACTION_TEXUNIT_AMBIENT_CUBE1 = 7; const int INTERACTION_TEXUNIT_SPECULAR_CUBE1 = 8; @@ -1358,6 +1358,17 @@ void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din, bool useFas GL_SelectTexture( INTERACTION_TEXUNIT_FALLOFF ); globalImages->brdfLutImage->Bind(); + GL_SelectTexture( INTERACTION_TEXUNIT_PROJECTION ); + if( !r_useSSAO.GetBool() ) + { + globalImages->whiteImage->Bind(); + //globalImages->brdfLutImage->Bind(); + } + else + { + globalImages->ambientOcclusionImage[0]->Bind(); + } + GL_SelectTexture( INTERACTION_TEXUNIT_AMBIENT_CUBE1 ); globalImages->defaultUACIrradianceCube->Bind(); @@ -2186,9 +2197,10 @@ void idRenderBackend::AmbientPass( const drawSurf_t* const* drawSurfs, int numDr //} //else { -#if 1 if( fillGbuffer ) { + // TODO support PBR textures and store roughness in the alpha channel + // fill geometry buffer with normal/roughness information if( drawSurf->jointCache ) { @@ -2200,43 +2212,18 @@ void idRenderBackend::AmbientPass( const drawSurf_t* const* drawSurfs, int numDr } } else -#endif { -#if 0 - if( useIBL ) + + // TODO support PBR textures + + // draw Quake 4 style ambient + if( drawSurf->jointCache ) { - // draw Quake 4 style ambient - /* - if( drawSurf->jointCache ) - { - renderProgManager.BindShader_ImageBasedLightingSkinned(); - } - else - { - renderProgManager.BindShader_ImageBasedLighting(); - } - */ - - GL_SelectTexture( INTERACTION_TEXUNIT_AMBIENT_CUBE1 ); - globalImages->defaultUACIrradianceCube->Bind(); - - GL_SelectTexture( INTERACTION_TEXUNIT_SPECULAR_CUBE1 ); - globalImages->defaultUACRadianceCube->Bind(); + renderProgManager.BindShader_AmbientLightingSkinned(); } else -#endif { - // TODO support PBR textures - - // draw Quake 4 style ambient - if( drawSurf->jointCache ) - { - renderProgManager.BindShader_AmbientLightingSkinned(); - } - else - { - renderProgManager.BindShader_AmbientLighting(); - } + renderProgManager.BindShader_AmbientLighting(); } } } @@ -4725,7 +4712,7 @@ void idRenderBackend::Bloom( const viewDef_t* _viewDef ) } -void idRenderBackend::DrawScreenSpaceAmbientOcclusion( const viewDef_t* _viewDef ) +void idRenderBackend::DrawScreenSpaceAmbientOcclusion( const viewDef_t* _viewDef, bool downModulateScreen ) { #if !defined(USE_VULKAN) if( !_viewDef->viewEntitys || _viewDef->is2Dgui ) @@ -4891,32 +4878,52 @@ void idRenderBackend::DrawScreenSpaceAmbientOcclusion( const viewDef_t* _viewDef GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS | GLS_CULL_TWOSIDED ); - if( r_ssaoFiltering.GetBool() ) + + if( downModulateScreen ) + { + if( r_ssaoFiltering.GetBool() ) + { + globalFramebuffers.ambientOcclusionFBO[0]->Bind(); + + glClearColor( 0, 0, 0, 0 ); + glClear( GL_COLOR_BUFFER_BIT ); + + renderProgManager.BindShader_AmbientOcclusion(); + } + else + { + if( r_ssaoDebug.GetInteger() <= 0 ) + { + GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO | GLS_ALPHAMASK | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS ); + } + + if( hdrIsActive ) + { + globalFramebuffers.hdrFBO->Bind(); + } + else + { + Framebuffer::Unbind(); + } + + renderProgManager.BindShader_AmbientOcclusionAndOutput(); + } + } + else { globalFramebuffers.ambientOcclusionFBO[0]->Bind(); glClearColor( 0, 0, 0, 0 ); glClear( GL_COLOR_BUFFER_BIT ); - renderProgManager.BindShader_AmbientOcclusion(); - } - else - { - if( r_ssaoDebug.GetInteger() <= 0 ) + if( r_ssaoFiltering.GetBool() ) { - GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO | GLS_ALPHAMASK | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS ); - } - - if( hdrIsActive ) - { - globalFramebuffers.hdrFBO->Bind(); + renderProgManager.BindShader_AmbientOcclusion(); } else { - Framebuffer::Unbind(); + renderProgManager.BindShader_AmbientOcclusionAndOutput(); } - - renderProgManager.BindShader_AmbientOcclusionAndOutput(); } float screenCorrectionParm[4]; @@ -4996,18 +5003,25 @@ void idRenderBackend::DrawScreenSpaceAmbientOcclusion( const viewDef_t* _viewDef #endif // AO blur Y - if( hdrIsActive ) + if( downModulateScreen ) { - globalFramebuffers.hdrFBO->Bind(); + if( hdrIsActive ) + { + globalFramebuffers.hdrFBO->Bind(); + } + else + { + Framebuffer::Unbind(); + } + + if( r_ssaoDebug.GetInteger() <= 0 ) + { + GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS ); + } } else { - Framebuffer::Unbind(); - } - - if( r_ssaoDebug.GetInteger() <= 0 ) - { - GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS ); + globalFramebuffers.ambientOcclusionFBO[0]->Bind(); } renderProgManager.BindShader_AmbientOcclusionBlurAndOutput(); @@ -5025,6 +5039,19 @@ void idRenderBackend::DrawScreenSpaceAmbientOcclusion( const viewDef_t* _viewDef DrawElementsWithCounters( &unitSquareSurface ); } + if( !downModulateScreen ) + { + // go back to main scene render target + if( hdrIsActive ) + { + globalFramebuffers.hdrFBO->Bind(); + } + else + { + Framebuffer::Unbind(); + } + } + renderProgManager.Unbind(); GL_State( GLS_DEFAULT ); @@ -5520,7 +5547,12 @@ void idRenderBackend::DrawViewInternal( const viewDef_t* _viewDef, const int ste AmbientPass( drawSurfs, numDrawSurfs, true ); //------------------------------------------------- - // fill the depth buffer and the color buffer with precomputed Q3A style lighting + // build hierarchical depth buffer and SSAO render target + //------------------------------------------------- + DrawScreenSpaceAmbientOcclusion( _viewDef, false ); + + //------------------------------------------------- + // render static lighting and consider SSAO results //------------------------------------------------- AmbientPass( drawSurfs, numDrawSurfs, false ); @@ -5541,7 +5573,7 @@ void idRenderBackend::DrawViewInternal( const viewDef_t* _viewDef, const int ste //------------------------------------------------- // darken the scene using the screen space ambient occlusion //------------------------------------------------- - DrawScreenSpaceAmbientOcclusion( _viewDef ); + //DrawScreenSpaceAmbientOcclusion( _viewDef ); //RB_SSGI( _viewDef ); //------------------------------------------------- diff --git a/neo/renderer/RenderBackend.h b/neo/renderer/RenderBackend.h index 9c662429..80e1f23f 100644 --- a/neo/renderer/RenderBackend.h +++ b/neo/renderer/RenderBackend.h @@ -307,7 +307,7 @@ private: void Tonemap( const viewDef_t* viewDef ); void Bloom( const viewDef_t* viewDef ); - void DrawScreenSpaceAmbientOcclusion( const viewDef_t* _viewDef ); + void DrawScreenSpaceAmbientOcclusion( const viewDef_t* _viewDef, bool downModulateScreen ); void DrawScreenSpaceGlobalIllumination( const viewDef_t* _viewDef ); // Experimental feature diff --git a/neo/renderer/RenderProgs_embedded.h b/neo/renderer/RenderProgs_embedded.h index 51bbc889..73799bef 100644 --- a/neo/renderer/RenderProgs_embedded.h +++ b/neo/renderer/RenderProgs_embedded.h @@ -1809,7 +1809,7 @@ static const cgShaderDef_t cg_renderprogs[] = "// Sébastien Lagarde proposes an empirical approach to derive the specular occlusion term from the diffuse occlusion term in [Lagarde14].\n" "// The result does not have any physical basis but produces visually pleasant results.\n" "// See Sébastien Lagarde and Charles de Rousiers. 2014. Moving Frostbite to PBR.\n" - "float ComputeSpecularAO( float vDotN, float ao, float roughness)\n" + "float ComputeSpecularAO( float vDotN, float ao, float roughness )\n" "{\n" " return clamp( pow( vDotN + ao, exp2( -16.0 * roughness - 1.0) ) - 1.0 + ao, 0.0, 1.0 );\n" "}\n" @@ -2238,7 +2238,7 @@ static const cgShaderDef_t cg_renderprogs[] = "uniform sampler2D samp1 : register(s1); // texture 3 is the per-surface specular or roughness/metallic/AO mixer map\n" "uniform sampler2D samp2 : register(s2); // texture 2 is the per-surface baseColor map \n" "uniform sampler2D samp3 : register(s3); // texture 4 is the BRDF LUT\n" - "uniform sampler2D samp4 : register(s4); // texture 5 is unused\n" + "uniform sampler2D samp4 : register(s4); // texture 5 is SSAO\n" "\n" "uniform samplerCUBE samp7 : register(s7); // texture 6 is the irradiance cube map\n" "uniform samplerCUBE samp8 : register(s8); // texture 7 is the radiance cube map\n" @@ -2359,12 +2359,20 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" "#endif\n" "\n" - " float3 ao = float3( 1.0, 1.0, 1.0 );\n" + " //diffuseColor = half3( 1.0, 1.0, 1.0 );\n" + " //diffuseColor = half3( 0.0, 0.0, 0.0 );\n" + " \n" + " // calculate the screen texcoord in the 0.0 to 1.0 range\n" + " //float2 screenTexCoord = vposToScreenPosTexCoord( fragment.position.xy );\n" + " float2 screenTexCoord = fragment.position.xy * rpScreenCorrectionFactor.xy;\n" + " \n" + " float ao = tex2D( samp4, screenTexCoord ).r;\n" + " //diffuseColor.rgb *= ao;\n" "\n" " // evaluate diffuse IBL\n" "\n" " float3 irradiance = texCUBE( samp7, globalNormal ).rgb;\n" - " float3 diffuseLight = ( kD * irradiance * diffuseColor ) * ( rpDiffuseModifier.xyz * 3.0 );\n" + " float3 diffuseLight = ( kD * irradiance * diffuseColor ) * ao * ( rpDiffuseModifier.xyz * 3.0 );\n" "\n" " // evaluate specular IBL\n" "\n" @@ -2373,9 +2381,7 @@ static const cgShaderDef_t cg_renderprogs[] = " float mip = clamp( ( roughness * MAX_REFLECTION_LOD ) + 0.0, 0.0, 10.0 );\n" " float3 radiance = textureLod( samp8, reflectionVector, mip ).rgb;\n" "\n" - " // our LUT is upside down\n" " float2 envBRDF = texture( samp3, float2( max( vDotN, 0.0 ), roughness ) ).rg;\n" - " //float2 envBRDF = texture( samp3, float2( max( vDotN, 0.0), 1.0 - roughness ) ).rg;\n" "\n" "#if 0\n" " result.color.rgb = float3( envBRDF.x, envBRDF.y, 0.0 );\n" @@ -2383,7 +2389,8 @@ static const cgShaderDef_t cg_renderprogs[] = " return;\n" "#endif\n" "\n" - " float3 specularLight = radiance * ( kS * envBRDF.x + float3( envBRDF.y ) ) * ( rpSpecularModifier.xyz * 0.75 );\n" + " float specAO = ComputeSpecularAO( vDotN, ao, roughness );\n" + " float3 specularLight = radiance * ( kS * envBRDF.x + float3( envBRDF.y ) ) * specAO * ( rpSpecularModifier.xyz * 0.75 );\n" "\n" "#if 0\n" " // Marmoset Horizon Fade trick\n" @@ -2402,6 +2409,7 @@ static const cgShaderDef_t cg_renderprogs[] = " //result.color.rgb = localNormal.xyz * 0.5 + 0.5;\n" " //result.color.xyz = ( ( diffuseColor + specularColor ) * halfLdotN * lightColor ) * fragment.color.rgb;\n" " //result.color = ( ( diffuseColor + specularColor ) * halfLdotN * lightColor + rimColor ) * fragment.color.rgba;\n" + " //result.color.rgb = float3( ao );\n" " result.color.w = fragment.color.a;\n" "}\n" "\n"