Last active
May 23, 2019 08:20
-
-
Save yiwenl/acb9800ce465aa77113c4c55c918a6ef to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#extension GL_EXT_shader_texture_lod : enable | |
uniform samplerCube uRadianceMap; | |
uniform samplerCube uIrradianceMap; | |
#define saturate(x) clamp(x, 0.0, 1.0) | |
#define PI 3.1415926535897932384626433832795 | |
const float A = 0.15; | |
const float B = 0.50; | |
const float C = 0.10; | |
const float D = 0.20; | |
const float E = 0.02; | |
const float F = 0.30; | |
vec3 Uncharted2Tonemap( vec3 x ) | |
{ | |
return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F; | |
} | |
// https://www.unrealengine.com/blog/physically-based-shading-on-mobile | |
vec3 EnvBRDFApprox( vec3 SpecularColor, float Roughness, float NoV ) | |
{ | |
const vec4 c0 = vec4( -1, -0.0275, -0.572, 0.022 ); | |
const vec4 c1 = vec4( 1, 0.0425, 1.04, -0.04 ); | |
vec4 r = Roughness * c0 + c1; | |
float a004 = min( r.x * r.x, exp2( -9.28 * NoV ) ) * r.x + r.y; | |
vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw; | |
return SpecularColor * AB.x + AB.y; | |
} | |
// http://the-witness.net/news/2012/02/seamless-cube-map-filtering/ | |
vec3 fix_cube_lookup( vec3 v, float cube_size, float lod ) { | |
float M = max(max(abs(v.x), abs(v.y)), abs(v.z)); | |
float scale = 1.0 - exp2(lod) / cube_size; | |
if (abs(v.x) != M) v.x *= scale; | |
if (abs(v.y) != M) v.y *= scale; | |
if (abs(v.z) != M) v.z *= scale; | |
return v; | |
} | |
vec3 correctGamma(vec3 color, float g) { | |
return pow(color, vec3(1.0/g)); | |
} | |
vec3 getPbr(vec3 N, vec3 V, vec3 baseColor, float roughness, float metallic, float specular) { | |
vec3 diffuseColor = baseColor - baseColor * metallic; | |
vec3 specularColor = mix( vec3( 0.08 * specular ), baseColor, specular ); | |
vec3 color; | |
float roughness4 = pow(roughness, 4.0); | |
// sample the pre-filtered cubemap at the corresponding mipmap level | |
float numMips = 6.0; | |
float mip = numMips - 1.0 + log2(roughness); | |
vec3 lookup = -reflect( V, N ); | |
lookup = fix_cube_lookup( lookup, 512.0, mip ); | |
vec3 radiance = pow( textureCubeLodEXT( uRadianceMap, lookup, mip ).rgb, vec3( 2.2 ) ); | |
vec3 irradiance = pow( textureCube( uIrradianceMap, N ).rgb, vec3( 1 ) ); | |
// get the approximate reflectance | |
float NoV = saturate( dot( N, V ) ); | |
vec3 reflectance = EnvBRDFApprox( specularColor, roughness4, NoV ); | |
// combine the specular IBL and the BRDF | |
vec3 diffuse = diffuseColor * irradiance; | |
vec3 _specular = radiance * reflectance; | |
color = diffuse + _specular; | |
vec3 ao = texture2D(uAoMap, vTextureCoord).rgb; | |
color *= ao; | |
return color; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define saturate(x) clamp(x, 0.0, 1.0) | |
#define PI 3.14159265359 | |
// OrenNayar diffuse | |
vec3 getDiffuse( vec3 diffuseColor, float roughness4, float NoV, float NoL, float VoH ) | |
{ | |
float VoL = 2.0 * VoH - 1.0; | |
float c1 = 1.0 - 0.5 * roughness4 / (roughness4 + 0.33); | |
float cosri = VoL - NoV * NoL; | |
float c2 = 0.45 * roughness4 / (roughness4 + 0.09) * cosri * ( cosri >= 0.0 ? min( 1.0, NoL / NoV ) : NoL ); | |
return diffuseColor / PI * ( NoL * c1 + c2 ); | |
} | |
// GGX Normal distribution | |
float getNormalDistribution( float roughness4, float NoH ) | |
{ | |
float d = ( NoH * roughness4 - NoH ) * NoH + 1.0; | |
return roughness4 / ( d*d ); | |
} | |
// Smith GGX geometric shadowing from "Physically-Based Shading at Disney" | |
float getGeometricShadowing( float roughness4, float NoV, float NoL, float VoH, vec3 L, vec3 V ) | |
{ | |
float gSmithV = NoV + sqrt( NoV * (NoV - NoV * roughness4) + roughness4 ); | |
float gSmithL = NoL + sqrt( NoL * (NoL - NoL * roughness4) + roughness4 ); | |
return 1.0 / ( gSmithV * gSmithL ); | |
} | |
// Fresnel term | |
vec3 getFresnel( vec3 specularColor, float VoH ) | |
{ | |
vec3 specularColorSqrt = sqrt( clamp( vec3(0.0, 0.0, 0.0), vec3(0.99, 0.99, 0.99), specularColor ) ); | |
vec3 n = ( 1.0 + specularColorSqrt ) / ( 1.0 - specularColorSqrt ); | |
vec3 g = sqrt( n * n + VoH * VoH - 1.0 ); | |
return 0.5 * pow( (g - VoH) / (g + VoH), vec3(2.0) ) * ( 1.0 + pow( ((g+VoH)*VoH - 1.0) / ((g-VoH)*VoH + 1.0), vec3(2.0) ) ); | |
} | |
const float A = 0.15; | |
const float B = 0.50; | |
const float C = 0.10; | |
const float D = 0.20; | |
const float E = 0.02; | |
const float F = 0.30; | |
vec3 Uncharted2Tonemap( vec3 x ) | |
{ | |
return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F; | |
} | |
// From "I'm doing it wrong" | |
// http://imdoingitwrong.wordpress.com/2011/01/31/light-attenuation/ | |
float getAttenuation( vec3 lightPosition, vec3 vertexPosition, float lightRadius ) | |
{ | |
float r = lightRadius; | |
vec3 L = lightPosition - vertexPosition; | |
float dist = length(L); | |
float d = max( dist - r, 0.0 ); | |
L /= dist; | |
float denom = d / r + 1.0; | |
float attenuation = 1.0 / (denom*denom); | |
float cutoff = 0.0052; | |
attenuation = (attenuation - cutoff) / (1.0 - cutoff); | |
attenuation = max(attenuation, 0.0); | |
return attenuation; | |
} | |
vec3 getPbrPointLight(vec3 normal, vec3 position, vec3 lightPosition, vec3 lightColor, float lightRadius) { | |
// vLightPosition = ( uViewMatrix * vec4( uLightPosition, 1.0 ) ).xyz; | |
vec3 N = normalize( normal ); | |
vec3 L = normalize( lightPosition - position ); | |
vec3 V = normalize( -position ); | |
vec3 H = normalize(V + L); | |
float NoL = saturate( dot( N, L ) ); | |
float NoV = saturate( dot( N, V ) ); | |
float VoH = saturate( dot( V, H ) ); | |
float NoH = saturate( dot( N, H ) ); | |
// deduce the diffuse and specular color from the baseColor and how metallic the material is | |
vec3 diffuseColor = uBaseColor - uBaseColor * uMetallic; | |
vec3 specularColor = mix( vec3( 0.8 * uSpecular ), uBaseColor, uMetallic ); | |
// compute the brdf terms | |
float distribution = getNormalDistribution( uRoughness, NoH ); | |
vec3 fresnel = getFresnel( specularColor, VoH ); | |
float geom = getGeometricShadowing( uRoughness, NoV, NoL, VoH, L, V ); | |
// get the specular and diffuse and combine them | |
vec3 diffuse = getDiffuse( diffuseColor, uRoughness, NoV, NoL, VoH ); | |
vec3 specular = NoL * ( distribution * fresnel * geom ); | |
vec3 color = lightColor * ( diffuse + specular ); | |
// get the light attenuation from its radius | |
float attenuation = getAttenuation( lightPosition, position, lightRadius ); | |
color *= attenuation; | |
return color; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment