uniform sampler2D shadow2DTex; uniform sampler2DShadow shadowMap; /* Part of this PCSS is from http://developer.download.nvidia.com/whitepapers/2008/PCSS_Integration.pdf */ #if SMALL_SHADOW #define BLOCKER_SEARCH_NUM_SAMPLES 16 #define PCF_NUM_SAMPLES 16 #else #define BLOCKER_SEARCH_NUM_SAMPLES 64 #define PCF_NUM_SAMPLES 64 #endif #define LIGHT_SIZE_UV (0.1) vec2 poissonDisk[64]; float FindBlocker(out float numBlockers, vec3 coord) { float searchWidth = 0.025; float blockerSum = 0; numBlockers = 0; for( int i = 0; i < BLOCKER_SEARCH_NUM_SAMPLES; i++ ) { #ifdef GL_ES float shadowMapDepth = texture2D(shadow2DTex, coord.xy + poissonDisk[i] * searchWidth).r; #else float shadowMapDepth = texture(shadow2DTex, coord.xy + poissonDisk[i] * searchWidth).r; #endif if ( shadowMapDepth < coord.z ) { blockerSum += coord.z - shadowMapDepth; numBlockers++; } } return blockerSum / numBlockers; } float PCF_Filter(vec4 coord, float filterRadiusUV) { float sum = 0.0f; for ( int i = 0; i < PCF_NUM_SAMPLES; i++ ) { vec4 offset = vec4(poissonDisk[i] * filterRadiusUV, 0.0, 0.0); sum += shadow2DProj(shadowMap, coord + offset).r; } return sum / PCF_NUM_SAMPLES; } float PCSS (vec4 coord) { #if SMALL_SHADOW poissonDisk[0] = vec2( -0.94201624, -0.39906216 ); poissonDisk[1] = vec2( 0.94558609, -0.76890725 ); poissonDisk[2] = vec2( -0.094184101, -0.92938870 ); poissonDisk[3] = vec2( 0.34495938, 0.29387760 ); poissonDisk[4] = vec2( -0.91588581, 0.45771432 ); poissonDisk[5] = vec2( -0.81544232, -0.87912464 ); poissonDisk[6] = vec2( -0.38277543, 0.27676845 ); poissonDisk[7] = vec2( 0.97484398, 0.75648379 ); poissonDisk[8] = vec2( 0.44323325, -0.97511554 ); poissonDisk[9] = vec2( 0.53742981, -0.47373420 ); poissonDisk[10] = vec2( -0.26496911, -0.41893023 ); poissonDisk[11] = vec2( 0.79197514, 0.19090188 ); poissonDisk[12] = vec2( -0.24188840, 0.99706507 ); poissonDisk[13] = vec2( -0.81409955, 0.91437590 ); poissonDisk[14] = vec2( 0.19984126, 0.78641367 ); poissonDisk[15] = vec2( 0.14383161, -0.14100790 ); #else poissonDisk[0] = vec2(-0.613392, 0.617481); poissonDisk[1] = vec2(0.170019, -0.040254); poissonDisk[2] = vec2(-0.299417, 0.791925); poissonDisk[3] = vec2(0.645680, 0.493210); poissonDisk[4] = vec2(-0.651784, 0.717887); poissonDisk[5] = vec2(0.421003, 0.027070); poissonDisk[6] = vec2(-0.817194, -0.271096); poissonDisk[7] = vec2(-0.705374, -0.668203); poissonDisk[8] = vec2(0.977050, -0.108615); poissonDisk[9] = vec2(0.063326, 0.142369); poissonDisk[10] = vec2(0.203528, 0.214331); poissonDisk[11] = vec2(-0.667531, 0.326090); poissonDisk[12] = vec2(-0.098422, -0.295755); poissonDisk[13] = vec2(-0.885922, 0.215369); poissonDisk[14] = vec2(0.566637, 0.605213); poissonDisk[15] = vec2(0.039766, -0.396100); poissonDisk[16] = vec2(0.751946, 0.453352); poissonDisk[17] = vec2(0.078707, -0.715323); poissonDisk[18] = vec2(-0.075838, -0.529344); poissonDisk[19] = vec2(0.724479, -0.580798); poissonDisk[20] = vec2(0.222999, -0.215125); poissonDisk[21] = vec2(-0.467574, -0.405438); poissonDisk[22] = vec2(-0.248268, -0.814753); poissonDisk[23] = vec2(0.354411, -0.887570); poissonDisk[24] = vec2(0.175817, 0.382366); poissonDisk[25] = vec2(0.487472, -0.063082); poissonDisk[26] = vec2(-0.084078, 0.898312); poissonDisk[27] = vec2(0.488876, -0.783441); poissonDisk[28] = vec2(0.470016, 0.217933); poissonDisk[29] = vec2(-0.696890, -0.549791); poissonDisk[30] = vec2(-0.149693, 0.605762); poissonDisk[31] = vec2(0.034211, 0.979980); poissonDisk[32] = vec2(0.503098, -0.308878); poissonDisk[33] = vec2(-0.016205, -0.872921); poissonDisk[34] = vec2(0.385784, -0.393902); poissonDisk[35] = vec2(-0.146886, -0.859249); poissonDisk[36] = vec2(0.643361, 0.164098); poissonDisk[37] = vec2(0.634388, -0.049471); poissonDisk[38] = vec2(-0.688894, 0.007843); poissonDisk[39] = vec2(0.464034, -0.188818); poissonDisk[40] = vec2(-0.440840, 0.137486); poissonDisk[41] = vec2(0.364483, 0.511704); poissonDisk[42] = vec2(0.034028, 0.325968); poissonDisk[43] = vec2(0.099094, -0.308023); poissonDisk[44] = vec2(0.693960, -0.366253); poissonDisk[45] = vec2(0.678884, -0.204688); poissonDisk[46] = vec2(0.001801, 0.780328); poissonDisk[47] = vec2(0.145177, -0.898984); poissonDisk[48] = vec2(0.062655, -0.611866); poissonDisk[49] = vec2(0.315226, -0.604297); poissonDisk[50] = vec2(-0.780145, 0.486251); poissonDisk[51] = vec2(-0.371868, 0.882138); poissonDisk[52] = vec2(0.200476, 0.494430); poissonDisk[53] = vec2(-0.494552, -0.711051); poissonDisk[54] = vec2(0.612476, 0.705252); poissonDisk[55] = vec2(-0.578845, -0.768792); poissonDisk[56] = vec2(-0.772454, -0.090976); poissonDisk[57] = vec2(0.504440, 0.372295); poissonDisk[58] = vec2(0.155736, 0.065157); poissonDisk[59] = vec2(0.391522, 0.849605); poissonDisk[60] = vec2(-0.620106, -0.328104); poissonDisk[61] = vec2(0.789239, -0.419965); poissonDisk[62] = vec2(-0.545396, 0.538133); poissonDisk[63] = vec2(-0.178564, -0.596057); #endif float zReceiver = coord.z; float numBlockers = 0; float avgBlockerDepth = FindBlocker(numBlockers, coord.xyz); if(numBlockers < 1) return 1.0f; float filterRadiusUV = avgBlockerDepth * 0.25; return PCF_Filter(coord, filterRadiusUV); }