Octahedron mapping hello world in IBL shader

This commit is contained in:
Robert Beckebans 2020-11-14 18:02:07 +01:00
parent 2e580b38ad
commit b8907b9754
4 changed files with 63 additions and 10 deletions

View file

@ -37,8 +37,8 @@ uniform sampler2D samp2 : register(s2); // texture 2 is the per-surface baseColo
uniform sampler2D samp3 : register(s3); // texture 3 is the BRDF LUT
uniform sampler2D samp4 : register(s4); // texture 4 is SSAO
uniform samplerCUBE samp7 : register(s7); // texture 7 is the irradiance cube map
uniform samplerCUBE samp8 : register(s8); // texture 8 is the radiance cube map
uniform sampler2D samp7 : register(s7); // texture 7 is the irradiance cube map
uniform sampler2D samp8 : register(s8); // texture 8 is the radiance cube map
struct PS_IN
{
@ -59,6 +59,52 @@ struct PS_OUT
};
// *INDENT-ON*
/** Efficient GPU implementation of the octahedral unit vector encoding from
Cigolle, Donow, Evangelakos, Mara, McGuire, Meyer,
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/
*/
float signNotZero( in float k )
{
return ( k >= 0.0 ) ? 1.0 : -1.0;
}
float2 signNotZero( in float2 v )
{
return float2( signNotZero( v.x ), signNotZero( 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 )
{
float l1norm = abs( v.x ) + abs( v.y ) + abs( v.z );
float2 result = v.xy * ( 1.0 / l1norm );
if( v.z < 0.0 )
{
result = ( 1.0 - abs( result.yx ) ) * signNotZero( result.xy );
}
return result;
}
/** Returns a unit vector. Argument o is an octahedral vector packed via octEncode,
on the [-1, +1] square*/
float3 octDecode( float2 o )
{
float3 v = float3( o.x, o.y, 1.0 - abs( o.x ) - abs( o.y ) );
if( v.z < 0.0 )
{
v.xy = ( 1.0 - abs( v.yx ) ) * signNotZero( v.xy );
}
return normalize( v );
}
void main( PS_IN fragment, out PS_OUT result )
{
half4 bumpMap = tex2D( samp0, fragment.texcoord0.xy );
@ -85,7 +131,7 @@ void main( PS_IN fragment, out PS_OUT result )
float3 globalEye = normalize( fragment.texcoord3.xyz );
float3 reflectionVector = globalNormal * dot3( globalEye, globalNormal );
reflectionVector = ( reflectionVector * 2.0f ) - globalEye;
reflectionVector = normalize( ( reflectionVector * 2.0f ) - globalEye );
half vDotN = saturate( dot3( globalEye, globalNormal ) );
@ -150,7 +196,10 @@ void main( PS_IN fragment, out PS_OUT result )
// evaluate diffuse IBL
float3 irradiance = texCUBE( samp7, globalNormal ).rgb;
float2 normalizedOctCoord = octEncode( globalNormal );
float2 normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5;
float3 irradiance = tex2D( samp7, normalizedOctCoord ).rgb;
float3 diffuseLight = ( kD * irradiance * diffuseColor ) * ao * ( rpDiffuseModifier.xyz * 1.0 );
// evaluate specular IBL
@ -159,7 +208,11 @@ void main( PS_IN fragment, out PS_OUT result )
const float MAX_REFLECTION_LOD = 10.0;
float mip = clamp( ( roughness * MAX_REFLECTION_LOD ), 0.0, MAX_REFLECTION_LOD );
//float mip = 0.0;
float3 radiance = textureLod( samp8, reflectionVector, mip ).rgb;
normalizedOctCoord = octEncode( reflectionVector );
normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5;
float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb;
float2 envBRDF = texture( samp3, float2( max( vDotN, 0.0 ), roughness ) ).rg;

View file

@ -381,7 +381,7 @@ void idVec3::FromOctahedral( const idVec2& o )
{
x = o.x;
y = o.y;
z = 1.0f - idMath::Fabs( o.x ) - idMath::Fabs( o.y );
z = 1.0f - ( idMath::Fabs( o.x ) + idMath::Fabs( o.y ) );
if( z < 0.0f )
{

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/testmap_1_amb", TF_DEFAULT, TR_CLAMP, TD_HIGHQUALITY_CUBE, CF_NATIVE );
defaultUACRadianceCube = ImageFromFile( "env/testmap_1_spec", TF_DEFAULT, TR_CLAMP, TD_HIGHQUALITY_CUBE, CF_NATIVE );
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 );
// RB end
release_assert( loadingIconImage->referencedOutsideLevelLoad );

View file

@ -780,7 +780,7 @@ void R_MakeAmbientMap( const char* baseName, const char* suffix, int outSize, fl
total[2] += result[2];
}
#if 1
#if 0
outBuffer[( y * outSize + x ) * 4 + 0] = total[0] / samples;
outBuffer[( y * outSize + x ) * 4 + 1] = total[1] / samples;
outBuffer[( y * outSize + x ) * 4 + 2] = total[2] / samples;
@ -788,7 +788,7 @@ void R_MakeAmbientMap( const char* baseName, const char* suffix, int outSize, fl
#else
outBuffer[( y * outSize + x ) * 4 + 0] = byte( ( dir.x * 0.5f + 0.5f ) * 255 );
outBuffer[( y * outSize + x ) * 4 + 1] = byte( ( dir.y * 0.5f + 0.5f ) * 255 );
outBuffer[( y * outSize + x ) * 4 + 2] = 0;
outBuffer[( y * outSize + x ) * 4 + 2] = byte( ( dir.z * 0.5f + 0.5f ) * 255 );
outBuffer[( y * outSize + x ) * 4 + 3] = 255;
#endif