Fixed a problem with octahedron irradiance sampling

This commit is contained in:
Robert Beckebans 2020-11-15 14:01:14 +01:00
parent b8907b9754
commit 86ff6cea87
5 changed files with 83 additions and 20 deletions

View file

@ -69,27 +69,27 @@ struct PS_OUT
Available online http://jcgt.org/published/0003/02/01/
*/
float signNotZero( in float k )
float signNotZeroFloat( float k )
{
return ( k >= 0.0 ) ? 1.0 : -1.0;
}
float2 signNotZero( in float2 v )
float2 signNotZero( float2 v )
{
return float2( signNotZero( v.x ), signNotZero( v.y ) );
return float2( signNotZeroFloat( v.x ), signNotZeroFloat( v.y ) );
}
/** Assumes that v is a unit vector. The result is an octahedral vector on the [-1, +1] square. */
float2 octEncode( in float3 v )
float2 octEncode( float3 v )
{
float l1norm = abs( v.x ) + abs( v.y ) + abs( v.z );
float2 result = v.xy * ( 1.0 / l1norm );
float2 oct = v.xy * ( 1.0 / l1norm );
if( v.z < 0.0 )
{
result = ( 1.0 - abs( result.yx ) ) * signNotZero( result.xy );
oct = ( 1.0 - abs( oct.yx ) ) * signNotZero( oct.xy );
}
return result;
return oct;
}
@ -127,6 +127,7 @@ void main( PS_IN fragment, out PS_OUT result )
globalNormal.x = dot3( localNormal, fragment.texcoord4 );
globalNormal.y = dot3( localNormal, fragment.texcoord5 );
globalNormal.z = dot3( localNormal, fragment.texcoord6 );
globalNormal = normalize( globalNormal );
float3 globalEye = normalize( fragment.texcoord3.xyz );
@ -199,7 +200,7 @@ void main( PS_IN fragment, out PS_OUT result )
float2 normalizedOctCoord = octEncode( globalNormal );
float2 normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5;
float3 irradiance = tex2D( samp7, normalizedOctCoord ).rgb;
float3 irradiance = tex2D( samp7, normalizedOctCoordZeroOne ).rgb;
float3 diffuseLight = ( kD * irradiance * diffuseColor ) * ao * ( rpDiffuseModifier.xyz * 1.0 );
// evaluate specular IBL
@ -213,6 +214,7 @@ void main( PS_IN fragment, out PS_OUT result )
normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5;
float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb;
//radiance = float3( 0.0 );
float2 envBRDF = texture( samp3, float2( max( vDotN, 0.0 ), roughness ) ).rg;

View file

@ -358,6 +358,11 @@ void idVec3::ProjectSelfOntoSphere( const float radius )
// A Survey of Efficient Representations for Independent Unit Vectors, Journal of Computer Graphics Techniques (JCGT), vol. 3, no. 2, 1-30, 2014
// Available online http://jcgt.org/published/0003/02/01/
inline float signNotZero( float k )
{
return ( k >= 0.0f ) ? 1.0f : -1.0f;
}
idVec2 idVec3::ToOctahedral() const
{
const float L1norm = idMath::Fabs( x ) + idMath::Fabs( x ) + idMath::Fabs( x );
@ -365,8 +370,8 @@ idVec2 idVec3::ToOctahedral() const
idVec2 result;
if( z < 0.0f )
{
result.x = ( 1.0f - idMath::Fabs( y ) ) * ( x >= 0.0f ) ? 1.0f : -1.0f;
result.y = ( 1.0f - idMath::Fabs( x ) ) * ( y >= 0.0f ) ? 1.0f : -1.0f;
result.x = ( 1.0f - idMath::Fabs( y ) ) * signNotZero( x );
result.y = ( 1.0f - idMath::Fabs( x ) ) * signNotZero( y );
}
else
{
@ -386,8 +391,8 @@ void idVec3::FromOctahedral( const idVec2& o )
if( z < 0.0f )
{
float oldX = x;
x = ( 1.0f - idMath::Fabs( y ) ) * ( oldX >= 0.0f ) ? 1.0f : -1.0f;
y = ( 1.0f - idMath::Fabs( oldX ) ) * ( y >= 0.0f ) ? 1.0f : -1.0f;
x = ( 1.0f - idMath::Fabs( y ) ) * signNotZero( oldX );
y = ( 1.0f - idMath::Fabs( oldX ) ) * signNotZero( y );
}
Normalize();

View file

@ -1041,8 +1041,8 @@ void idImageManager::CreateIntrinsicImages()
hellLoadingIconImage = ImageFromFile( "textures/loadingicon3", TF_DEFAULT, TR_CLAMP, TD_DEFAULT, CF_2D );
// RB begin
defaultUACIrradianceCube = ImageFromFile( "env/UAC1_amb", TF_DEFAULT, TR_CLAMP, TD_LOOKUP_TABLE_RGB1, CF_2D );
defaultUACRadianceCube = ImageFromFile( "env/UAC1_spec", TF_DEFAULT, TR_CLAMP, TD_LOOKUP_TABLE_RGB1, CF_2D );
defaultUACIrradianceCube = ImageFromFile( "env/UAC2_amb", TF_DEFAULT, TR_CLAMP, TD_LOOKUP_TABLE_RGB1, CF_2D );
defaultUACRadianceCube = ImageFromFile( "env/UAC2_spec", TF_DEFAULT, TR_CLAMP, TD_LOOKUP_TABLE_RGB1, CF_2D );
// RB end
release_assert( loadingIconImage->referencedOutsideLevelLoad );

View file

@ -2483,8 +2483,8 @@ static const cgShaderDef_t cg_renderprogs[] =
"uniform sampler2D samp3 : register(s3); // texture 3 is the BRDF LUT\n"
"uniform sampler2D samp4 : register(s4); // texture 4 is SSAO\n"
"\n"
"uniform samplerCUBE samp7 : register(s7); // texture 7 is the irradiance cube map\n"
"uniform samplerCUBE samp8 : register(s8); // texture 8 is the radiance cube map\n"
"uniform sampler2D samp7 : register(s7); // texture 7 is the irradiance cube map\n"
"uniform sampler2D samp8 : register(s8); // texture 8 is the radiance cube map\n"
"\n"
"struct PS_IN \n"
"{\n"
@ -2505,6 +2505,52 @@ static const cgShaderDef_t cg_renderprogs[] =
"};\n"
"// *INDENT-ON*\n"
"\n"
"\n"
"\n"
"/** Efficient GPU implementation of the octahedral unit vector encoding from\n"
"\n"
" Cigolle, Donow, Evangelakos, Mara, McGuire, Meyer,\n"
" A Survey of Efficient Representations for Independent Unit Vectors, Journal of Computer Graphics Techniques (JCGT), vol. 3, no. 2, 1-30, 2014\n"
"\n"
" Available online http://jcgt.org/published/0003/02/01/\n"
"*/\n"
"\n"
"float signNotZeroFloat( float k )\n"
"{\n"
" return ( k >= 0.0 ) ? 1.0 : -1.0;\n"
"}\n"
"\n"
"\n"
"float2 signNotZero( float2 v )\n"
"{\n"
" return float2( signNotZeroFloat( v.x ), signNotZeroFloat( v.y ) );\n"
"}\n"
"\n"
"/** Assumes that v is a unit vector. The result is an octahedral vector on the [-1, +1] square. */\n"
"float2 octEncode( float3 v )\n"
"{\n"
" float l1norm = abs( v.x ) + abs( v.y ) + abs( v.z );\n"
" float2 oct = v.xy * ( 1.0 / l1norm );\n"
" if( v.z < 0.0 )\n"
" {\n"
" oct = ( 1.0 - abs( oct.yx ) ) * signNotZero( oct.xy );\n"
" }\n"
" return oct;\n"
"}\n"
"\n"
"\n"
"/** Returns a unit vector. Argument o is an octahedral vector packed via octEncode,\n"
" on the [-1, +1] square*/\n"
"float3 octDecode( float2 o )\n"
"{\n"
" float3 v = float3( o.x, o.y, 1.0 - abs( o.x ) - abs( o.y ) );\n"
" if( v.z < 0.0 )\n"
" {\n"
" v.xy = ( 1.0 - abs( v.yx ) ) * signNotZero( v.xy );\n"
" }\n"
" return normalize( v );\n"
"}\n"
"\n"
"void main( PS_IN fragment, out PS_OUT result )\n"
"{\n"
" half4 bumpMap = tex2D( samp0, fragment.texcoord0.xy );\n"
@ -2527,11 +2573,12 @@ static const cgShaderDef_t cg_renderprogs[] =
" globalNormal.x = dot3( localNormal, fragment.texcoord4 );\n"
" globalNormal.y = dot3( localNormal, fragment.texcoord5 );\n"
" globalNormal.z = dot3( localNormal, fragment.texcoord6 );\n"
" globalNormal = normalize( globalNormal );\n"
"\n"
" float3 globalEye = normalize( fragment.texcoord3.xyz );\n"
"\n"
" float3 reflectionVector = globalNormal * dot3( globalEye, globalNormal );\n"
" reflectionVector = ( reflectionVector * 2.0f ) - globalEye;\n"
" reflectionVector = normalize( ( reflectionVector * 2.0f ) - globalEye );\n"
"\n"
" half vDotN = saturate( dot3( globalEye, globalNormal ) );\n"
"\n"
@ -2596,7 +2643,10 @@ static const cgShaderDef_t cg_renderprogs[] =
"\n"
" // evaluate diffuse IBL\n"
"\n"
" float3 irradiance = texCUBE( samp7, globalNormal ).rgb;\n"
" float2 normalizedOctCoord = octEncode( globalNormal );\n"
" float2 normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5;\n"
"\n"
" float3 irradiance = tex2D( samp7, normalizedOctCoordZeroOne ).rgb;\n"
" float3 diffuseLight = ( kD * irradiance * diffuseColor ) * ao * ( rpDiffuseModifier.xyz * 1.0 );\n"
"\n"
" // evaluate specular IBL\n"
@ -2605,7 +2655,12 @@ static const cgShaderDef_t cg_renderprogs[] =
" const float MAX_REFLECTION_LOD = 10.0;\n"
" float mip = clamp( ( roughness * MAX_REFLECTION_LOD ), 0.0, MAX_REFLECTION_LOD );\n"
" //float mip = 0.0;\n"
" float3 radiance = textureLod( samp8, reflectionVector, mip ).rgb;\n"
"\n"
" normalizedOctCoord = octEncode( reflectionVector );\n"
" normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5;\n"
"\n"
" float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb;\n"
" //radiance = float3( 0.0 );\n"
"\n"
" float2 envBRDF = texture( samp3, float2( max( vDotN, 0.0 ), roughness ) ).rg;\n"
"\n"

View file

@ -938,7 +938,7 @@ CONSOLE_COMMAND( generateEnvironmentProbes, "Generate environment probes", NULL
axis[5][2][1] = 1;
//--------------------------------------------
// CAPTURE SCENE LIGHTING
// CAPTURE SCENE LIGHTING TO CUBEMAPS
//--------------------------------------------
// let's get the game window to a "size" resolution
@ -975,6 +975,7 @@ CONSOLE_COMMAND( generateEnvironmentProbes, "Generate environment probes", NULL
ref.viewaxis = axis[j];
fullname.Format( "env/%s/envprobe%i%s", baseName.c_str(), i, extension );
// TODO capture resolved HDR data without bloom aka _currentRender in 16bit float HDR RGB
tr.TakeScreenshot( size, size, fullname, blends, &ref, PNG );
//tr.CaptureRenderToFile( fullname, false );
}