PBR precomputations
This commit is contained in:
parent
ba7595d781
commit
290555ad53
2 changed files with 74 additions and 36 deletions
|
@ -13,6 +13,12 @@ struct T_PBRMaterial
|
||||||
float specularTint; // Albedo color% in specular tint (non-metals)
|
float specularTint; // Albedo color% in specular tint (non-metals)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct T_PBRPrecomputed
|
||||||
|
{
|
||||||
|
float nDotV , ax , ay , fv , vgs;
|
||||||
|
vec3 tangent , bitangent , cSpecular;
|
||||||
|
};
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
float PBR_SchlickFresnel(
|
float PBR_SchlickFresnel(
|
||||||
|
@ -46,66 +52,93 @@ float PBR_SmithGGXAniso(
|
||||||
return 1 / ( nDotV + sqrt( x * x + y * y + nDotV * nDotV ) );
|
return 1 / ( nDotV + sqrt( x * x + y * y + nDotV * nDotV ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T_PBRPrecomputed PBR_Precompute(
|
||||||
|
in T_PBRMaterial material ,
|
||||||
|
in vec3 camDir ,
|
||||||
|
in vec3 normal )
|
||||||
|
{
|
||||||
|
T_PBRPrecomputed rv;
|
||||||
|
|
||||||
|
rv.nDotV = dot( normal , camDir );
|
||||||
|
rv.fv = PBR_SchlickFresnel( rv.nDotV );
|
||||||
|
|
||||||
|
float tDir = step( .99 , abs( normal.z ) ) ,
|
||||||
|
aspect = sqrt( 1 - material.anisotropy * .9 ) ,
|
||||||
|
rsqr = material.roughness * material.roughness;
|
||||||
|
|
||||||
|
vec3 tUp = mix( vec3( 0 , 0 , 1 ) , vec3( 1 , 0 , 0 ) , tDir ) ,
|
||||||
|
tint = M_NormalizeColor( material.cAlbedo );
|
||||||
|
rv.tangent = normalize( cross( tUp , normal ) );
|
||||||
|
rv.bitangent = normalize( cross( normal , rv.tangent ) );
|
||||||
|
|
||||||
|
rv.cSpecular = mix(
|
||||||
|
material.specular * .08 * mix(
|
||||||
|
vec3( 1 ) , tint , material.specularTint ) ,
|
||||||
|
material.cAlbedo , material.metallic );
|
||||||
|
|
||||||
|
rv.ax = max( .001, rsqr / aspect );
|
||||||
|
rv.ay = max( .001, rsqr * aspect );
|
||||||
|
rv.vgs = PBR_SmithGGXAniso( rv.nDotV ,
|
||||||
|
dot( camDir , rv.tangent ) , dot( camDir , rv.bitangent ) ,
|
||||||
|
rv.ax , rv.ay );
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
vec3 PBR_Shade(
|
vec3 PBR_Shade(
|
||||||
in T_PBRMaterial material ,
|
in T_PBRMaterial material ,
|
||||||
|
in T_PBRPrecomputed pre ,
|
||||||
in vec3 camDir ,
|
in vec3 camDir ,
|
||||||
in vec3 normal ,
|
in vec3 normal ,
|
||||||
in vec3 lightDir )
|
in vec3 lightDir )
|
||||||
{
|
{
|
||||||
float nDotL = dot( normal , lightDir ) ,
|
float nDotL = dot( normal , lightDir );
|
||||||
nDotV = dot( normal , camDir );
|
if ( nDotL < 0 || pre.nDotV < 0 ) {
|
||||||
if ( nDotL < 0 || nDotV < 0 ) {
|
|
||||||
return vec3( 0 );
|
return vec3( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 tangent = cross( vec3( 0 , 1 , 0 ) , normal );
|
vec3 halfVec = normalize( lightDir + camDir ) ;
|
||||||
if ( length( tangent ) == 0 ) {
|
|
||||||
tangent = cross( vec3( 1 , 0 , 0 ) , normal );
|
|
||||||
}
|
|
||||||
tangent = normalize( tangent );
|
|
||||||
vec3 bitangent = normalize( cross( normal , tangent ) );
|
|
||||||
|
|
||||||
vec3 halfVec = normalize( lightDir + camDir ) ,
|
|
||||||
tint = M_NormalizeColor( material.cAlbedo ) ,
|
|
||||||
cSpecular = mix( material.specular * .08 * mix(
|
|
||||||
vec3( 1 ) , tint , material.specularTint ) ,
|
|
||||||
material.cAlbedo , material.metallic );
|
|
||||||
//vec3 Csheen = mix(vec3(1), Ctint, sheenTint);
|
|
||||||
|
|
||||||
float nDotH = dot( normal , halfVec ) ,
|
float nDotH = dot( normal , halfVec ) ,
|
||||||
lDotH = dot( lightDir , halfVec ) ,
|
lDotH = dot( lightDir , halfVec ) ,
|
||||||
|
|
||||||
// Diffuse fresnel - go from 1 at normal incidence to .5 at grazing
|
// Diffuse fresnel - go from 1 at normal incidence to .5 at grazing
|
||||||
// and mix in diffuse retro-reflection based on roughness
|
// and mix in diffuse retro-reflection based on roughness
|
||||||
FL = PBR_SchlickFresnel( nDotL ) ,
|
FL = PBR_SchlickFresnel( nDotL ) ,
|
||||||
FV = PBR_SchlickFresnel( nDotV ) ,
|
|
||||||
Fd90 = 0.5 + 2 * lDotH * lDotH * material.roughness ,
|
Fd90 = 0.5 + 2 * lDotH * lDotH * material.roughness ,
|
||||||
Fd = mix( 1 , Fd90 , FL ) * mix( 1 , Fd90 , FV ) ,
|
Fd = mix( 1 , Fd90 , FL ) * mix( 1 , Fd90 , pre.fv ) ,
|
||||||
|
|
||||||
// Based on Hanrahan-Krueger brdf approximation of isotropic bssrdf
|
// Based on Hanrahan-Krueger brdf approximation of isotropic bssrdf
|
||||||
// 1.25 scale is used to (roughly) preserve albedo
|
// 1.25 scale is used to (roughly) preserve albedo
|
||||||
// Fss90 used to "flatten" retroreflection based on roughness
|
// Fss90 used to "flatten" retroreflection based on roughness
|
||||||
Fss90 = lDotH * lDotH * material.roughness ,
|
Fss90 = lDotH * lDotH * material.roughness ,
|
||||||
Fss = mix( 1 , Fss90 , FL ) * mix( 1 , Fss90 , FV ) ,
|
Fss = mix( 1 , Fss90 , FL ) * mix( 1 , Fss90 , pre.fv ) ,
|
||||||
ss = 1.25 * ( Fss * ( 1 / ( nDotL + nDotV ) - .5 ) + .5 ) ,
|
ss = 1.25 * ( Fss * ( 1 / ( nDotL + pre.nDotV ) - .5 ) + .5 ) ,
|
||||||
|
|
||||||
// Specular
|
// Specular
|
||||||
aspect = sqrt( 1 - material.anisotropy * .9 ) ,
|
Ds = PBR_GTR2Aniso( nDotH , dot( halfVec , pre.tangent ) ,
|
||||||
rsqr = material.roughness * material.roughness ,
|
dot( halfVec , pre.bitangent ) ,
|
||||||
ax = max( .001, rsqr / aspect ) ,
|
pre.ax , pre.ay ) ,
|
||||||
ay = max( .001, rsqr * aspect ) ,
|
|
||||||
Ds = PBR_GTR2Aniso( nDotH , dot( halfVec , tangent ) ,
|
|
||||||
dot( halfVec , bitangent ) , ax , ay ) ,
|
|
||||||
FH = PBR_SchlickFresnel( lDotH ) ,
|
FH = PBR_SchlickFresnel( lDotH ) ,
|
||||||
Gs = PBR_SmithGGXAniso( nDotL , dot( lightDir , tangent ) ,
|
Gs = PBR_SmithGGXAniso( nDotL , dot( lightDir , pre.tangent ) ,
|
||||||
dot( lightDir , bitangent ) , ax , ay )
|
dot( lightDir , pre.bitangent ) ,
|
||||||
* PBR_SmithGGXAniso( nDotV , dot( camDir , tangent ) ,
|
pre.ax , pre.ay ) * pre.vgs;
|
||||||
dot( camDir , bitangent ) , ax , ay );
|
|
||||||
|
|
||||||
vec3 Fs = mix( cSpecular , vec3(1) , FH );
|
vec3 Fs = mix( pre.cSpecular , vec3(1) , FH );
|
||||||
return nDotL * ( ( ( 1 / PI )
|
return nDotL * ( ( ( 1 / PI )
|
||||||
* mix( Fd , ss , material.subsurface )
|
* mix( Fd , ss , material.subsurface )
|
||||||
* material.cAlbedo /* + Fsheen */)
|
* material.cAlbedo /* + Fsheen */)
|
||||||
* pow( 1 - material.metallic , 3 )
|
* pow( 1 - material.metallic , 3 )
|
||||||
+ clamp( Gs , 0 , 1 ) * Fs * Ds );
|
+ clamp( Gs , 0 , 1 ) * Fs * Ds );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vec3 PBR_Shade(
|
||||||
|
in T_PBRMaterial material ,
|
||||||
|
in vec3 camDir ,
|
||||||
|
in vec3 normal ,
|
||||||
|
in vec3 lightDir )
|
||||||
|
{
|
||||||
|
return PBR_Shade(
|
||||||
|
material ,
|
||||||
|
PBR_Precompute( material , camDir , normal ) ,
|
||||||
|
camDir , normal , lightDir );
|
||||||
|
}
|
||||||
|
|
|
@ -65,6 +65,7 @@ vec2 RM_Map( vec3 pos )
|
||||||
|
|
||||||
vec3 pointlight(
|
vec3 pointlight(
|
||||||
in T_PBRMaterial material ,
|
in T_PBRMaterial material ,
|
||||||
|
in T_PBRPrecomputed pre ,
|
||||||
in vec3 hitPos ,
|
in vec3 hitPos ,
|
||||||
in vec3 rayDir ,
|
in vec3 rayDir ,
|
||||||
in vec3 normal ,
|
in vec3 normal ,
|
||||||
|
@ -79,7 +80,7 @@ vec3 pointlight(
|
||||||
}
|
}
|
||||||
|
|
||||||
return lightColor * lPwr * PBR_Shade(
|
return lightColor * lPwr * PBR_Shade(
|
||||||
material , -rayDir , normal , lightRay );
|
material , pre , -rayDir , normal , lightRay );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -123,11 +124,15 @@ void main( )
|
||||||
-rayDir , normal , sunlightDir );
|
-rayDir , normal , sunlightDir );
|
||||||
} else {
|
} else {
|
||||||
T_PBRMaterial mat = PBRMaterials[ mtidx ];
|
T_PBRMaterial mat = PBRMaterials[ mtidx ];
|
||||||
bc = sunlightColor * PBR_Shade( mat ,
|
T_PBRPrecomputed pre = PBR_Precompute(
|
||||||
|
mat , -rayDir , normal );
|
||||||
|
bc = sunlightColor * PBR_Shade( mat , pre ,
|
||||||
-rayDir , normal , sunlightDir );
|
-rayDir , normal , sunlightDir );
|
||||||
bc += pointlight( mat , hitPos , rayDir , normal ,
|
bc += pointlight( mat , pre ,
|
||||||
|
hitPos , rayDir , normal ,
|
||||||
pl1Pos , pl1Color , pl1Power );
|
pl1Pos , pl1Color , pl1Power );
|
||||||
bc += pointlight( mat , hitPos , rayDir , normal ,
|
bc += pointlight( mat , pre ,
|
||||||
|
hitPos , rayDir , normal ,
|
||||||
pl2Pos , pl2Color , pl2Power );
|
pl2Pos , pl2Color , pl2Power );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue