lib/mittsu/opengl/shader/chunks/shadowmap_fragment.glsl
#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 );
<% parameters[:max_shadows].times do |i| %>
vec3 shadowCoord = vShadowCoord[ <%= i %> ].xyz / vShadowCoord[ <%= i %> ].w;
// if ( something && something ) breaks ATI OpenGL shader compiler
// if ( all( something, something ) ) using this instead
bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );
bool inFrustum = all( inFrustumVec );
// don't shadow pixels outside of light frustum
// use just first frustum (for cascades)
// don't shadow pixels behind far plane of light frustum
#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 )
// Percentage-close filtering
// (9 pixel kernel)
// http://fabiensanglard.net/shadowmappingPCF/
float shadow = 0.0;
/*
// nested loops breaks shader compiler / validator on some ATI cards when using OpenGL
// must enroll loop manually
for ( float y = -1.25; y <= 1.25; y += 1.25 )
for ( float x = -1.25; x <= 1.25; x += 1.25 ) {
vec4 rgbaDepth = texture( shadowMap[ <%= i %> ], vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy );
// doesn't seem to produce any noticeable visual difference compared to simple texture lookup
//vec4 rgbaDepth = textureProj( shadowMap[ <%= i %> ], vec4( vShadowCoord[ <%= i %> ].w * ( vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy ), 0.05, vShadowCoord[ <%= i %> ].w ) );
float fDepth = unpackDepth( rgbaDepth );
if ( fDepth < shadowCoord.z )
shadow += 1.0;
}
shadow /= 9.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( texture( shadowMap[ <%= i %> ], shadowCoord.xy + vec2( dx0, dy0 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
fDepth = unpackDepth( texture( shadowMap[ <%= i %> ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
fDepth = unpackDepth( texture( shadowMap[ <%= i %> ], shadowCoord.xy + vec2( dx1, dy0 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
fDepth = unpackDepth( texture( shadowMap[ <%= i %> ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
fDepth = unpackDepth( texture( shadowMap[ <%= i %> ], shadowCoord.xy ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
fDepth = unpackDepth( texture( shadowMap[ <%= i %> ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
fDepth = unpackDepth( texture( shadowMap[ <%= i %> ], shadowCoord.xy + vec2( dx0, dy1 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
fDepth = unpackDepth( texture( shadowMap[ <%= i %> ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
fDepth = unpackDepth( texture( 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 )
// Percentage-close filtering
// (9 pixel kernel)
// http://fabiensanglard.net/shadowmappingPCF/
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( texture( shadowMap[ <%= i %> ], shadowCoord.xy + vec2( dx0, dy0 ) ) );
depthKernel[0][1] = unpackDepth( texture( shadowMap[ <%= i %> ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );
depthKernel[0][2] = unpackDepth( texture( shadowMap[ <%= i %> ], shadowCoord.xy + vec2( dx0, dy1 ) ) );
depthKernel[1][0] = unpackDepth( texture( shadowMap[ <%= i %> ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );
depthKernel[1][1] = unpackDepth( texture( shadowMap[ <%= i %> ], shadowCoord.xy ) );
depthKernel[1][2] = unpackDepth( texture( shadowMap[ <%= i %> ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );
depthKernel[2][0] = unpackDepth( texture( shadowMap[ <%= i %> ], shadowCoord.xy + vec2( dx1, dy0 ) ) );
depthKernel[2][1] = unpackDepth( texture( shadowMap[ <%= i %> ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );
depthKernel[2][2] = unpackDepth( texture( 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 = texture( shadowMap[ <%= i %> ], shadowCoord.xy );
float fDepth = unpackDepth( rgbaDepth );
if ( fDepth < shadowCoord.z )
// spot with multiple shadows is darker
shadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ <%= i %> ] );
// spot with multiple shadows has the same color as single shadow spot
// shadowColor = min( shadowColor, vec3( shadowDarkness[ <%= i %> ] ) );
#endif
}
#ifdef SHADOWMAP_DEBUG
#ifdef SHADOWMAP_CASCADE
if ( inFrustum && inFrustumCount == 1 ) outgoingLight *= frustumColors[ <%= i %> ];
#else
if ( inFrustum ) outgoingLight *= frustumColors[ <%= i %> ];
#endif
#endif
<% end %>
// NOTE: I am unsure if this is correct in linear space. -bhouston, Dec 29, 2014
shadowColor = inputToLinear( shadowColor );
outgoingLight = outgoingLight * shadowColor;
#endif