#ifdef GL_ES precision mediump int; precision highp float; #endif #define USE_OGRE_FROM_FUTURE #include SAMPLER2D(shadowTexture0, 0); SAMPLER2D(shadowTexture1, 1); SAMPLER2D(shadowTexture2, 2); SAMPLER2D(jitterMapUnit, 3); SAMPLER2D(diffuseTexture, 4); OGRE_UNIFORMS( uniform vec4 texMatrixScaleBias1; uniform vec4 texMatrixScaleBias2; uniform float shadowmapSize0; uniform float inverseShadowmapSize0; uniform float shadowmapSize1; uniform float inverseShadowmapSize1; uniform float shadowmapSize2; uniform float inverseShadowmapSize2; uniform vec4 ambientColor; uniform vec4 materialColor; uniform vec4 lightPosition[6]; uniform vec4 spotlight[6]; uniform vec4 spotDir[6]; uniform vec4 lightAtt[6]; uniform vec4 lightDiff[6]; uniform vec4 fogParams; uniform vec4 slicePlane; ) vec2 lightAttribution(vec3 wp, vec3 normal, int id) { if ((lightAtt[id].x == 0.0) && (lightAtt[id].y == 1.0) && (lightAtt[id].z == 0.0) && (lightAtt[id].w == 0.0)) return vec2(0.0, 0.0); vec3 ld = normalize(lightPosition[id].xyz - (vec3_splat(lightPosition[id].w) * wp.xyz)); float diffFactor = (lightDiff[id].x + lightDiff[id].y + lightDiff[id].z) * 0.333333333; // attenuation if(lightAtt[id].w > 0.0) { float lightDist = length(lightPosition[id].xyz - wp.xyz); if (lightDist > lightAtt[id].x) return vec2(0.0, 0.0); float la = 1.0 / (lightAtt[id].y + lightAtt[id].z * lightDist + lightAtt[id].w * lightDist * lightDist); float spot = (spotlight[id].w == 0.0) ? 1.0 : saturate((dot(-normalize(spotDir[id].xyz - (vec3_splat(spotDir[id].w) * wp.xyz)), ld) - spotlight[id].y) / (spotlight[id].x - spotlight[id].y)); float cb = saturate(saturate(dot(normal, ld)) * spot * la * diffFactor); return vec2(cb, cb); } else { return vec2(saturate(dot(normal, ld) * diffFactor), 0.0); } } vec2 offsetRotateSample(vec2 uv, vec2 offset, mat2 rotMat, float invMapSize) { offset = mul(rotMat, offset); return vec2(uv + offset * vec2_splat(invMapSize)); } float getShadowFactor(sampler2D shadowMapUnit, sampler2D jitterMap, vec3 lightSpacePos, float shadowmapSize, float inverseShadowmapSize) { // point on shadowmap mat4 offsets; offsets[0] = vec4(-0.3464376, -0.7120676, 0.4692491, -0.7939163); offsets[1] = vec4(0.1561844, -0.04416115, -0.9133415, -0.3314315); offsets[2] = vec4(-0.4210564, 0.4838058, 0.5794852, 0.474482); offsets[3] = vec4(0.7723071, -0.2627881, 0.07587272, 0.926478); vec2 rotations = texture2D(jitterMap, lightSpacePos.xy * vec2_splat(shadowmapSize)).xy * vec2_splat(2.0) - vec2_splat(1.0); mat2 rotMat = mat2(rotations.x, -rotations.y, rotations.y, rotations.x); vec2 s1 = texture2D(shadowMapUnit, offsetRotateSample(lightSpacePos.xy, offsets[0].xy, rotMat, inverseShadowmapSize)).xy; vec2 s2 = texture2D(shadowMapUnit, offsetRotateSample(lightSpacePos.xy, offsets[0].zw, rotMat, inverseShadowmapSize)).xy; vec2 s3 = texture2D(shadowMapUnit, offsetRotateSample(lightSpacePos.xy, offsets[1].xy, rotMat, inverseShadowmapSize)).xy; vec2 s4 = texture2D(shadowMapUnit, offsetRotateSample(lightSpacePos.xy, offsets[1].zw, rotMat, inverseShadowmapSize)).xy; vec4 inLight = vec4_splat(0.0); if (lightSpacePos.z > s1.x) inLight.x = s1.y; if (lightSpacePos.z > s2.x) inLight.y = s2.y; if (lightSpacePos.z > s3.x) inLight.z = s3.y; if (lightSpacePos.z > s4.x) inLight.w = s4.y; float shadow = dot(inLight, vec4(0.125, 0.125, 0.125, 0.125)); s1 = texture2D(shadowMapUnit, offsetRotateSample(lightSpacePos.xy, offsets[2].xy, rotMat, inverseShadowmapSize)).xy; s2 = texture2D(shadowMapUnit, offsetRotateSample(lightSpacePos.xy, offsets[2].zw, rotMat, inverseShadowmapSize)).xy; s3 = texture2D(shadowMapUnit, offsetRotateSample(lightSpacePos.xy, offsets[3].xy, rotMat, inverseShadowmapSize)).xy; s4 = texture2D(shadowMapUnit, offsetRotateSample(lightSpacePos.xy, offsets[3].zw, rotMat, inverseShadowmapSize)).xy; inLight = vec4_splat(0.0); if (lightSpacePos.z > s1.x) inLight.x = s1.y; if (lightSpacePos.z > s2.x) inLight.y = s2.y; if (lightSpacePos.z > s3.x) inLight.z = s3.y; if (lightSpacePos.z > s4.x) inLight.w = s4.y; shadow += dot(inLight, vec4(0.125, 0.125, 0.125, 0.125)); return shadow; } float getCsmShadowFactor(sampler2D shadowTexture0, sampler2D shadowTexture1, sampler2D shadowTexture2, sampler2D jitterMap, vec3 lightSpacePos0) { float factor = 0.0; if (lightSpacePos0.x > 0.01 && lightSpacePos0.y > 0.01 && lightSpacePos0.x < 0.99 && lightSpacePos0.y < 0.99) { factor = getShadowFactor(shadowTexture0, jitterMap, lightSpacePos0, shadowmapSize0, inverseShadowmapSize0); vec3 lightSpacePos1 = lightSpacePos0.xyz + texMatrixScaleBias1.xyz; lightSpacePos1.xy *= vec2_splat(texMatrixScaleBias1.w); float blend = getShadowFactor(shadowTexture1, jitterMap, lightSpacePos1, shadowmapSize1, inverseShadowmapSize1); float weight = saturate((max(abs(lightSpacePos0.x-0.5), abs(lightSpacePos0.y-0.5)) -0.375) * 8.0); factor = mix(factor, blend, weight); } else { vec3 lightSpacePos1 = lightSpacePos0.xyz + texMatrixScaleBias1.xyz; lightSpacePos1.xy *= vec2_splat(texMatrixScaleBias1.w); if (lightSpacePos1.x > 0.01 && lightSpacePos1.y > 0.01 && lightSpacePos1.x < 0.99 && lightSpacePos1.y < 0.99) { factor = getShadowFactor(shadowTexture1, jitterMap, lightSpacePos1, shadowmapSize1, inverseShadowmapSize1); vec3 lightSpacePos2 = lightSpacePos0.xyz + texMatrixScaleBias2.xyz; lightSpacePos2.xy *= vec2_splat(texMatrixScaleBias2.w); float blend = getShadowFactor(shadowTexture2, jitterMap, lightSpacePos2, shadowmapSize2, inverseShadowmapSize2); float weight = saturate((max( abs(lightSpacePos1.x-0.5), abs(lightSpacePos1.y-0.5)) -0.4375) * 16.0); factor = mix(factor, blend, weight); } else { vec3 lightSpacePos2 = lightSpacePos0.xyz + texMatrixScaleBias2.xyz; lightSpacePos2.xy *= vec2_splat(texMatrixScaleBias2.w); factor = getShadowFactor(shadowTexture2, jitterMap, lightSpacePos2, shadowmapSize2, inverseShadowmapSize2); // Fade out to edges float weight = saturate((max(abs(lightSpacePos2.x-0.5), abs(lightSpacePos2.y-0.5)) -0.375) * 8.0); factor = mix(factor, 1.0, weight); } } return factor; } MAIN_PARAMETERS IN(vec3 oUv, TEXCOORD0) IN(vec3 oShadowLightspacePos, TEXCOORD1) IN(vec3 oWp, TEXCOORD2) IN(vec3 oNormal, TEXCOORD3) MAIN_DECLARATION { if(((slicePlane.x + slicePlane.y + slicePlane.z) != 0.0) && (slicePlane.x * oWp.x + slicePlane.y * oWp.y + slicePlane.z * oWp.z + slicePlane.w > 0.0)) discard; float alpha = texture2D(diffuseTexture, oUv.xy).a; //if(alpha < 0.05) // discard; alpha *= materialColor.a; vec2 ld0 = lightAttribution(oWp, oNormal, 0); vec2 ld1 = lightAttribution(oWp, oNormal, 1); vec2 ld2 = lightAttribution(oWp, oNormal, 2); vec2 ld3 = lightAttribution(oWp, oNormal, 3); vec2 ld4 = lightAttribution(oWp, oNormal, 4); vec2 ld5 = lightAttribution(oWp, oNormal, 5); float ld = saturate(ld0.x - saturate(ld1.y + ld2.y + ld3.y + ld4.y + ld5.y)); float shadow = getCsmShadowFactor(shadowTexture0, shadowTexture1, shadowTexture2, jitterMapUnit, oShadowLightspacePos); float fog = saturate((fogParams.z - oUv.z) * fogParams.w); shadow *= fog * alpha * ld; vec3 brightness = ambientColor.rgb * vec3_splat(shadow); gl_FragColor = vec4(brightness, shadow); }