diff --git a/base/renderprogs/bumpyenvironment.pixel b/base/renderprogs/bumpyenvironment.pixel index 8bfb4fbf..2c489c63 100644 --- a/base/renderprogs/bumpyenvironment.pixel +++ b/base/renderprogs/bumpyenvironment.pixel @@ -71,5 +71,5 @@ void main( PS_IN fragment, out PS_OUT result ) { float4 envMap = texCUBE( samp0, reflectionVector ); - result.color = float4( envMap.xyz, 1.0f ) * fragment.color; + result.color = float4( sRGBToLinearRGB( envMap.xyz ), 1.0f ) * fragment.color; } diff --git a/base/renderprogs/environment.pixel b/base/renderprogs/environment.pixel index 2952f4ce..4d7e831f 100644 --- a/base/renderprogs/environment.pixel +++ b/base/renderprogs/environment.pixel @@ -52,5 +52,5 @@ void main( PS_IN fragment, out PS_OUT result ) { float4 envMap = texCUBE( samp0, reflectionVector ); - result.color = float4( envMap.xyz, 1.0f ) * fragment.color; + result.color = float4( sRGBToLinearRGB( envMap.xyz ), 1.0f ) * fragment.color; } diff --git a/base/renderprogs/environment_skinned.pixel b/base/renderprogs/environment_skinned.pixel index 2952f4ce..4d7e831f 100644 --- a/base/renderprogs/environment_skinned.pixel +++ b/base/renderprogs/environment_skinned.pixel @@ -52,5 +52,5 @@ void main( PS_IN fragment, out PS_OUT result ) { float4 envMap = texCUBE( samp0, reflectionVector ); - result.color = float4( envMap.xyz, 1.0f ) * fragment.color; + result.color = float4( sRGBToLinearRGB( envMap.xyz ), 1.0f ) * fragment.color; } diff --git a/base/renderprogs/tonemap.pixel b/base/renderprogs/tonemap.pixel index 85575a24..58c575b7 100644 --- a/base/renderprogs/tonemap.pixel +++ b/base/renderprogs/tonemap.pixel @@ -137,6 +137,20 @@ void main( PS_IN fragment, out PS_OUT result ) #elif OPERATOR == 2 + // can be in range [-4.0 .. 4.0] + //float exposureOffset = rpScreenCorrectionFactor.w; + + float avgLuminance = max( hdrAverageLuminance, 0.001 ); + float linearExposure = ( hdrKey / avgLuminance ); + float exposure = log2( max( linearExposure, 0.0001 ) ); + + //exposure = -2.0; + float3 exposedColor = exp2( exposure ) * color.rgb; + + color.rgb = ACESFilm( exposedColor ); + +#elif OPERATOR == 3 + // can be in range [-4.0 .. 4.0] float exposure = rpScreenCorrectionFactor.w; @@ -148,7 +162,8 @@ void main( PS_IN fragment, out PS_OUT result ) float3 whiteScale = 1.0 / ACESFilm( float3( Ymax ) ); color.rgb = curr * whiteScale; -#elif OPERATOR == 3 + +#elif OPERATOR == 4 // Uncharted 2 tone mapping based on Kodak film curve //float exposure = ( hdrKey / hdrAverageLuminance ) * 0.2; diff --git a/base/renderprogs/wobblesky.pixel b/base/renderprogs/wobblesky.pixel index c52765c2..4b32ce90 100644 --- a/base/renderprogs/wobblesky.pixel +++ b/base/renderprogs/wobblesky.pixel @@ -41,5 +41,5 @@ struct PS_OUT { }; void main( PS_IN fragment, out PS_OUT result ) { - result.color = texCUBE( samp0, fragment.texcoord0 ) * fragment.color; + result.color = sRGBAToLinearRGBA( texCUBE( samp0, fragment.texcoord0 ) ) * fragment.color; } diff --git a/neo/renderer/RenderSystem_init.cpp b/neo/renderer/RenderSystem_init.cpp index b0b895a7..8b21ee16 100644 --- a/neo/renderer/RenderSystem_init.cpp +++ b/neo/renderer/RenderSystem_init.cpp @@ -247,11 +247,11 @@ idCVar r_shadowMapSunDepthBiasScale( "r_shadowMapSunDepthBiasScale", "0.999991", // RB: HDR parameters idCVar r_useHDR( "r_useHDR", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "use high dynamic range rendering" ); idCVar r_hdrAutoExposure( "r_hdrAutoExposure", "1", CVAR_RENDERER | CVAR_BOOL, "EXPENSIVE: enables adapative HDR tone mapping otherwise the exposure is derived by r_exposure" ); -idCVar r_hdrMinLuminance( "r_hdrMinLuminance", "0.05", CVAR_RENDERER | CVAR_FLOAT, "" ); +idCVar r_hdrMinLuminance( "r_hdrMinLuminance", "0.005", CVAR_RENDERER | CVAR_FLOAT, "" ); idCVar r_hdrMaxLuminance( "r_hdrMaxLuminance", "300", CVAR_RENDERER | CVAR_FLOAT, "" ); -idCVar r_hdrKey( "r_hdrKey", "1.0", CVAR_RENDERER | CVAR_FLOAT, "mid-gray 0.5 in linear RGB space (without gamma curve applied)" ); -idCVar r_hdrContrastDynamicThreshold( "r_hdrContrastDynamicThreshold", "33", CVAR_RENDERER | CVAR_FLOAT, "if dynamic tonemapping is on, all pixels brighter than this cause HDR bloom glares" ); -idCVar r_hdrContrastStaticThreshold( "r_hdrContrastStaticThreshold", "0.5", CVAR_RENDERER | CVAR_FLOAT, "if dynamic tonemapping is off, all pixels brighter than this cause HDR bloom glares" ); +idCVar r_hdrKey( "r_hdrKey", "0.015", CVAR_RENDERER | CVAR_FLOAT, "magic exposure key that works well with Doom 3 maps" ); +idCVar r_hdrContrastDynamicThreshold( "r_hdrContrastDynamicThreshold", "2", CVAR_RENDERER | CVAR_FLOAT, "if auto exposure is on, all pixels brighter than this cause HDR bloom glares" ); +idCVar r_hdrContrastStaticThreshold( "r_hdrContrastStaticThreshold", "3", CVAR_RENDERER | CVAR_FLOAT, "if auto exposure is off, all pixels brighter than this cause HDR bloom glares" ); idCVar r_hdrContrastOffset( "r_hdrContrastOffset", "100", CVAR_RENDERER | CVAR_FLOAT, "" ); idCVar r_hdrGlarePasses( "r_hdrGlarePasses", "8", CVAR_RENDERER | CVAR_INTEGER, "how many times the bloom blur is rendered offscreen. number should be even" ); idCVar r_hdrDebug( "r_hdrDebug", "0", CVAR_RENDERER | CVAR_FLOAT, "show scene luminance as heat map" ); diff --git a/neo/renderer/tr_backend_draw.cpp b/neo/renderer/tr_backend_draw.cpp index 68462b18..a48d6618 100644 --- a/neo/renderer/tr_backend_draw.cpp +++ b/neo/renderer/tr_backend_draw.cpp @@ -1812,7 +1812,7 @@ static void RB_AmbientPass( const drawSurf_t* const* drawSurfs, int numDrawSurfs idVec4 ambientColor; float ambientBoost = 1.0f; - ambientBoost += r_useSSAO.GetBool() ? 0.5f : 0.0f; + ambientBoost += r_useSSAO.GetBool() ? 0.2f : 0.0f; ambientBoost *= r_useHDR.GetBool() ? 1.1f : 1.0f; ambientColor.x = r_forceAmbient.GetFloat() * ambientBoost; ambientColor.y = r_forceAmbient.GetFloat() * ambientBoost; @@ -4242,7 +4242,7 @@ static void RB_CalculateAdaptation() // no dynamic exposure backEnd.hdrKey = r_hdrKey.GetFloat(); - backEnd.hdrAverageLuminance = 1; + backEnd.hdrAverageLuminance = r_hdrMinLuminance.GetFloat(); backEnd.hdrMaxLuminance = 1; } else @@ -4392,21 +4392,39 @@ static void RB_Tonemap( const viewDef_t* viewDef ) float screenCorrectionParm[4]; if( viewDef->is2Dgui ) { - screenCorrectionParm[0] = 1.0f; + screenCorrectionParm[0] = 2.0f; screenCorrectionParm[1] = 1.0f; screenCorrectionParm[2] = 1.0f; } else { - screenCorrectionParm[0] = backEnd.hdrKey; - screenCorrectionParm[1] = backEnd.hdrAverageLuminance; - screenCorrectionParm[2] = backEnd.hdrMaxLuminance; + if( r_hdrAutoExposure.GetBool() ) + { + float exposureOffset = Lerp( -0.01f, 0.02f, idMath::ClampFloat( 0.0, 1.0, r_exposure.GetFloat() ) ); + + screenCorrectionParm[0] = backEnd.hdrKey + exposureOffset; + screenCorrectionParm[1] = backEnd.hdrAverageLuminance; + screenCorrectionParm[2] = backEnd.hdrMaxLuminance; + screenCorrectionParm[3] = exposureOffset; + //screenCorrectionParm[3] = Lerp( -1, 5, idMath::ClampFloat( 0.0, 1.0, r_exposure.GetFloat() ) ); + } + else + { + //float exposureOffset = ( idMath::ClampFloat( 0.0, 1.0, r_exposure.GetFloat() ) * 2.0f - 1.0f ) * 0.01f; + + float exposureOffset = Lerp( -0.01f, 0.01f, idMath::ClampFloat( 0.0, 1.0, r_exposure.GetFloat() ) ); + + screenCorrectionParm[0] = 0.015f + exposureOffset; + screenCorrectionParm[1] = 0.005f; + screenCorrectionParm[2] = 1; + + // RB: this gives a nice exposure curve in Scilab when using + // log2( max( 3 + 0..10, 0.001 ) ) as input for exp2 + //float exposureOffset = r_exposure.GetFloat() * 10.0f; + //screenCorrectionParm[3] = exposureOffset; + } } - float exposure = ( r_exposure.GetFloat() * 2.0f - 1.0f ) * 4.0f; - //float exposure = r_exposure.GetFloat() * 2.0f; - screenCorrectionParm[3] = idMath::ClampFloat( -10.0f, 10.0f, exposure ); - SetFragmentParm( RENDERPARM_SCREENCORRECTIONFACTOR, screenCorrectionParm ); // rpScreenCorrectionFactor // Draw