/media/CORE/COREShaders/GEARCoreShadow.mod.glsl

http://gear.googlecode.com/ · GLSL · 245 lines · 139 code · 35 blank · 71 comment · 53 complexity · 2517faa456065ee956c80dfd28c1c19b MD5 · raw file

  1. /* This is a gear shader module for shadow mapping.
  2. * to use this module add the following line before usage of the here defined functions
  3. * into the shader:
  4. * import gearmod GEARCoreShadow.mod.glsl
  5. * after this you can simply call the gearShadowLookupOmnidirectionalLight(...) function with the parameters you want.
  6. * make sure that the shadow mapping is enabled in your gear application.
  7. * note: this version only works with a textures available in the shader.
  8. * for another version you should remove the access to this texture slots.
  9. * Here are the values of the GEARFlag [GEARCORETexN_SPEC]:
  10. * 6: TEX_2D_SHADOW_LIGHT1 - Texture contains a 2D shadowmap for light 1
  11. * 7: TEX_2D_SHADOW_LIGHT2 - Texture contains a 2D shadowmap for light 2
  12. * 8: TEX_2D_SHADOW_LIGHT3 - Texture contains a 2D shadowmap for light 3
  13. * 9: TEX_2D_SHADOW_LIGHT4 - Texture contains a 2D shadowmap for light 4
  14. * 11: TEX_CUBE_SHADOW_LIGHT1 - Texture contains a cube shadowmap for light 1
  15. * 12: TEX_CUBE_SHADOW_LIGHT2 - Texture contains a cube shadowmap for light 2
  16. * 13: TEX_CUBE_SHADOW_LIGHT3 - Texture contains a cube shadowmap for light 3
  17. * 14: TEX_CUBE_SHADOW_LIGHT4 - Texture contains a cube shadowmap for light 4
  18. *
  19. * Note that only Texture slot 5 to 8 are used for shadow maps.
  20. */
  21. // these integers hold the informations about the lightsources regardless to their type (spot, directional, ...), e.g. if they use shadowing or not.
  22. // If for example a spot light 4 uses shadow, we know that to the corresponding Shadowmap the right shadowmap is bound
  23. // the available texture combiners
  24. #define GEAR_SHADOW_OFF 0
  25. #define GEAR_SHADOW_MAPPING 1
  26. #define GEAR_CASCADED_SHADOW_MAPPING 2
  27. #define GEAR_SHADOW_VOLUME 3
  28. uniform int gear_light_id[8];
  29. /*
  30. * This function is only for internal usage.
  31. */
  32. float toTexDepth( vec3 d, float near, float far) {
  33. float dist = max(max(abs(d.x),abs(d.y)),abs(d.z));
  34. float fmn = far - near;
  35. dist = ((far+near)/(fmn)) + (1.0/dist)*((-2.0*far*near)/(fmn));
  36. return (dist+1.0)/2.0;
  37. }
  38. /*
  39. * This function does a shadowmap lookup in a given shadowmap and returs the date.
  40. * There have to be a few parameters provided:
  41. * @param i The light ID.
  42. * @param vertex The vertex in modelspace
  43. * @param nearClipPlane The near clip plane to use.
  44. * @param farClipPlane The far clip plane to use.
  45. * @param lightingFactor The factor to multiply the ambient light with.
  46. * @return True, if fragment is in shadow, false if not.
  47. */
  48. bool gearShadowLookupOmnidirectionalLight( in int i, in vec3 vertex, in float nearClipPlane, in float farClipPlane, inout float lightingFactor ) {
  49. // get the sampler to use for this light
  50. float shadowDepth = 0.0;
  51. vec3 D = gl_LightSource[i].position.xyz - vertex;
  52. float depth = toTexDepth(D, nearClipPlane, farClipPlane);
  53. vec3 L = -normalize(D);
  54. if( [GEARCORETex5_SPEC] == 11+i ) {
  55. shadowDepth = textureCube( [GEARCORETex5_CUBE], L ).r;
  56. }
  57. else if( [GEARCORETex6_SPEC] == 11+i ) {
  58. shadowDepth = textureCube( [GEARCORETex6_CUBE], L ).r;
  59. }
  60. else if( [GEARCORETex7_SPEC] == 11+i ) {
  61. shadowDepth = textureCube( [GEARCORETex7_CUBE], L ).r;
  62. }
  63. else if( [GEARCORETex8_SPEC] == 11+i ) {
  64. shadowDepth = textureCube( [GEARCORETex8_CUBE], L ).r;
  65. }
  66. else {
  67. // no sampler found
  68. lightingFactor = 1.0;
  69. return false; // no shadow on default case
  70. }
  71. lightingFactor = 1.0;
  72. if( depth >= shadowDepth && depth < 1.0 ) {
  73. lightingFactor = 0.0;
  74. return true;
  75. }
  76. else
  77. return false;
  78. }
  79. // we define one shadow coordinate for each spot lightsource
  80. varying vec4 ShadowCoord_5;
  81. varying vec4 ShadowCoord_6;
  82. varying vec4 ShadowCoord_7;
  83. varying vec4 ShadowCoord_8;
  84. // we define one sampler for each spot lightsource
  85. uniform sampler2D shadow_map_spot_5;
  86. uniform sampler2D shadow_map_spot_6;
  87. uniform sampler2D shadow_map_spot_7;
  88. uniform sampler2D shadow_map_spot_8;
  89. /*
  90. * This function does a shadowmap lookup in a given shadowmap and returs a shadow coefficient,
  91. * which can be used for the diffuse and specular lighting calculation.
  92. * There have to be a few parameters provided:
  93. * @param i The light ID.
  94. * @return True, if fragment is in shadow, false if not.
  95. */
  96. float gearShadowLookupSpotLight( in int i ) {
  97. // get the sampler to use for this light
  98. float shadowCoeff = 0.0; // the resulting coefficient
  99. vec4 shadowCoord;
  100. if( [GEARCORETex5_SPEC] == 6+i ) {
  101. // we have to divide by the w component due to perspective
  102. shadowCoord = ShadowCoord_5 / ShadowCoord_5.w;
  103. shadowCoeff = texture2D([GEARCORETex5_2D],shadowCoord.st).r;
  104. if( shadowCoeff < shadowCoord.z ) return 0.0;
  105. else return 1.0;
  106. }
  107. else if( [GEARCORETex6_SPEC] == 6+i ) {
  108. // we have to divide by the w component due to perspective
  109. shadowCoord = ShadowCoord_6 / ShadowCoord_6.w;
  110. shadowCoeff = texture2D([GEARCORETex6_2D],shadowCoord.st).r;
  111. if( shadowCoeff < shadowCoord.z ) return 0.0;
  112. else return 1.0;
  113. }
  114. else if( [GEARCORETex7_SPEC] == 6+i ) {
  115. // we have to divide by the w component due to perspective
  116. shadowCoord = ShadowCoord_7 / ShadowCoord_7.w;
  117. shadowCoeff = texture2D([GEARCORETex7_2D],shadowCoord.st).r;
  118. if( shadowCoeff < shadowCoord.z ) return 0.0;
  119. else return 1.0;
  120. }
  121. else if( [GEARCORETex8_SPEC] == 6+i ) {
  122. // we have to divide by the w component due to perspective
  123. shadowCoord = ShadowCoord_8 / ShadowCoord_8.w;
  124. shadowCoeff = texture2D([GEARCORETex8_2D],shadowCoord.st).r;
  125. if( shadowCoeff < shadowCoord.z ) return 0.0;
  126. else return 1.0;
  127. }
  128. else {
  129. // no sampler found
  130. return 1.0; // no shadow on default case
  131. }
  132. }
  133. // variables to allow only one cascade shadow mapping light
  134. // note that when including this module, the here given uniforms are always defined.
  135. // The currently implemented CSM-Algorithm will bind the Shadowmaps to this variables.
  136. // currently it is not possible to let GEAR bind the Shadowmaps for CSM to other variables than this one!
  137. // make sure you've included the following line to your shader loader:
  138. // shader->addRequest( SHADER_REQ_CASCADED_SHADOW_RESSOURCES );
  139. // this let's GEAR know that this module is included and that the variables are accessable
  140. uniform sampler2DArrayShadow gear_cascadeArray; // a cascade array for every light
  141. uniform vec4 gear_far_bounds; // the far bounds of the different cascades contained in a Vec4
  142. uniform mat4 gear_cascade_texture_matrices[4]; // The different texturematrices
  143. #define GEAR_NO_FILTER 0
  144. #define GEAR_PERCENTAGE_CLOSER_FILTER_4 1
  145. #define GEAR_PERCENTAGE_CLOSER_FILTER_8 2
  146. #define GEAR_GAUSSIAN_FILTER 3
  147. uniform int gear_filter_mode = GEAR_GAUSSIAN_FILTER;
  148. int getCascadeIndex() {
  149. int index = 3;
  150. // find the appropriate depth map to look up in based on the depth of this fragment
  151. if(gl_FragCoord.z < gear_far_bounds.x)
  152. index = 0;
  153. else if(gl_FragCoord.z < gear_far_bounds.y)
  154. index = 1;
  155. else if(gl_FragCoord.z < gear_far_bounds.z)
  156. index = 2;
  157. return index;
  158. }
  159. // sample offsets
  160. // Variables for 8 times PCF
  161. // Array Instanciation inside Shader will not work on ATI and NVIDIA Cards -> thanks to Alexander Gruske
  162. uniform vec4 offsets[8];
  163. float gearGetShadowCoeffDirectionalLightCascade( in int lightID, in vec3 vertexPosition ) {
  164. if( gear_light_id[lightID] == GEAR_CASCADED_SHADOW_MAPPING ) {
  165. int index = getCascadeIndex();
  166. // transform this fragment's position from view space to scaled light clip space
  167. // such that the xy coordinates are in [0;1]
  168. // note there is no need to divide by w for othogonal light sources
  169. vec4 shadow_coord = gear_cascade_texture_matrices[index]*vec4(vertexPosition, 1.0);
  170. shadow_coord.w = shadow_coord.z;
  171. // tell glsl in which layer to do the look up
  172. shadow_coord.z = float(index);
  173. vec2 texSize = vec2(2048.0,1.0/2048.0);
  174. float ret = 0.0f;
  175. if( gear_filter_mode == GEAR_PERCENTAGE_CLOSER_FILTER_4 ) {
  176. //Bilinear weighted 4-tap filter
  177. vec2 pos = mod( shadow_coord.xy * texSize.x, 1.0);
  178. vec2 offset = (0.5 - step( 0.5, pos)) * texSize.y;
  179. ret = shadow2DArray( gear_cascadeArray, shadow_coord + vec4( offset, 0, 0)).x * (pos.x) * (pos.y);
  180. ret += shadow2DArray( gear_cascadeArray, shadow_coord + vec4( offset.x, -offset.y, 0, 0)).x * (pos.x) * (1-pos.y);
  181. ret += shadow2DArray( gear_cascadeArray, shadow_coord + vec4( -offset.x, offset.y, 0, 0)).x * (1-pos.x) * (pos.y);
  182. ret += shadow2DArray( gear_cascadeArray, shadow_coord + vec4( -offset.x, -offset.y, 0, 0)).x * (1-pos.x) * (1-pos.y);
  183. }
  184. else if( gear_filter_mode == GEAR_PERCENTAGE_CLOSER_FILTER_8 ) {
  185. // PCF 8-tab filter
  186. for(int i = 0; i < 8; i++) {
  187. vec4 shadow_lookup = shadow_coord + texSize.y*offsets[i]*2.0; //scale the offsets to the texture size, and make them twice as large to cover a larger radius
  188. ret += shadow2DArray( gear_cascadeArray, shadow_lookup).x * 0.125 ;
  189. }
  190. }
  191. else if( gear_filter_mode == GEAR_GAUSSIAN_FILTER ) {
  192. // PCF Gaussian 3x3 filter
  193. ret = shadow2DArray(gear_cascadeArray, shadow_coord).x * 0.25;
  194. ret += shadow2DArrayOffset(gear_cascadeArray, shadow_coord, ivec2( -1, -1)).x * 0.0625;
  195. ret += shadow2DArrayOffset(gear_cascadeArray, shadow_coord, ivec2( -1, 0)).x * 0.125;
  196. ret += shadow2DArrayOffset(gear_cascadeArray, shadow_coord, ivec2( -1, 1)).x * 0.0625;
  197. ret += shadow2DArrayOffset(gear_cascadeArray, shadow_coord, ivec2( 0, -1)).x * 0.125;
  198. ret += shadow2DArrayOffset(gear_cascadeArray, shadow_coord, ivec2( 0, 1)).x * 0.125;
  199. ret += shadow2DArrayOffset(gear_cascadeArray, shadow_coord, ivec2( 1, -1)).x * 0.0625;
  200. ret += shadow2DArrayOffset(gear_cascadeArray, shadow_coord, ivec2( 1, 0)).x * 0.125;
  201. ret += shadow2DArrayOffset(gear_cascadeArray, shadow_coord, ivec2( 1, 1)).x * 0.0625;
  202. }
  203. else if( gear_filter_mode == GEAR_NO_FILTER ) {
  204. ret = shadow2DArray(gear_cascadeArray, shadow_coord).x;
  205. }
  206. return ret;
  207. }
  208. else
  209. return 1.0; // no shadow
  210. }