mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2025-06-03 18:21:32 +00:00
Improved linear RGB lighting and added ACES tonemap
This commit is contained in:
parent
a96eb702b5
commit
f82b700598
12 changed files with 170 additions and 202 deletions
|
@ -75,7 +75,7 @@ const float invRadius2 = 1.0 / radius2;
|
||||||
const float bias = 0.01 * METERS_TO_DOOM;
|
const float bias = 0.01 * METERS_TO_DOOM;
|
||||||
|
|
||||||
/** intensity / radius^6 */
|
/** intensity / radius^6 */
|
||||||
const float intensity = 0.3;
|
const float intensity = 0.6;
|
||||||
const float intensityDivR6 = intensity / ( radius* radius* radius* radius* radius* radius );
|
const float intensityDivR6 = intensity / ( radius* radius* radius* radius* radius* radius );
|
||||||
|
|
||||||
/** The height in pixels of a 1m object if viewed from 1m away.
|
/** The height in pixels of a 1m object if viewed from 1m away.
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#define USE_OCT16 0
|
#define USE_OCT16 0
|
||||||
#define COMPUTE_PEELED_LAYER 0
|
#define COMPUTE_PEELED_LAYER 0
|
||||||
#define USE_MIPMAPS 1
|
#define USE_MIPMAPS 1
|
||||||
#define USE_TAP_NORMAL 0
|
#define USE_TAP_NORMAL 1
|
||||||
|
|
||||||
#define HIGH_QUALITY 0
|
#define HIGH_QUALITY 0
|
||||||
|
|
||||||
|
@ -473,8 +473,8 @@ void sampleIndirectLight
|
||||||
numSamplesUsed += weight_Y;
|
numSamplesUsed += weight_Y;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//irradianceSum += E;
|
irradianceSum += E;
|
||||||
irradianceSum += pow( E, float3( 2.2 ) ); // RB: to linear RGB
|
//irradianceSum += pow( E, float3( 2.2 ) ); // RB: to linear RGB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -535,8 +535,8 @@ void main( PS_IN fragment, out PS_OUT result )
|
||||||
const float solidAngleHemisphere = 2 * PI;
|
const float solidAngleHemisphere = 2 * PI;
|
||||||
float3 E_X = irradianceSum * solidAngleHemisphere / ( numSamplesUsed + 0.00001 );
|
float3 E_X = irradianceSum * solidAngleHemisphere / ( numSamplesUsed + 0.00001 );
|
||||||
|
|
||||||
//indirectColor = E_X;
|
indirectColor = E_X;
|
||||||
indirectColor = pow( E_X, float3( 1.0 / 2.2 ) ); // RB: to sRGB
|
//indirectColor = pow( E_X, float3( 1.0 / 2.2 ) ); // RB: to sRGB
|
||||||
|
|
||||||
// What is the ambient visibility of this location
|
// What is the ambient visibility of this location
|
||||||
visibility = 1 - numSamplesUsed / float( NUM_SAMPLES );
|
visibility = 1 - numSamplesUsed / float( NUM_SAMPLES );
|
||||||
|
|
|
@ -75,8 +75,8 @@ void main( PS_IN fragment, out PS_OUT result ) {
|
||||||
// RB: added abs
|
// RB: added abs
|
||||||
half3 specularContribution = _half3( pow( abs( hDotN ), specularPower ) );
|
half3 specularContribution = _half3( pow( abs( hDotN ), specularPower ) );
|
||||||
|
|
||||||
half3 diffuseColor = diffuseMap * sRGBToLinearRGB( rpDiffuseModifier.xyz ) * 1.5f;
|
half3 diffuseColor = diffuseMap * ( rpDiffuseModifier.xyz ) * 1.5f;
|
||||||
half3 specularColor = specMap.xyz * specularContribution * sRGBToLinearRGB( rpSpecularModifier.xyz );
|
half3 specularColor = specMap.xyz * specularContribution * ( rpSpecularModifier.xyz );
|
||||||
|
|
||||||
// RB: http://developer.valvesoftware.com/wiki/Half_Lambert
|
// RB: http://developer.valvesoftware.com/wiki/Half_Lambert
|
||||||
float halfLdotN = dot3( localNormal, lightVector ) * 0.5 + 0.5;
|
float halfLdotN = dot3( localNormal, lightVector ) * 0.5 + 0.5;
|
||||||
|
@ -92,6 +92,7 @@ void main( PS_IN fragment, out PS_OUT result ) {
|
||||||
half3 rimColor = sRGBToLinearRGB( half3( 0.125 ) * 1.2 ) * lightColor * pow( rim, rimPower );
|
half3 rimColor = sRGBToLinearRGB( half3( 0.125 ) * 1.2 ) * lightColor * pow( rim, rimPower );
|
||||||
|
|
||||||
//result.color.rgb = localNormal.xyz * 0.5 + 0.5;
|
//result.color.rgb = localNormal.xyz * 0.5 + 0.5;
|
||||||
result.color.xyz = ( ( diffuseColor + specularColor ) * halfLdotN * lightColor + rimColor ) * fragment.color.rgb;;
|
result.color.xyz = ( ( diffuseColor + specularColor ) * halfLdotN * lightColor + rimColor ) * fragment.color.rgb;
|
||||||
result.color.w = 1.0;
|
//result.color = ( ( diffuseColor + specularColor ) * halfLdotN * lightColor + rimColor ) * fragment.color.rgba;
|
||||||
|
result.color.w = fragment.color.a;
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,7 +134,7 @@ static float dot4( float2 a, float4 b ) { return dot( float4( a, 0, 1 ), b ); }
|
||||||
half3 sRGBToLinearRGB( half3 rgb )
|
half3 sRGBToLinearRGB( half3 rgb )
|
||||||
{
|
{
|
||||||
#if defined(USE_SRGB)
|
#if defined(USE_SRGB)
|
||||||
return pow( rgb, half3( 2.2 ) );
|
return max( pow( rgb, half3( 2.2 ) ), half3( 0.0 ) );
|
||||||
#else
|
#else
|
||||||
return rgb;
|
return rgb;
|
||||||
#endif
|
#endif
|
||||||
|
@ -143,7 +143,7 @@ half3 sRGBToLinearRGB( half3 rgb )
|
||||||
half4 sRGBAToLinearRGBA( half4 rgba )
|
half4 sRGBAToLinearRGBA( half4 rgba )
|
||||||
{
|
{
|
||||||
#if defined(USE_SRGB)
|
#if defined(USE_SRGB)
|
||||||
return pow( rgba, half4( 2.2 ) );
|
return float4( max( pow( rgba.rgb, half3( 2.2 ) ), half3( 0.0 ) ), rgba.a );
|
||||||
#else
|
#else
|
||||||
return rgba;
|
return rgba;
|
||||||
#endif
|
#endif
|
||||||
|
@ -243,7 +243,8 @@ static const half4 LUMINANCE_LINEAR = half4( 0.299, 0.587, 0.144, 0.0 );
|
||||||
static float4 idtex2Dproj( sampler2D samp, float4 texCoords ) { return tex2Dproj( samp, texCoords.xyw ); }
|
static float4 idtex2Dproj( sampler2D samp, float4 texCoords ) { return tex2Dproj( samp, texCoords.xyw ); }
|
||||||
static float4 swizzleColor( float4 c )
|
static float4 swizzleColor( float4 c )
|
||||||
{
|
{
|
||||||
return sRGBAToLinearRGBA( c );
|
return c;
|
||||||
|
//return sRGBAToLinearRGBA( c );
|
||||||
}
|
}
|
||||||
static float2 vposToScreenPosTexCoord( float2 vpos ) { return vpos.xy * rpWindowCoord.xy; }
|
static float2 vposToScreenPosTexCoord( float2 vpos ) { return vpos.xy * rpWindowCoord.xy; }
|
||||||
|
|
||||||
|
|
|
@ -60,12 +60,12 @@ void main( PS_IN fragment, out PS_OUT result )
|
||||||
half4 lightFalloff = ( idtex2Dproj( samp1, fragment.texcoord2 ) );
|
half4 lightFalloff = ( idtex2Dproj( samp1, fragment.texcoord2 ) );
|
||||||
half4 lightProj = ( idtex2Dproj( samp2, fragment.texcoord3 ) );
|
half4 lightProj = ( idtex2Dproj( samp2, fragment.texcoord3 ) );
|
||||||
half4 YCoCG = tex2D( samp3, fragment.texcoord4.xy );
|
half4 YCoCG = tex2D( samp3, fragment.texcoord4.xy );
|
||||||
half4 specMap = sRGBAToLinearRGBA( tex2D( samp4, fragment.texcoord5.xy ) );
|
half4 specMapSRGB = tex2D( samp4, fragment.texcoord5.xy );
|
||||||
|
half4 specMap = sRGBAToLinearRGBA( specMapSRGB );
|
||||||
|
|
||||||
half3 lightVector = normalize( fragment.texcoord0.xyz );
|
half3 lightVector = normalize( fragment.texcoord0.xyz );
|
||||||
half3 viewVector = normalize( fragment.texcoord6.xyz );
|
half3 viewVector = normalize( fragment.texcoord6.xyz );
|
||||||
half3 diffuseMap = sRGBToLinearRGB( ConvertYCoCgToRGB( YCoCG ) );
|
half3 diffuseMap = sRGBToLinearRGB( ConvertYCoCgToRGB( YCoCG ) );
|
||||||
//diffuseMap.r = 1.0;
|
|
||||||
|
|
||||||
half3 localNormal;
|
half3 localNormal;
|
||||||
// RB begin
|
// RB begin
|
||||||
|
@ -95,105 +95,76 @@ void main( PS_IN fragment, out PS_OUT result )
|
||||||
half3 halfAngleVector = normalize( lightVector + viewVector );
|
half3 halfAngleVector = normalize( lightVector + viewVector );
|
||||||
half hdotN = saturate( dot3( halfAngleVector, localNormal ) );
|
half hdotN = saturate( dot3( halfAngleVector, localNormal ) );
|
||||||
|
|
||||||
#if 1
|
#if 0 //defined(USE_PBR)
|
||||||
/*
|
|
||||||
Physically based shading
|
|
||||||
|
|
||||||
Lambert diffuse BRDF combined with Cook-Torrance microfacet specular BRDF
|
#if 0 //defined(USE_METALNESS)
|
||||||
|
const half metallic = specMapSRGB.g;
|
||||||
|
const half roughness = specMapSRGB.r;
|
||||||
|
const half glossiness = 1.0 - roughness;
|
||||||
|
|
||||||
D( h ) * F( v, h ) * G( l, v, h )
|
// the vast majority of real-world materials (anything not metal or gems) have F(0°)
|
||||||
f( l, v ) = diffuse + ---------------------------------
|
// values in a very narrow range (~0.02 - 0.08)
|
||||||
4 * ( n * l ) ( n * v )
|
|
||||||
*/
|
|
||||||
|
|
||||||
// RB: compensate r_lightScale 3 and the division of Pi
|
// approximate non-metals with linear RGB 0.04 which is 0.08 * 0.5 (default in UE4)
|
||||||
lambert *= 1.3;
|
const half3 dielectricColor = half3( 0.04 );
|
||||||
|
|
||||||
const half3 goldColor = half3( 1.00, 0.71, 0.29 );
|
// derive diffuse and specular from albedo(m) base color
|
||||||
|
|
||||||
//const half3 baseColor = goldColor;
|
|
||||||
const half3 baseColor = diffuseMap;
|
const half3 baseColor = diffuseMap;
|
||||||
|
|
||||||
const half metallic = 0.0;
|
half3 diffuseColor = baseColor * ( 1.0 - metallic );
|
||||||
|
half3 specularColor = lerp( dielectricColor, baseColor, metallic );
|
||||||
// rpDiffuseModifier contains light color
|
#else
|
||||||
half3 lightColor = lightProj.xyz * lightFalloff.xyz * rpDiffuseModifier.xyz;
|
|
||||||
|
|
||||||
half vdotN = saturate( dot3( viewVector, localNormal ) );
|
|
||||||
half vdotH = saturate( dot3( viewVector, halfAngleVector ) );
|
|
||||||
|
|
||||||
// the vast majority of real-world materials (anything not metal or gems) have F(0°) values in a very narrow range (~0.02 - 0.06)
|
|
||||||
|
|
||||||
// HACK calculate roughness from D3 gloss maps
|
// HACK calculate roughness from D3 gloss maps
|
||||||
// converting from linear to sRGB space give pretty results
|
float Y = dot( LUMINANCE_SRGB.rgb, specMapSRGB.rgb );
|
||||||
const half glossiness = clamp( pow( dot( LUMINANCE_VECTOR.rgb, specMap.rgb ) * 0.4, 1.0 / 2.2 ) * 1.0, 0.0, 0.98 );
|
|
||||||
|
|
||||||
const half roughness = 1.0 - glossiness;
|
//const float glossiness = clamp( 1.0 - specMapSRGB.r, 0.0, 0.98 );
|
||||||
|
const float glossiness = clamp( pow( Y, 1.0 / 2.0 ), 0.0, 0.98 );
|
||||||
|
|
||||||
|
const float roughness = 1.0 - glossiness;
|
||||||
|
|
||||||
|
half3 diffuseColor = diffuseMap;
|
||||||
|
half3 specularColor = specMap.rgb;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// RB: compensate r_lightScale 3 and the division of Pi
|
||||||
|
//lambert *= 1.3;
|
||||||
|
|
||||||
|
// rpDiffuseModifier contains light color multiplier
|
||||||
|
half3 lightColor = sRGBToLinearRGB( lightProj.xyz * lightFalloff.xyz );// * rpDiffuseModifier.xyz;
|
||||||
|
|
||||||
|
half vdotN = clamp( dot3( viewVector, localNormal ), 0.0, 1.0 );
|
||||||
|
half vdotH = clamp( dot3( viewVector, halfAngleVector ), 0.0, 1.0 );
|
||||||
|
half ldotH = clamp( dot3( lightVector, halfAngleVector ), 0.0, 1.0 );
|
||||||
|
|
||||||
// compensate r_lightScale 3 * 2
|
// compensate r_lightScale 3 * 2
|
||||||
half3 reflectColor = specMap.rgb * rpSpecularModifier.rgb * 0.5;
|
half3 reflectColor = specMap.rgb * rpSpecularModifier.rgb * 1.0;// * 0.5;
|
||||||
|
|
||||||
// alpha modifications by Disney - s2012_pbs_disney_brdf_notes_v2.pdf
|
// cheap approximation by ARM with only one division
|
||||||
const half alpha = roughness * roughness;
|
// http://community.arm.com/servlet/JiveServlet/download/96891546-19496/siggraph2015-mmg-renaldas-slides.pdf
|
||||||
|
// page 26
|
||||||
|
|
||||||
// reduce roughness range from [0 .. 1] to [0.5 .. 1]
|
float rr = roughness * roughness;
|
||||||
const half alphaG = pow( 0.5 + roughness * 0.5, 2.0 );
|
float rrrr = rr * rr;
|
||||||
|
|
||||||
//half3 D = _half3( pow( abs( hdotN ), 10.0f ) );
|
|
||||||
half3 D = _half3( Distribution_GGX( hdotN, alpha ) );
|
|
||||||
//half3 D = _half3( Distribution_GGX_1886( hdotN, alpha ) );
|
|
||||||
half3 G = _half3( Visibility_Schlick( ldotN, vdotN, alpha ) );
|
|
||||||
//half3 G = _half3( Visibility_SmithGGX( ldotN, vdotN, alpha ) );
|
|
||||||
half3 F = Fresnel_Schlick( reflectColor, vdotH );
|
|
||||||
|
|
||||||
// horizon
|
|
||||||
float horizon = 1.0 - ldotN;
|
|
||||||
horizon *= horizon;
|
|
||||||
horizon *= horizon;
|
|
||||||
half3 specLightColor = lightColor.rgb - lightColor.rgb * horizon;
|
|
||||||
|
|
||||||
float3 specularColor = saturate( D * G * ( F * ( specLightColor.rgb * lambert ) ) );
|
|
||||||
|
|
||||||
//specularColor = EnvironmentBRDFApprox( roughness, vdotN, specularColor.rgb );// * 0.45;
|
|
||||||
|
|
||||||
|
// disney GGX
|
||||||
|
float D = ( hdotN * hdotN ) * ( rrrr - 1.0 ) + 1.0;
|
||||||
|
float VFapprox = ( ldotH * ldotH ) * ( roughness + 0.5 );
|
||||||
|
half3 specularBRDF = ( rrrr / ( 4.0 * PI * D * D * VFapprox ) ) * reflectColor;
|
||||||
|
//specularBRDF = half3( 0.0 );
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
result.color = float4( _half3( F ), 1.0 );
|
result.color = float4( _half3( VFapprox ), 1.0 );
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// see http://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/
|
// see http://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/
|
||||||
lambert /= PI;
|
//lambert /= PI;
|
||||||
|
|
||||||
//half3 diffuseColor = mix( diffuseMap, F0, metal ) * rpDiffuseModifier.xyz;
|
//half3 diffuseColor = mix( diffuseMap, F0, metal ) * rpDiffuseModifier.xyz;
|
||||||
half3 diffuseColor = baseColor * rpDiffuseModifier.xyz;
|
half3 diffuseBRDF = diffuseColor * lambert * sRGBToLinearRGB( rpDiffuseModifier.xyz );
|
||||||
diffuseColor *= lightColor * lambert;
|
|
||||||
|
|
||||||
|
result.color.xyz = ( diffuseBRDF + specularBRDF ) * lightColor * fragment.color.rgb * shadow;
|
||||||
|
|
||||||
/*
|
|
||||||
maintain energy conservation
|
|
||||||
|
|
||||||
Energy conservation is a restriction on the reflection model
|
|
||||||
that requires that the total amount of reflected light
|
|
||||||
cannot be more than the incoming light.
|
|
||||||
|
|
||||||
http://www.rorydriscoll.com/2009/01/25/energy-conservation-in-games/
|
|
||||||
|
|
||||||
Cdiff + Cspec <= 1
|
|
||||||
*/
|
|
||||||
//diffuseColor.rgb *= ( half3( 1.0 ) - specularColor.rgb );
|
|
||||||
|
|
||||||
|
|
||||||
#if 0 //defined(USE_METALNESS)
|
|
||||||
//specularColor *= ( 0.96 * metallic ) * diffuseColor + half( 0.04 );
|
|
||||||
diffuseColor.rgb *= ( 1.0 - metallic );
|
|
||||||
|
|
||||||
//diffuseColor.rgb = mix( diffuseColor, specularColor, metallic );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// apply r_lightScale overbright for both diffuse and specular
|
|
||||||
result.color.xyz = ( diffuseColor + specularColor ) * fragment.color.rgb;// + rimColor;
|
|
||||||
result.color.w = 1.0;
|
result.color.w = 1.0;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
@ -205,10 +176,10 @@ void main( PS_IN fragment, out PS_OUT result )
|
||||||
const half specularPower = 10.0f;
|
const half specularPower = 10.0f;
|
||||||
|
|
||||||
// RB: added abs
|
// RB: added abs
|
||||||
half3 specularContribution = _half3( pow( abs( hdotN ), specularPower ) );
|
half3 specularContribution = _half3( pow( hdotN, specularPower ) );
|
||||||
|
|
||||||
half3 diffuseColor = diffuseMap * sRGBToLinearRGB( rpDiffuseModifier.xyz );
|
half3 diffuseColor = diffuseMap * sRGBToLinearRGB( rpDiffuseModifier.xyz );
|
||||||
half3 specularColor = specMap.xyz * specularContribution * sRGBToLinearRGB( rpSpecularModifier.xyz * 1.0 );
|
half3 specularColor = specMap.xyz * specularContribution * sRGBToLinearRGB( rpSpecularModifier.xyz );
|
||||||
half3 lightColor = sRGBToLinearRGB( lightProj.xyz * lightFalloff.xyz );
|
half3 lightColor = sRGBToLinearRGB( lightProj.xyz * lightFalloff.xyz );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -67,7 +67,8 @@ void main( PS_IN fragment, out PS_OUT result )
|
||||||
half4 lightFalloff = ( idtex2Dproj( samp1, fragment.texcoord2 ) );
|
half4 lightFalloff = ( idtex2Dproj( samp1, fragment.texcoord2 ) );
|
||||||
half4 lightProj = ( idtex2Dproj( samp2, fragment.texcoord3 ) );
|
half4 lightProj = ( idtex2Dproj( samp2, fragment.texcoord3 ) );
|
||||||
half4 YCoCG = tex2D( samp3, fragment.texcoord4.xy );
|
half4 YCoCG = tex2D( samp3, fragment.texcoord4.xy );
|
||||||
half4 specMap = sRGBAToLinearRGBA( tex2D( samp4, fragment.texcoord5.xy ) );
|
half4 specMapSRGB = tex2D( samp4, fragment.texcoord5.xy );
|
||||||
|
half4 specMap = sRGBAToLinearRGBA( specMapSRGB );
|
||||||
|
|
||||||
half3 lightVector = normalize( fragment.texcoord0.xyz );
|
half3 lightVector = normalize( fragment.texcoord0.xyz );
|
||||||
half3 viewVector = normalize( fragment.texcoord6.xyz );
|
half3 viewVector = normalize( fragment.texcoord6.xyz );
|
||||||
|
@ -272,107 +273,78 @@ void main( PS_IN fragment, out PS_OUT result )
|
||||||
|
|
||||||
|
|
||||||
half3 halfAngleVector = normalize( lightVector + viewVector );
|
half3 halfAngleVector = normalize( lightVector + viewVector );
|
||||||
half hdotN = saturate( dot3( halfAngleVector, localNormal ) );
|
half hdotN = clamp( dot3( halfAngleVector, localNormal ), 0.0, 1.0 );
|
||||||
|
|
||||||
#if 1
|
#if 0 //defined(USE_PBR)
|
||||||
/*
|
|
||||||
Physically based shading
|
|
||||||
|
|
||||||
Lambert diffuse BRDF combined with Cook-Torrance microfacet specular BRDF
|
#if 0 //defined(USE_METALNESS)
|
||||||
|
const half metallic = specMapSRGB.g;
|
||||||
|
const half roughness = specMapSRGB.r;
|
||||||
|
const half glossiness = 1.0 - roughness;
|
||||||
|
|
||||||
D( h ) * F( v, h ) * G( l, v, h )
|
// the vast majority of real-world materials (anything not metal or gems) have F(0°)
|
||||||
f( l, v ) = diffuse + ---------------------------------
|
// values in a very narrow range (~0.02 - 0.08)
|
||||||
4 * ( n * l ) ( n * v )
|
|
||||||
*/
|
|
||||||
|
|
||||||
// RB: compensate r_lightScale 3 and the division of Pi
|
// approximate non-metals with linear RGB 0.04 which is 0.08 * 0.5 (default in UE4)
|
||||||
lambert *= 1.3;
|
const half3 dielectricColor = half3( 0.04 );
|
||||||
|
|
||||||
const half3 goldColor = half3( 1.00, 0.71, 0.29 );
|
// derive diffuse and specular from albedo(m) base color
|
||||||
|
|
||||||
//const half3 baseColor = goldColor;
|
|
||||||
const half3 baseColor = diffuseMap;
|
const half3 baseColor = diffuseMap;
|
||||||
|
|
||||||
const half metallic = 0.0;
|
half3 diffuseColor = baseColor * ( 1.0 - metallic );
|
||||||
|
half3 specularColor = lerp( dielectricColor, baseColor, metallic );
|
||||||
// rpDiffuseModifier contains light color
|
#else
|
||||||
half3 lightColor = lightProj.xyz * lightFalloff.xyz * rpDiffuseModifier.xyz;
|
|
||||||
|
|
||||||
half vdotN = saturate( dot3( viewVector, localNormal ) );
|
|
||||||
half vdotH = saturate( dot3( viewVector, halfAngleVector ) );
|
|
||||||
|
|
||||||
// the vast majority of real-world materials (anything not metal or gems) have F(0°) values in a very narrow range (~0.02 - 0.06)
|
|
||||||
|
|
||||||
// HACK calculate roughness from D3 gloss maps
|
// HACK calculate roughness from D3 gloss maps
|
||||||
// converting from linear to sRGB space give pretty results
|
float Y = dot( LUMINANCE_SRGB.rgb, specMapSRGB.rgb );
|
||||||
const half glossiness = clamp( pow( dot( LUMINANCE_VECTOR.rgb, specMap.rgb ) * 0.4, 1.0 / 2.2 ) * 1.0, 0.0, 0.98 );
|
|
||||||
|
|
||||||
const half roughness = 1.0 - glossiness;
|
//const float glossiness = clamp( 1.0 - specMapSRGB.r, 0.0, 0.98 );
|
||||||
|
const float glossiness = clamp( pow( Y, 1.0 / 2.0 ), 0.0, 0.98 );
|
||||||
|
|
||||||
|
const float roughness = 1.0 - glossiness;
|
||||||
|
|
||||||
|
half3 diffuseColor = diffuseMap;
|
||||||
|
half3 specularColor = specMap.rgb;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// RB: compensate r_lightScale 3 and the division of Pi
|
||||||
|
//lambert *= 1.3;
|
||||||
|
|
||||||
|
// rpDiffuseModifier contains light color multiplier
|
||||||
|
half3 lightColor = sRGBToLinearRGB( lightProj.xyz * lightFalloff.xyz );// * rpDiffuseModifier.xyz;
|
||||||
|
|
||||||
|
half vdotN = clamp( dot3( viewVector, localNormal ), 0.0, 1.0 );
|
||||||
|
half vdotH = clamp( dot3( viewVector, halfAngleVector ), 0.0, 1.0 );
|
||||||
|
half ldotH = clamp( dot3( lightVector, halfAngleVector ), 0.0, 1.0 );
|
||||||
|
|
||||||
// compensate r_lightScale 3 * 2
|
// compensate r_lightScale 3 * 2
|
||||||
half3 reflectColor = specMap.rgb * rpSpecularModifier.rgb * 0.5;
|
half3 reflectColor = specMap.rgb * rpSpecularModifier.rgb * 1.0;// * 0.5;
|
||||||
|
|
||||||
// alpha modifications by Disney - s2012_pbs_disney_brdf_notes_v2.pdf
|
// cheap approximation by ARM with only one division
|
||||||
const half alpha = roughness * roughness;
|
// http://community.arm.com/servlet/JiveServlet/download/96891546-19496/siggraph2015-mmg-renaldas-slides.pdf
|
||||||
|
// page 26
|
||||||
|
|
||||||
// reduce roughness range from [0 .. 1] to [0.5 .. 1]
|
float rr = roughness * roughness;
|
||||||
const half alphaG = pow( 0.5 + roughness * 0.5, 2.0 );
|
float rrrr = rr * rr;
|
||||||
|
|
||||||
//half3 D = _half3( pow( abs( hdotN ), 10.0f ) );
|
|
||||||
half3 D = _half3( Distribution_GGX( hdotN, alpha ) );
|
|
||||||
//half3 D = _half3( Distribution_GGX_1886( hdotN, alpha ) );
|
|
||||||
half3 G = _half3( Visibility_Schlick( ldotN, vdotN, alpha ) );
|
|
||||||
//half3 G = _half3( Visibility_SmithGGX( ldotN, vdotN, alpha ) );
|
|
||||||
half3 F = Fresnel_Schlick( reflectColor, vdotH );
|
|
||||||
|
|
||||||
// horizon
|
|
||||||
float horizon = 1.0 - ldotN;
|
|
||||||
horizon *= horizon;
|
|
||||||
horizon *= horizon;
|
|
||||||
half3 specLightColor = lightColor.rgb - lightColor.rgb * horizon;
|
|
||||||
|
|
||||||
float3 specularColor = saturate( D * G * ( F * ( specLightColor.rgb * lambert ) ) );
|
|
||||||
|
|
||||||
//specularColor = EnvironmentBRDFApprox( roughness, vdotN, specularColor.rgb );// * 0.45;
|
|
||||||
|
|
||||||
|
// disney GGX
|
||||||
|
float D = ( hdotN * hdotN ) * ( rrrr - 1.0 ) + 1.0;
|
||||||
|
float VFapprox = ( ldotH * ldotH ) * ( roughness + 0.5 );
|
||||||
|
half3 specularBRDF = ( rrrr / ( 4.0 * PI * D * D * VFapprox ) ) * reflectColor;
|
||||||
|
//specularBRDF = half3( 0.0 );
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
result.color = float4( _half3( F ), 1.0 );
|
result.color = float4( _half3( VFapprox ), 1.0 );
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// see http://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/
|
// see http://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/
|
||||||
lambert /= PI;
|
//lambert /= PI;
|
||||||
|
|
||||||
//half3 diffuseColor = mix( diffuseMap, F0, metal ) * rpDiffuseModifier.xyz;
|
//half3 diffuseColor = mix( diffuseMap, F0, metal ) * rpDiffuseModifier.xyz;
|
||||||
half3 diffuseColor = baseColor * rpDiffuseModifier.xyz;
|
half3 diffuseBRDF = diffuseColor * lambert * sRGBToLinearRGB( rpDiffuseModifier.xyz );
|
||||||
diffuseColor *= lightColor * lambert;
|
|
||||||
|
|
||||||
|
result.color.xyz = ( diffuseBRDF + specularBRDF ) * lightColor * fragment.color.rgb * shadow;
|
||||||
|
|
||||||
/*
|
|
||||||
maintain energy conservation
|
|
||||||
|
|
||||||
Energy conservation is a restriction on the reflection model
|
|
||||||
that requires that the total amount of reflected light
|
|
||||||
cannot be more than the incoming light.
|
|
||||||
|
|
||||||
http://www.rorydriscoll.com/2009/01/25/energy-conservation-in-games/
|
|
||||||
|
|
||||||
Cdiff + Cspec <= 1
|
|
||||||
*/
|
|
||||||
//diffuseColor.rgb *= ( half3( 1.0 ) - specularColor.rgb );
|
|
||||||
|
|
||||||
|
|
||||||
#if 0 //defined(USE_METALNESS)
|
|
||||||
//specularColor *= ( 0.96 * metallic ) * diffuseColor + half( 0.04 );
|
|
||||||
diffuseColor.rgb *= ( 1.0 - metallic );
|
|
||||||
|
|
||||||
//diffuseColor.rgb = mix( diffuseColor, specularColor, metallic );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// apply r_lightScale overbright for both diffuse and specular
|
|
||||||
result.color.xyz = ( diffuseColor + specularColor ) * fragment.color.rgb * shadow;// + rimColor;
|
|
||||||
result.color.w = 1.0;
|
result.color.w = 1.0;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
@ -384,11 +356,11 @@ void main( PS_IN fragment, out PS_OUT result )
|
||||||
const half specularPower = 10.0f;
|
const half specularPower = 10.0f;
|
||||||
|
|
||||||
// RB: added abs
|
// RB: added abs
|
||||||
half3 specularContribution = _half3( pow( abs( hdotN ), specularPower ) );
|
half3 specularContribution = _half3( pow( hdotN, specularPower ) );
|
||||||
|
|
||||||
half3 diffuseColor = diffuseMap * rpDiffuseModifier.xyz;
|
half3 diffuseColor = diffuseMap * sRGBToLinearRGB( rpDiffuseModifier.xyz );
|
||||||
half3 specularColor = specMap.xyz * specularContribution * rpSpecularModifier.xyz;
|
half3 specularColor = specMap.xyz * specularContribution * sRGBToLinearRGB( rpSpecularModifier.xyz );
|
||||||
half3 lightColor = lightProj.xyz * lightFalloff.xyz;
|
half3 lightColor = sRGBToLinearRGB( lightProj.xyz * lightFalloff.xyz );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
half rim = 1.0f - saturate( hdotN );
|
half rim = 1.0f - saturate( hdotN );
|
||||||
|
|
|
@ -43,5 +43,5 @@ struct PS_OUT {
|
||||||
void main( PS_IN fragment, out PS_OUT result ) {
|
void main( PS_IN fragment, out PS_OUT result ) {
|
||||||
float4 color = tex2D( samp0, fragment.texcoord0 ) * fragment.color;
|
float4 color = tex2D( samp0, fragment.texcoord0 ) * fragment.color;
|
||||||
clip( color.a - rpAlphaTest.x );
|
clip( color.a - rpAlphaTest.x );
|
||||||
result.color = color;
|
result.color = sRGBAToLinearRGBA( color );
|
||||||
}
|
}
|
|
@ -43,5 +43,5 @@ struct PS_OUT {
|
||||||
void main( PS_IN fragment, out PS_OUT result ) {
|
void main( PS_IN fragment, out PS_OUT result ) {
|
||||||
float4 color = tex2D( samp0, fragment.texcoord0 ) * fragment.color;
|
float4 color = tex2D( samp0, fragment.texcoord0 ) * fragment.color;
|
||||||
clip( color.a - rpAlphaTest.x );
|
clip( color.a - rpAlphaTest.x );
|
||||||
result.color = color;
|
result.color = sRGBAToLinearRGBA( color );
|
||||||
}
|
}
|
|
@ -48,5 +48,5 @@ void main( PS_IN fragment, out PS_OUT result ) {
|
||||||
// gets called.
|
// gets called.
|
||||||
float4 texSample = idtex2Dproj( samp0, fragment.texcoord0 );
|
float4 texSample = idtex2Dproj( samp0, fragment.texcoord0 );
|
||||||
|
|
||||||
result.color = texSample * fragment.color;
|
result.color = sRGBAToLinearRGBA( texSample ) * fragment.color;
|
||||||
}
|
}
|
|
@ -43,6 +43,10 @@ struct PS_OUT
|
||||||
float4 color : COLOR;
|
float4 color : COLOR;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
float3 Uncharted2Tonemap( float3 x )
|
||||||
|
{
|
||||||
float A = 0.22; // shoulder strength
|
float A = 0.22; // shoulder strength
|
||||||
float B = 0.3; // linear strength
|
float B = 0.3; // linear strength
|
||||||
float C = 0.10; // linear angle
|
float C = 0.10; // linear angle
|
||||||
|
@ -51,11 +55,20 @@ float E = 0.01; // toe numerator
|
||||||
float F = 0.30; // toe denominator
|
float F = 0.30; // toe denominator
|
||||||
float W = 11.2; // linear white point
|
float W = 11.2; // linear white point
|
||||||
|
|
||||||
float3 Uncharted2Tonemap( float3 x )
|
|
||||||
{
|
|
||||||
return ( ( x * ( A * x + C * B ) + D * E ) / ( x * ( A * x + B ) + D * F ) ) - E / F;
|
return ( ( x * ( A * x + C * B ) + D * E ) / ( x * ( A * x + B ) + D * F ) ) - E / F;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/
|
||||||
|
float3 ACESFilm( float3 x )
|
||||||
|
{
|
||||||
|
float a = 2.51;
|
||||||
|
float b = 0.03;
|
||||||
|
float c = 2.43;
|
||||||
|
float d = 0.59;
|
||||||
|
float e = 0.14;
|
||||||
|
return saturate( ( x * ( a * x + b ) ) / ( x * ( c * x + d ) + e ) );
|
||||||
|
}
|
||||||
|
|
||||||
void main( PS_IN fragment, out PS_OUT result )
|
void main( PS_IN fragment, out PS_OUT result )
|
||||||
{
|
{
|
||||||
float2 tCoords = fragment.texcoord0;
|
float2 tCoords = fragment.texcoord0;
|
||||||
|
@ -98,18 +111,20 @@ void main( PS_IN fragment, out PS_OUT result )
|
||||||
|
|
||||||
float Ymax = hdrMaxLuminance;
|
float Ymax = hdrMaxLuminance;
|
||||||
|
|
||||||
|
#define OPERATOR 2
|
||||||
|
|
||||||
#if 0
|
#if OPERATOR == 0
|
||||||
// advanced Reinhard operator, artistically desirable to burn out bright areas
|
// advanced Reinhard operator, artistically desirable to burn out bright areas
|
||||||
float L = Yr * ( 1.0 + Yr / ( Ymax * Ymax ) ) / ( 1.0 + Yr );
|
float L = Yr * ( 1.0 + Yr / ( Ymax * Ymax ) ) / ( 1.0 + Yr );
|
||||||
color.rgb *= L;
|
color.rgb *= L;
|
||||||
|
|
||||||
|
#elif OPERATOR == 1
|
||||||
// http://freespace.virgin.net/hugo.elias/graphics/x_posure.htm
|
// http://freespace.virgin.net/hugo.elias/graphics/x_posure.htm
|
||||||
// exponential tone mapper that is very similar to the Uncharted one
|
// exponential tone mapper that is very similar to the Uncharted one
|
||||||
// very good in keeping the colors natural
|
// very good in keeping the colors natural
|
||||||
//float exposure = 1.0;
|
float exposure = 1.0;
|
||||||
//float L = ( 1.0 - exp( -Yr * exposure ) );
|
float L = ( 1.0 - exp( -Yr * exposure ) );
|
||||||
//color.rgb *= L;
|
color.rgb *= L;
|
||||||
|
|
||||||
// Kodak filmic tone mappping, includes gamma correction
|
// Kodak filmic tone mappping, includes gamma correction
|
||||||
//float3 rgb = max( float3( 0 ), color.rgb - float3( 0.004 ) );
|
//float3 rgb = max( float3( 0 ), color.rgb - float3( 0.004 ) );
|
||||||
|
@ -120,7 +135,15 @@ void main( PS_IN fragment, out PS_OUT result )
|
||||||
//color.rgb += ( cutoff * 2.0 - color.rgb ) * saturate( cutoff * 2 - color.rgb ) * ( 0.25 / cutoff ) - cutoff;
|
//color.rgb += ( cutoff * 2.0 - color.rgb ) * saturate( cutoff * 2 - color.rgb ) * ( 0.25 / cutoff ) - cutoff;
|
||||||
//color.rgb = color.rgb * ( float3( 0.5 ) + 6.2 * color.rgb ) / ( float3( 0.06 ) + color.rgb * ( float3( 1.7 ) + 6.2 * color.rgb ) );
|
//color.rgb = color.rgb * ( float3( 0.5 ) + 6.2 * color.rgb ) / ( float3( 0.06 ) + color.rgb * ( float3( 1.7 ) + 6.2 * color.rgb ) );
|
||||||
|
|
||||||
#else
|
#elif OPERATOR == 2
|
||||||
|
float exposure = 1.0;
|
||||||
|
float3 exposedColor = exposure * color.rgb;
|
||||||
|
|
||||||
|
float3 curr = ACESFilm( exposedColor );
|
||||||
|
|
||||||
|
float3 whiteScale = 1.0 / ACESFilm( float3( Ymax ) );
|
||||||
|
color.rgb = curr * whiteScale;
|
||||||
|
#elif OPERATOR == 3
|
||||||
// Uncharted 2 tone mapping based on Kodak film curve
|
// Uncharted 2 tone mapping based on Kodak film curve
|
||||||
|
|
||||||
//float exposure = ( hdrKey / hdrAverageLuminance ) * 0.2;
|
//float exposure = ( hdrKey / hdrAverageLuminance ) * 0.2;
|
||||||
|
|
|
@ -248,8 +248,8 @@ idCVar r_shadowMapSunDepthBiasScale( "r_shadowMapSunDepthBiasScale", "0.999991",
|
||||||
idCVar r_useHDR( "r_useHDR", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "use high dynamic range rendering" );
|
idCVar r_useHDR( "r_useHDR", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "use high dynamic range rendering" );
|
||||||
idCVar r_hdrMinLuminance( "r_hdrMinLuminance", "0.05", CVAR_RENDERER | CVAR_FLOAT, "" );
|
idCVar r_hdrMinLuminance( "r_hdrMinLuminance", "0.05", CVAR_RENDERER | CVAR_FLOAT, "" );
|
||||||
idCVar r_hdrMaxLuminance( "r_hdrMaxLuminance", "300", CVAR_RENDERER | CVAR_FLOAT, "" );
|
idCVar r_hdrMaxLuminance( "r_hdrMaxLuminance", "300", CVAR_RENDERER | CVAR_FLOAT, "" );
|
||||||
idCVar r_hdrKey( "r_hdrKey", "0.5", CVAR_RENDERER | CVAR_FLOAT, "mid-gray 0.5 in linear RGB space (without gamma curve applied)" );
|
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_hdrContrastThreshold( "r_hdrContrastThreshold", "13", CVAR_RENDERER | CVAR_FLOAT, "all pixels brighter than this cause HDR bloom glares" );
|
idCVar r_hdrContrastThreshold( "r_hdrContrastThreshold", "33", CVAR_RENDERER | CVAR_FLOAT, "all pixels brighter than this cause HDR bloom glares" );
|
||||||
idCVar r_hdrContrastOffset( "r_hdrContrastOffset", "100", CVAR_RENDERER | CVAR_FLOAT, "" );
|
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_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" );
|
idCVar r_hdrDebug( "r_hdrDebug", "0", CVAR_RENDERER | CVAR_FLOAT, "show scene luminance as heat map" );
|
||||||
|
|
|
@ -5244,7 +5244,7 @@ void RB_DrawViewInternal( const viewDef_t* viewDef, const int stereoEye )
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// darken the scene using the screen space ambient occlusion result
|
// darken the scene using the screen space ambient occlusion result
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
//RB_SSAO( viewDef );
|
RB_SSAO( viewDef );
|
||||||
//RB_SSGI( viewDef );
|
//RB_SSGI( viewDef );
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
@ -5271,7 +5271,7 @@ void RB_DrawViewInternal( const viewDef_t* viewDef, const int stereoEye )
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// use direct light and emissive light contributions to add indirect screen space light
|
// use direct light and emissive light contributions to add indirect screen space light
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
RB_SSGI( viewDef );
|
//RB_SSGI( viewDef );
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// fog and blend lights, drawn after emissive surfaces
|
// fog and blend lights, drawn after emissive surfaces
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue