Created
January 7, 2014 17:35
-
-
Save bhouston/8303128 to your computer and use it in GitHub Desktop.
Partially refractored normalmap.fragment.glsl
This file contains hidden or 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
uniform vec3 ambient; | |
uniform vec3 diffuse; | |
uniform vec3 specular; | |
uniform float shininess; | |
uniform float opacity; | |
uniform bool enableDiffuse; | |
uniform bool enableSpecular; | |
uniform bool enableAO; | |
uniform bool enableReflection; | |
uniform sampler2D tDiffuse; | |
uniform sampler2D tNormal; | |
uniform sampler2D tSpecular; | |
uniform sampler2D tAO; | |
uniform samplerCube tCube; | |
uniform vec2 uNormalScale; | |
uniform bool useRefract; | |
uniform float refractionRatio; | |
uniform float reflectivity; | |
varying vec3 vTangent; | |
varying vec3 vBinormal; | |
varying vec3 vNormal; | |
varying vec2 vUv; | |
uniform vec3 ambientLightColor; | |
#if MAX_DIR_LIGHTS > 0 | |
uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ]; | |
uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ]; | |
#endif | |
#if MAX_HEMI_LIGHTS > 0 | |
uniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ]; | |
uniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ]; | |
uniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ]; | |
#endif | |
#if MAX_POINT_LIGHTS > 0 | |
uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ]; | |
uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ]; | |
uniform float pointLightDistance[ MAX_POINT_LIGHTS ]; | |
#endif | |
#if MAX_SPOT_LIGHTS > 0 | |
uniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ]; | |
uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ]; | |
uniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ]; | |
uniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ]; | |
uniform float spotLightExponent[ MAX_SPOT_LIGHTS ]; | |
uniform float spotLightDistance[ MAX_SPOT_LIGHTS ]; | |
#endif | |
varying vec3 vWorldPosition; | |
varying vec3 vViewPosition; | |
#ifdef USE_SHADOWMAP | |
uniform sampler2D shadowMap[ MAX_SHADOWS ]; | |
uniform vec2 shadowMapSize[ MAX_SHADOWS ]; | |
uniform float shadowDarkness[ MAX_SHADOWS ]; | |
uniform float shadowBias[ MAX_SHADOWS ]; | |
varying vec4 vShadowCoord[ MAX_SHADOWS ]; | |
float unpackDepth( const in vec4 rgba_depth ) { | |
const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 ); | |
float depth = dot( rgba_depth, bit_shift ); | |
return depth; | |
} | |
#endif | |
#ifdef USE_FOG | |
uniform vec3 fogColor; | |
#ifdef FOG_EXP2 | |
uniform float fogDensity; | |
#else | |
uniform float fogNear; | |
uniform float fogFar; | |
#endif | |
#endif | |
void main() { | |
gl_FragColor = vec4( vec3( 1.0 ), opacity ); | |
if( enableDiffuse ) { | |
gl_FragColor = gl_FragColor * inputGamma( texture2D( tDiffuse, vUv ) ); | |
} | |
if( enableAO ) { | |
gl_FragColor.xyz = gl_FragColor.xyz * inputGamma( texture2D( tAO, vUv ) ).xyz; | |
} | |
// specular shininess factor | |
vec3 specularTex = vec3( 1.0 ); | |
if( enableSpecular ) | |
specularTex = texture2D( tSpecular, vUv ).xyz; | |
// calculate normal | |
vec3 normalTex = rgbaToNormal( texture2D( tNormal, vUv ), uNormalScale ); | |
mat3 tsb = mat3( normalize( vTangent ), normalize( vBinormal ), normalize( vNormal ) ); | |
vec3 normal = tsb * normalTex; | |
#ifdef FLIP_SIDED | |
normal = -normal; | |
#endif | |
vec3 normal = normalize( normal ); | |
vec3 viewNormal = normalize( vViewPosition ); | |
vec3 totalDiffuse = vec3( 0.0 ); | |
vec3 totalSpecular = vec3( 0.0 ); | |
// no need for a MAX_POINT_LIGHTS define, this for loop just is optmized by the compiler away | |
for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) { | |
vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 ); | |
vec3 pointVector = lPosition.xyz + vViewPosition.xyz; | |
float pointDistance = lightDistanceFadeOutAlpha( pointVector, pointLightDistance[ i ] ); | |
vec3 pointNormal = normalize( pointVector ); | |
totalDiffuse += pointDistance * pointLightColor[i] * diffuse * lambertDiffuse( normal, pointNormal ); | |
totalSpecular += pointDistance * pointLightColor[i] * schlickSpecular( specular, normal, viewNormal, pointNormal, specularTex.r, shininess ); | |
} | |
// no need for a MAX_SPOT_LIGHTS define, this for loop just is optmized by the compiler away | |
for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) { | |
vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 ); | |
vec3 spotVector = lPosition.xyz + vViewPosition.xyz; | |
float spotDistance = lightDistanceFadeOutAlpha( spotVector, spotLightDistance[ i ] ); | |
vec3 spotNormal = normalize( spotVector ); | |
float spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) ); | |
if ( spotEffect > spotLightAngleCos[ i ] ) { | |
spotEffect = max( pow( spotEffect, spotLightExponent[ i ] ), 0.0 ); | |
totalDiffuse += spotDistance * spotLightColor[i] * diffuse * lambertDiffuse( normal, spotNormal ) * spotEffect; | |
totalSpecular += spotDistance * spotLightColor[i] * schlickSpecular( specular, normal, viewNormal, spotNormal, specularTex.r, shininess ) * spotEffect; | |
} | |
} | |
// no need for a MAX_DIR_LIGHTS define, this for loop just is optmized by the compiler away | |
for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) { | |
vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 ); | |
vec3 dirNormal = normalize( lDirection.xyz ); | |
totalDiffuse += directionalLightColor[ i ] * diffuse * lambertDiffuse( normal, dirNormal ); | |
totalSpecular += directionalLightColor[i] * schlickSpecular( specular, normal, viewNormal, dirNormal, specularTex.r, shininess ); | |
} | |
// no need for a MAX_HEMI_LIGHTS define, this for loop just is optmized by the compiler away | |
for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) { | |
vec4 lDirection = viewMatrix * vec4( hemisphereLightDirection[ i ], 0.0 ); | |
vec3 lVector = normalize( lDirection.xyz ); | |
float dotProduct = dot( normal, lVector ); | |
float hemiDiffuseWeight = 0.5 * dotProduct + 0.5; | |
vec3 hemiColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight ); | |
totalDiffuse += diffuse * hemiColor; | |
vec3 hemiHalfVectorSky = normalize( lVector + viewNormal ); | |
float hemiDotNormalHalfSky = halfDot( normal, hemiHalfVectorSky ); | |
float hemiSpecularWeightSky = specularCoeff( specularTex, hemiDotNormalHalfSky, shininess ); | |
vec3 lVectorGround = -lVector; | |
vec3 hemiHalfVectorGround = normalize( lVectorGround + viewNormal ); | |
float hemiDotNormalHalfGround = halfDot( normal, hemiHalfVectorGround ); | |
float hemiSpecularWeightGround = specularCoeff( specularTex, hemiDotNormalHalfGround, shininess ); | |
float dotProductGround = dot( normal, lVectorGround ); | |
float specularNormalization = ( shininess + 2.0001 ) / 8.0; | |
vec3 schlickSky = schlickCoeff( specular, lVector, hemiHalfVectorSky ); | |
vec3 schlickGround = schlickCoeff( specular, lVectorGround, hemiHalfVectorGround ); | |
totalSpecular += hemiColor * specularNormalization * ( schlickSky * hemiSpecularWeightSky * max( dotProduct, 0.0 ) + schlickGround * hemiSpecularWeightGround * max( dotProductGround, 0.0 ) ); | |
} | |
#ifdef METAL | |
gl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * ambient + totalSpecular ); | |
#else | |
gl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * ambient ) + totalSpecular; | |
#endif | |
if ( enableReflection ) { | |
vec3 vReflect; | |
vec3 cameraToVertex = normalize( vWorldPosition - cameraPosition ); | |
if ( useRefract ) { | |
vReflect = refract( cameraToVertex, normal, refractionRatio ); | |
} else { | |
vReflect = reflect( cameraToVertex, normal ); | |
} | |
vec4 cubeColor = inputGamma( textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) ) ); | |
gl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularTex.r * reflectivity ); | |
} | |
#ifdef USE_SHADOWMAP | |
#ifdef SHADOWMAP_DEBUG | |
vec3 frustumColors[3]; | |
frustumColors[0] = vec3( 1.0, 0.5, 0.0 ); | |
frustumColors[1] = vec3( 0.0, 1.0, 0.8 ); | |
frustumColors[2] = vec3( 0.0, 0.5, 1.0 ); | |
#endif | |
#ifdef SHADOWMAP_CASCADE | |
int inFrustumCount = 0; | |
#endif | |
float fDepth; | |
vec3 shadowColor = vec3( 1.0 ); | |
for( int i = 0; i < MAX_SHADOWS; i ++ ) { | |
vec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w; | |
bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 ); | |
bool inFrustum = all( inFrustumVec ); | |
#ifdef SHADOWMAP_CASCADE | |
inFrustumCount += int( inFrustum ); | |
bvec3 frustumTestVec = bvec3( inFrustum, inFrustumCount == 1, shadowCoord.z <= 1.0 ); | |
#else | |
bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 ); | |
#endif | |
bool frustumTest = all( frustumTestVec ); | |
if ( frustumTest ) { | |
shadowCoord.z += shadowBias[ i ]; | |
#if defined( SHADOWMAP_TYPE_PCF ) | |
float shadow = 0.0; | |
const float shadowDelta = 1.0 / 9.0; | |
float xPixelOffset = 1.0 / shadowMapSize[ i ].x; | |
float yPixelOffset = 1.0 / shadowMapSize[ i ].y; | |
float dx0 = -1.25 * xPixelOffset; | |
float dy0 = -1.25 * yPixelOffset; | |
float dx1 = 1.25 * xPixelOffset; | |
float dy1 = 1.25 * yPixelOffset; | |
fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) ); | |
if ( fDepth < shadowCoord.z ) shadow += shadowDelta; | |
fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) ); | |
if ( fDepth < shadowCoord.z ) shadow += shadowDelta; | |
fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) ); | |
if ( fDepth < shadowCoord.z ) shadow += shadowDelta; | |
fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) ); | |
if ( fDepth < shadowCoord.z ) shadow += shadowDelta; | |
fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) ); | |
if ( fDepth < shadowCoord.z ) shadow += shadowDelta; | |
fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) ); | |
if ( fDepth < shadowCoord.z ) shadow += shadowDelta; | |
fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) ); | |
if ( fDepth < shadowCoord.z ) shadow += shadowDelta; | |
fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) ); | |
if ( fDepth < shadowCoord.z ) shadow += shadowDelta; | |
fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) ); | |
if ( fDepth < shadowCoord.z ) shadow += shadowDelta; | |
shadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) ); | |
#elif defined( SHADOWMAP_TYPE_PCF_SOFT ) | |
float shadow = 0.0; | |
float xPixelOffset = 1.0 / shadowMapSize[ i ].x; | |
float yPixelOffset = 1.0 / shadowMapSize[ i ].y; | |
float dx0 = -1.0 * xPixelOffset; | |
float dy0 = -1.0 * yPixelOffset; | |
float dx1 = 1.0 * xPixelOffset; | |
float dy1 = 1.0 * yPixelOffset; | |
mat3 shadowKernel; | |
mat3 depthKernel; | |
depthKernel[0][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) ); | |
depthKernel[0][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) ); | |
depthKernel[0][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) ); | |
depthKernel[1][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) ); | |
depthKernel[1][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) ); | |
depthKernel[1][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) ); | |
depthKernel[2][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) ); | |
depthKernel[2][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) ); | |
depthKernel[2][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) ); | |
vec3 shadowZ = vec3( shadowCoord.z ); | |
shadowKernel[0] = vec3(lessThan(depthKernel[0], shadowZ )); | |
shadowKernel[0] *= vec3(0.25); | |
shadowKernel[1] = vec3(lessThan(depthKernel[1], shadowZ )); | |
shadowKernel[1] *= vec3(0.25); | |
shadowKernel[2] = vec3(lessThan(depthKernel[2], shadowZ )); | |
shadowKernel[2] *= vec3(0.25); | |
vec2 fractionalCoord = 1.0 - fract( shadowCoord.xy * shadowMapSize[i].xy ); | |
shadowKernel[0] = mix( shadowKernel[1], shadowKernel[0], fractionalCoord.x ); | |
shadowKernel[1] = mix( shadowKernel[2], shadowKernel[1], fractionalCoord.x ); | |
vec4 shadowValues; | |
shadowValues.x = mix( shadowKernel[0][1], shadowKernel[0][0], fractionalCoord.y ); | |
shadowValues.y = mix( shadowKernel[0][2], shadowKernel[0][1], fractionalCoord.y ); | |
shadowValues.z = mix( shadowKernel[1][1], shadowKernel[1][0], fractionalCoord.y ); | |
shadowValues.w = mix( shadowKernel[1][2], shadowKernel[1][1], fractionalCoord.y ); | |
shadow = dot( shadowValues, vec4( 1.0 ) ); | |
shadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) ); | |
#else | |
vec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy ); | |
float fDepth = unpackDepth( rgbaDepth ); | |
if ( fDepth < shadowCoord.z ) | |
shadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ i ] ); | |
#endif | |
} | |
#ifdef SHADOWMAP_DEBUG | |
#ifdef SHADOWMAP_CASCADE | |
if ( inFrustum && inFrustumCount == 1 ) gl_FragColor.xyz *= frustumColors[ i ]; | |
#else | |
if ( inFrustum ) gl_FragColor.xyz *= frustumColors[ i ]; | |
#endif | |
#endif | |
} | |
#ifdef GAMMA_OUTPUT | |
shadowColor *= shadowColor; | |
#endif | |
gl_FragColor.xyz = gl_FragColor.xyz * shadowColor; | |
#endif | |
#ifdef GAMMA_OUTPUT | |
gl_FragColor.xyz = sqrt( gl_FragColor.xyz ); | |
#endif | |
#ifdef USE_FOG | |
float depth = gl_FragCoord.z / gl_FragCoord.w; | |
#ifdef FOG_EXP2 | |
const float LOG2 = 1.442695; | |
float fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 ); | |
fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 ); | |
#else | |
float fogFactor = smoothstep( fogNear, fogFar, depth ); | |
#endif | |
gl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor ); | |
#endif | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment