#version 330 // Number of lights // 3 is resonable number to support #define NUM_LIGHTS 3 uniform sampler2D diffuseMap; uniform sampler2D specularMap; uniform sampler2D normalHeightMap; uniform sampler2D shadowMap0; uniform sampler2D shadowMap1; uniform sampler2D shadowMap2; uniform sampler2D shadowMap3; uniform sampler2D shadowMap4; uniform float fixedDepthBias; uniform vec3 cameraPosition; uniform vec3 lightAmbient; uniform vec4 scaleBias; uniform vec4 lightPositions[NUM_LIGHTS]; uniform vec4 lightDiffuseColours[NUM_LIGHTS]; uniform vec4 lightSpecularColours[NUM_LIGHTS]; uniform vec4 lightAttenuations[NUM_LIGHTS]; uniform float numberOfActiveLights; uniform float shininess; uniform vec4 invShadowMapSize0; uniform vec4 invShadowMapSize1; uniform vec4 invShadowMapSize2; uniform vec4 invShadowMapSize3; uniform vec4 invShadowMapSize4; //uniform vec4 pssmSplitPoints; const vec4 pssmSplitPoints = vec4(1.0, 15.0, 50.0, 200.0); in vec4 oUv0; in vec3 oVNormal; in vec4 oVPos; in vec3 oEyeDir; in mat4 oWorldMatrix; in vec3 oVTangent; in vec3 oNormal; in vec3 oTangent; in vec4 oShadowTexCoord0; in vec4 oShadowTexCoord1; in vec4 oShadowTexCoord2; in vec4 oShadowTexCoord3; in vec4 oShadowTexCoord4; out vec4 fragColour; float shadowPCF(sampler2D shadowMap, vec4 shadowMapPos, vec2 offset) { shadowMapPos = shadowMapPos / shadowMapPos.w; vec2 uv = shadowMapPos.xy; vec3 o = vec3(offset, -offset.x) * 0.3; float c = (shadowMapPos.z <= texture(shadowMap, uv.xy - o.xy).r * (1.0 - fixedDepthBias)) ? 1.0 : 0.0; // top left c += (shadowMapPos.z <= texture(shadowMap, uv.xy + o.xy).r * (1.0 - fixedDepthBias)) ? 1.0 : 0.0; // bottom right c += (shadowMapPos.z <= texture(shadowMap, uv.xy + o.zy).r * (1.0 - fixedDepthBias)) ? 1.0 : 0.0; // bottom left c += (shadowMapPos.z <= texture(shadowMap, uv.xy - o.zy).r * (1.0 - fixedDepthBias)) ? 1.0 : 0.0; // top right return c / 4.0; } vec4 expand(vec4 x) { return 2.0 * x - 1.0; } void main(void) { /* // Get the height using the tex coords float height = texture2D(normalHeightMap, oUv0.xy).a; // Calculate displacement float displacement = (height * scaleBias.x) + scaleBias.y; vec3 uv2 = vec3(oUv0.xy, 1.0); // calculate the new tex coord to use for normal and diffuse vec2 uv = ((oEyeDir * displacement) + uv2).xy; */ vec2 uv = oUv0.xy; vec4 baseColour = texture(diffuseMap, uv); if (baseColour.a < 0.5) { discard; } vec4 specularColour = texture(specularMap, uv); vec3 ambient = lightAmbient * baseColour.xyz; vec3 normal = normalize(oVNormal); vec3 eyeDir = normalize(cameraPosition - oVPos.xyz ); // vec4 bumpVec = expand(texture(normalHeightMap, uv)); // normal = normalize(bumpVec.xyz * oWorldMatrix).xyz; // normal = normalize(bumpVec.xyz); // normal = normalize((oWorldMatrix * bumpVec).xyz); // derive the tangent space basis vec3 tangent = oVTangent.xyz; normal = normalize(oNormal); tangent = normalize(oTangent); // we do this in the pixel shader because we don't have per-vertex normals // because of the LOD, we use a normal map vec3 binormal = normalize(cross(tangent, normal)); // note, now we need to re-cross to derive tangent again because it wasn't orthonormal tangent = normalize(cross(normal, binormal)); // derive final matrix mat3 TBN = mat3(tangent, binormal, normal); vec3 cameraDirectionTangentSpace = normalize(transpose(TBN) * (eyeDir)); float displacement = texture(normalHeightMap, uv).a * scaleBias.x + scaleBias.y; uv += cameraDirectionTangentSpace.xy * displacement; normal = texture(normalHeightMap, uv).rgb; baseColour = texture(diffuseMap, uv); normal = normalize(TBN * normal); vec3 directLighting = vec3(0); for (int i = 0; i < NUM_LIGHTS && i < int(numberOfActiveLights); i++) { float shadowing = 1.0; //First light uses PSSM if (i == 0) { if (oUv0.z <= pssmSplitPoints.y) { // Calculate the position of vertex in light space shadowing = shadowPCF(shadowMap0, oShadowTexCoord0, invShadowMapSize0.xy); } else if (oUv0.z <= pssmSplitPoints.z) { // Calculate the position of vertex in light space shadowing = shadowPCF(shadowMap1, oShadowTexCoord1, invShadowMapSize1.xy); } else { // Calculate the position of vertex in light space shadowing = shadowPCF(shadowMap2, oShadowTexCoord2, invShadowMapSize2.xy); } } else if (i == 1) { shadowing = shadowPCF(shadowMap3, oShadowTexCoord3, invShadowMapSize3.xy); } else { shadowing = shadowPCF(shadowMap4, oShadowTexCoord4, invShadowMapSize4.xy); } vec3 lightDir = lightPositions[i].xyz - oVPos.xyz * lightPositions[i].w; float fLength = length(lightDir); lightDir = normalize(lightDir); float NdotL = max(0, dot(normal, lightDir)); vec3 diffuse = lightDiffuseColours[i].rgb * NdotL * baseColour.xyz; float attenuation = 1.0 / (lightAttenuations[i].y + lightAttenuations[i].z * fLength + lightAttenuations[i].w * fLength * fLength); vec3 specular = vec3(0); if (NdotL > 0.0) { vec3 halfVector = normalize(lightDir + eyeDir); float NdotH = max(0.0, dot(normal, halfVector)); specular = lightSpecularColours[i].rgb * vec3(pow(NdotH, shininess)); } directLighting += (diffuse + (specular * specularColour.xyz)) * shadowing * attenuation; } fragColour = vec4(directLighting + ambient, baseColour.a); }