/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
- /* This is a gear shader module for shadow mapping.
- * to use this module add the following line before usage of the here defined functions
- * into the shader:
- * import gearmod GEARCoreShadow.mod.glsl
- * after this you can simply call the gearShadowLookupOmnidirectionalLight(...) function with the parameters you want.
- * make sure that the shadow mapping is enabled in your gear application.
- * note: this version only works with a textures available in the shader.
- * for another version you should remove the access to this texture slots.
- * Here are the values of the GEARFlag [GEARCORETexN_SPEC]:
- * 6: TEX_2D_SHADOW_LIGHT1 - Texture contains a 2D shadowmap for light 1
- * 7: TEX_2D_SHADOW_LIGHT2 - Texture contains a 2D shadowmap for light 2
- * 8: TEX_2D_SHADOW_LIGHT3 - Texture contains a 2D shadowmap for light 3
- * 9: TEX_2D_SHADOW_LIGHT4 - Texture contains a 2D shadowmap for light 4
- * 11: TEX_CUBE_SHADOW_LIGHT1 - Texture contains a cube shadowmap for light 1
- * 12: TEX_CUBE_SHADOW_LIGHT2 - Texture contains a cube shadowmap for light 2
- * 13: TEX_CUBE_SHADOW_LIGHT3 - Texture contains a cube shadowmap for light 3
- * 14: TEX_CUBE_SHADOW_LIGHT4 - Texture contains a cube shadowmap for light 4
- *
- * Note that only Texture slot 5 to 8 are used for shadow maps.
- */
-
- // these integers hold the informations about the lightsources regardless to their type (spot, directional, ...), e.g. if they use shadowing or not.
- // If for example a spot light 4 uses shadow, we know that to the corresponding Shadowmap the right shadowmap is bound
- // the available texture combiners
- #define GEAR_SHADOW_OFF 0
- #define GEAR_SHADOW_MAPPING 1
- #define GEAR_CASCADED_SHADOW_MAPPING 2
- #define GEAR_SHADOW_VOLUME 3
- uniform int gear_light_id[8];
-
-
- /*
- * This function is only for internal usage.
- */
- float toTexDepth( vec3 d, float near, float far) {
- float dist = max(max(abs(d.x),abs(d.y)),abs(d.z));
- float fmn = far - near;
- dist = ((far+near)/(fmn)) + (1.0/dist)*((-2.0*far*near)/(fmn));
- return (dist+1.0)/2.0;
- }
-
- /*
- * This function does a shadowmap lookup in a given shadowmap and returs the date.
- * There have to be a few parameters provided:
- * @param i The light ID.
- * @param vertex The vertex in modelspace
- * @param nearClipPlane The near clip plane to use.
- * @param farClipPlane The far clip plane to use.
- * @param lightingFactor The factor to multiply the ambient light with.
- * @return True, if fragment is in shadow, false if not.
- */
- bool gearShadowLookupOmnidirectionalLight( in int i, in vec3 vertex, in float nearClipPlane, in float farClipPlane, inout float lightingFactor ) {
- // get the sampler to use for this light
-
- float shadowDepth = 0.0;
- vec3 D = gl_LightSource[i].position.xyz - vertex;
-
- float depth = toTexDepth(D, nearClipPlane, farClipPlane);
- vec3 L = -normalize(D);
-
- if( [GEARCORETex5_SPEC] == 11+i ) {
- shadowDepth = textureCube( [GEARCORETex5_CUBE], L ).r;
- }
- else if( [GEARCORETex6_SPEC] == 11+i ) {
- shadowDepth = textureCube( [GEARCORETex6_CUBE], L ).r;
- }
- else if( [GEARCORETex7_SPEC] == 11+i ) {
- shadowDepth = textureCube( [GEARCORETex7_CUBE], L ).r;
- }
- else if( [GEARCORETex8_SPEC] == 11+i ) {
- shadowDepth = textureCube( [GEARCORETex8_CUBE], L ).r;
- }
- else {
- // no sampler found
- lightingFactor = 1.0;
- return false; // no shadow on default case
- }
-
- lightingFactor = 1.0;
-
- if( depth >= shadowDepth && depth < 1.0 ) {
- lightingFactor = 0.0;
- return true;
- }
- else
- return false;
- }
-
- // we define one shadow coordinate for each spot lightsource
- varying vec4 ShadowCoord_5;
- varying vec4 ShadowCoord_6;
- varying vec4 ShadowCoord_7;
- varying vec4 ShadowCoord_8;
-
- // we define one sampler for each spot lightsource
- uniform sampler2D shadow_map_spot_5;
- uniform sampler2D shadow_map_spot_6;
- uniform sampler2D shadow_map_spot_7;
- uniform sampler2D shadow_map_spot_8;
-
- /*
- * This function does a shadowmap lookup in a given shadowmap and returs a shadow coefficient,
- * which can be used for the diffuse and specular lighting calculation.
- * There have to be a few parameters provided:
- * @param i The light ID.
- * @return True, if fragment is in shadow, false if not.
- */
- float gearShadowLookupSpotLight( in int i ) {
- // get the sampler to use for this light
-
- float shadowCoeff = 0.0; // the resulting coefficient
- vec4 shadowCoord;
-
- if( [GEARCORETex5_SPEC] == 6+i ) {
- // we have to divide by the w component due to perspective
- shadowCoord = ShadowCoord_5 / ShadowCoord_5.w;
- shadowCoeff = texture2D([GEARCORETex5_2D],shadowCoord.st).r;
- if( shadowCoeff < shadowCoord.z ) return 0.0;
- else return 1.0;
- }
- else if( [GEARCORETex6_SPEC] == 6+i ) {
- // we have to divide by the w component due to perspective
- shadowCoord = ShadowCoord_6 / ShadowCoord_6.w;
- shadowCoeff = texture2D([GEARCORETex6_2D],shadowCoord.st).r;
- if( shadowCoeff < shadowCoord.z ) return 0.0;
- else return 1.0;
- }
- else if( [GEARCORETex7_SPEC] == 6+i ) {
- // we have to divide by the w component due to perspective
- shadowCoord = ShadowCoord_7 / ShadowCoord_7.w;
- shadowCoeff = texture2D([GEARCORETex7_2D],shadowCoord.st).r;
- if( shadowCoeff < shadowCoord.z ) return 0.0;
- else return 1.0;
- }
- else if( [GEARCORETex8_SPEC] == 6+i ) {
- // we have to divide by the w component due to perspective
- shadowCoord = ShadowCoord_8 / ShadowCoord_8.w;
- shadowCoeff = texture2D([GEARCORETex8_2D],shadowCoord.st).r;
- if( shadowCoeff < shadowCoord.z ) return 0.0;
- else return 1.0;
- }
- else {
- // no sampler found
- return 1.0; // no shadow on default case
- }
- }
-
- // variables to allow only one cascade shadow mapping light
- // note that when including this module, the here given uniforms are always defined.
- // The currently implemented CSM-Algorithm will bind the Shadowmaps to this variables.
- // currently it is not possible to let GEAR bind the Shadowmaps for CSM to other variables than this one!
- // make sure you've included the following line to your shader loader:
- // shader->addRequest( SHADER_REQ_CASCADED_SHADOW_RESSOURCES );
- // this let's GEAR know that this module is included and that the variables are accessable
- uniform sampler2DArrayShadow gear_cascadeArray; // a cascade array for every light
- uniform vec4 gear_far_bounds; // the far bounds of the different cascades contained in a Vec4
- uniform mat4 gear_cascade_texture_matrices[4]; // The different texturematrices
-
- #define GEAR_NO_FILTER 0
- #define GEAR_PERCENTAGE_CLOSER_FILTER_4 1
- #define GEAR_PERCENTAGE_CLOSER_FILTER_8 2
- #define GEAR_GAUSSIAN_FILTER 3
- uniform int gear_filter_mode = GEAR_GAUSSIAN_FILTER;
-
- int getCascadeIndex() {
- int index = 3;
-
- // find the appropriate depth map to look up in based on the depth of this fragment
- if(gl_FragCoord.z < gear_far_bounds.x)
- index = 0;
- else if(gl_FragCoord.z < gear_far_bounds.y)
- index = 1;
- else if(gl_FragCoord.z < gear_far_bounds.z)
- index = 2;
-
- return index;
- }
- // sample offsets
-
- // Variables for 8 times PCF
- // Array Instanciation inside Shader will not work on ATI and NVIDIA Cards -> thanks to Alexander Gruske
- uniform vec4 offsets[8];
-
-
-
-
- float gearGetShadowCoeffDirectionalLightCascade( in int lightID, in vec3 vertexPosition ) {
-
- if( gear_light_id[lightID] == GEAR_CASCADED_SHADOW_MAPPING ) {
- int index = getCascadeIndex();
-
- // transform this fragment's position from view space to scaled light clip space
- // such that the xy coordinates are in [0;1]
- // note there is no need to divide by w for othogonal light sources
- vec4 shadow_coord = gear_cascade_texture_matrices[index]*vec4(vertexPosition, 1.0);
-
- shadow_coord.w = shadow_coord.z;
-
- // tell glsl in which layer to do the look up
- shadow_coord.z = float(index);
-
-
-
-
- vec2 texSize = vec2(2048.0,1.0/2048.0);
-
- float ret = 0.0f;
-
- if( gear_filter_mode == GEAR_PERCENTAGE_CLOSER_FILTER_4 ) {
- //Bilinear weighted 4-tap filter
- vec2 pos = mod( shadow_coord.xy * texSize.x, 1.0);
- vec2 offset = (0.5 - step( 0.5, pos)) * texSize.y;
- ret = shadow2DArray( gear_cascadeArray, shadow_coord + vec4( offset, 0, 0)).x * (pos.x) * (pos.y);
- ret += shadow2DArray( gear_cascadeArray, shadow_coord + vec4( offset.x, -offset.y, 0, 0)).x * (pos.x) * (1-pos.y);
- ret += shadow2DArray( gear_cascadeArray, shadow_coord + vec4( -offset.x, offset.y, 0, 0)).x * (1-pos.x) * (pos.y);
- ret += shadow2DArray( gear_cascadeArray, shadow_coord + vec4( -offset.x, -offset.y, 0, 0)).x * (1-pos.x) * (1-pos.y);
- }
- else if( gear_filter_mode == GEAR_PERCENTAGE_CLOSER_FILTER_8 ) {
- // PCF 8-tab filter
- for(int i = 0; i < 8; i++) {
- 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
- ret += shadow2DArray( gear_cascadeArray, shadow_lookup).x * 0.125 ;
- }
- }
- else if( gear_filter_mode == GEAR_GAUSSIAN_FILTER ) {
- // PCF Gaussian 3x3 filter
- ret = shadow2DArray(gear_cascadeArray, shadow_coord).x * 0.25;
- ret += shadow2DArrayOffset(gear_cascadeArray, shadow_coord, ivec2( -1, -1)).x * 0.0625;
- ret += shadow2DArrayOffset(gear_cascadeArray, shadow_coord, ivec2( -1, 0)).x * 0.125;
- ret += shadow2DArrayOffset(gear_cascadeArray, shadow_coord, ivec2( -1, 1)).x * 0.0625;
- ret += shadow2DArrayOffset(gear_cascadeArray, shadow_coord, ivec2( 0, -1)).x * 0.125;
- ret += shadow2DArrayOffset(gear_cascadeArray, shadow_coord, ivec2( 0, 1)).x * 0.125;
- ret += shadow2DArrayOffset(gear_cascadeArray, shadow_coord, ivec2( 1, -1)).x * 0.0625;
- ret += shadow2DArrayOffset(gear_cascadeArray, shadow_coord, ivec2( 1, 0)).x * 0.125;
- ret += shadow2DArrayOffset(gear_cascadeArray, shadow_coord, ivec2( 1, 1)).x * 0.0625;
- }
- else if( gear_filter_mode == GEAR_NO_FILTER ) {
- ret = shadow2DArray(gear_cascadeArray, shadow_coord).x;
- }
- return ret;
- }
- else
- return 1.0; // no shadow
- }