From b8907b9754d72bc3f3bb04e9d74e505935d7a79b Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Sat, 14 Nov 2020 18:02:07 +0100 Subject: [PATCH] Octahedron mapping hello world in IBL shader --- base/renderprogs/ambient_lighting_IBL.ps.hlsl | 63 +++++++++++++++++-- neo/idlib/math/Vector.cpp | 2 +- neo/renderer/Image_intrinsic.cpp | 4 +- neo/renderer/RenderWorld_envprobes.cpp | 4 +- 4 files changed, 63 insertions(+), 10 deletions(-) diff --git a/base/renderprogs/ambient_lighting_IBL.ps.hlsl b/base/renderprogs/ambient_lighting_IBL.ps.hlsl index bf177439..e390265f 100644 --- a/base/renderprogs/ambient_lighting_IBL.ps.hlsl +++ b/base/renderprogs/ambient_lighting_IBL.ps.hlsl @@ -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; diff --git a/neo/idlib/math/Vector.cpp b/neo/idlib/math/Vector.cpp index 043f2a20..592aab8c 100644 --- a/neo/idlib/math/Vector.cpp +++ b/neo/idlib/math/Vector.cpp @@ -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 ) { diff --git a/neo/renderer/Image_intrinsic.cpp b/neo/renderer/Image_intrinsic.cpp index 8de03c4d..4834bd40 100644 --- a/neo/renderer/Image_intrinsic.cpp +++ b/neo/renderer/Image_intrinsic.cpp @@ -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 ); diff --git a/neo/renderer/RenderWorld_envprobes.cpp b/neo/renderer/RenderWorld_envprobes.cpp index 796893da..e3d273e1 100644 --- a/neo/renderer/RenderWorld_envprobes.cpp +++ b/neo/renderer/RenderWorld_envprobes.cpp @@ -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