1#version 150 2 3in vec3 oPos; 4in vec4 oNormAndFogVal; 5in vec3 oEyePos; 6 7#if LIGHT0 8uniform vec4 lightPosition0; 9uniform vec4 spotlightDir0; 10uniform vec4 lightDiffuse0; 11uniform vec4 lightSpecular0; 12uniform vec4 lightAttenuation0; 13uniform vec4 lightSpotlight0; 14#endif 15#if LIGHT1 16uniform vec4 lightPosition1; 17uniform vec4 spotlightDir1; 18uniform vec4 lightDiffuse1; 19uniform vec4 lightSpecular1; 20uniform vec4 lightAttenuation1; 21uniform vec4 lightSpotlight1; 22#endif 23#if LIGHT2 24uniform vec4 lightPosition2; 25uniform vec4 spotlightDir2; 26uniform vec4 lightDiffuse2; 27uniform vec4 lightSpecular2; 28uniform vec4 lightAttenuation2; 29uniform vec4 lightSpotlight2; 30#endif 31 32uniform mat4 world; 33uniform float exponent; 34uniform float texScale; 35uniform float plateauSize; 36uniform float transitionSpeed; 37 38#if FOGLINEAR || FOGEXPONENTIAL || FOGEXPONENTIAL2 39uniform vec4 fogColour; 40#endif 41 42uniform vec4 ambient; 43uniform sampler2D texFromX; 44uniform sampler2D texFromXNormal; 45uniform sampler2D texFromY; 46uniform sampler2D texFromYNormal; 47uniform sampler2D texFromZ; 48uniform sampler2D texFromZNormal; 49 50out vec4 fragColour; 51 52vec3 expand(vec3 v) 53{ 54 return (v - 0.5) * 2; 55} 56 57vec4 lit(float NdotL, float NdotH, float m) 58{ 59 float ambient = 1.0; 60 float diffuse = max(NdotL, 0.0); 61 float specular = step(0.0, NdotL) * max(NdotH * m, 0.0); 62 63 return vec4(ambient, diffuse, specular, 1.0); 64} 65 66vec4 doLighting( 67 vec3 oPos, 68 vec3 normal, 69 vec3 eyeDir, 70 float exponent, 71 float specularFactor, 72 vec3 lightDir, 73 vec4 lightPosition, 74 vec4 lightDiffuse, 75 vec4 lightSpecular, 76 vec4 lightAttenuation, 77 vec4 lightSpotlight, 78 vec3 lightSpotDir 79) { 80 vec3 halfAngle = normalize(lightDir + eyeDir); 81 82 float nDotL = dot(lightDir, normal); 83 float nDotH = dot(halfAngle, normal); 84 vec4 lighting = lit(nDotL, nDotH, exponent); 85 86 float attenuation = 1; 87 #if ATTENUATION 88 if (lightPosition.w != 0) { 89 float distance = length(lightPosition.xyz - oPos); 90 attenuation = 1.0 / (lightAttenuation.y + lightAttenuation.z * distance + lightAttenuation.w * distance * distance); 91 } 92 #endif 93 94 float spot = 1; 95 if (!(lightSpotlight.x == 1 && lightSpotlight.y == 0 && lightSpotlight.z == 0 && lightSpotlight.w == 1)) { 96 spot = clamp( 97 (dot(lightDir, normalize(-lightSpotDir)) - lightSpotlight.y) / 98 (lightSpotlight.x - lightSpotlight.y), 0.0, 1.0); 99 } 100 101 return attenuation * spot * (lightDiffuse * lighting.y + specularFactor * lightSpecular * lighting.z); 102} 103 104void main() 105{ 106 107 vec3 unitNormal = normalize(oNormAndFogVal.xyz); 108 vec3 eyeDir = normalize(oEyePos - oPos); 109 110 // Ported from http://http.developer.nvidia.com/GPUGems3/gpugems3_ch01.html 111 vec3 blendWeights = abs(unitNormal); 112 blendWeights = blendWeights - plateauSize; 113 blendWeights = pow(max(blendWeights, 0), vec3(transitionSpeed)); 114 blendWeights /= vec3(blendWeights.x + blendWeights.y + blendWeights.z ); 115 // Move the planar mapping a bit according to the normal length to avoid bad looking skirts. 116 float nLength = length(oNormAndFogVal.xyz - 1.0); 117 vec2 coord1 = (oPos.yz + nLength) * texScale; 118 vec2 coord2 = (oPos.zx + nLength) * texScale; 119 vec2 coord3 = (oPos.xy + nLength) * texScale; 120 121 vec4 col1 = texture(texFromX, coord1); 122 vec4 col2 = texture(texFromY, coord2); 123 vec4 col3 = texture(texFromZ, coord3); 124 vec4 textColour = vec4(col1.xyz * blendWeights.x + 125 col2.xyz * blendWeights.y + 126 col3.xyz * blendWeights.z, 1); 127 128 // Normal Mapping 129 #if LIGHTNORMALMAPPING 130 vec3 tangent = vec3(1, 0, 0); 131 vec3 binormal = normalize(cross(tangent, unitNormal)); 132 tangent = normalize(cross(unitNormal, binormal)); 133 mat3 TBN = mat3(tangent, binormal, unitNormal); 134 vec3 eyeDir2 = normalize(TBN * eyeDir); 135 vec3 bumpFetch1 = expand(texture(texFromXNormal, coord1).rgb); 136 vec3 bumpFetch2 = expand(texture(texFromYNormal, coord2).rgb); 137 vec3 bumpFetch3 = expand(texture(texFromZNormal, coord3).rgb); 138 vec3 normal2 = bumpFetch1.xyz * blendWeights.x + 139 bumpFetch2.xyz * blendWeights.y + 140 bumpFetch3.xyz * blendWeights.z; 141 #else 142 vec3 eyeDir2 = eyeDir; 143 vec3 normal2 = unitNormal; 144 #endif 145 146 #if USESPECULARMAP 147 float specularFactor = textColour.a; 148 #else 149 float specularFactor = 1.0; 150 #endif 151 152 // Light 153 vec4 lightContribution = vec4(0, 0, 0, 0); 154 #if LIGHT0 155 vec3 lightSpotDir0 = (world * spotlightDir0).xyz; 156 vec3 lightDir0 = normalize(lightPosition0.xyz - oPos * lightPosition0.w); 157 #if LIGHTNORMALMAPPING 158 vec3 lightSpotDir02 = normalize(TBN * lightSpotDir0); 159 vec3 lightDir02 = normalize(TBN * lightDir0); 160 #else 161 vec3 lightSpotDir02 = lightSpotDir0; 162 vec3 lightDir02 = lightDir0; 163 #endif 164 lightContribution += doLighting(oPos, normal2, eyeDir2, exponent, specularFactor, lightDir02, lightPosition0, lightDiffuse0, lightSpecular0, lightAttenuation0, lightSpotlight0, lightSpotDir02); 165 #endif 166 167 #if LIGHT1 168 vec3 lightSpotDir1 = (world * spotlightDir1).xyz; 169 vec3 lightDir1 = normalize(lightPosition1.xyz - oPos * lightPosition1.w); 170 #if LIGHTNORMALMAPPING 171 vec3 lightSpotDir12 = normalize(TBN * lightSpotDir1); 172 vec3 lightDir12 = normalize(TBN * lightDir1); 173 #else 174 vec3 lightSpotDir12 = lightSpotDir1; 175 vec3 lightDir12 = lightDir1; 176 #endif 177 lightContribution += doLighting(oPos, normal2, eyeDir2, exponent, specularFactor, lightDir12, lightPosition1, lightDiffuse1, lightSpecular1, lightAttenuation1, lightSpotlight1, lightSpotDir12); 178 #endif 179 180 #if LIGHT2 181 vec3 lightSpotDir2 = (world * spotlightDir2).xyz; 182 vec3 lightDir2 = normalize(lightPosition2.xyz - oPos * lightPosition2.w); 183 #if LIGHTNORMALMAPPING 184 vec3 lightSpotDir22 = normalize(TBN * lightSpotDir2); 185 vec3 lightDir22 = normalize(TBN * lightDir2); 186 #else 187 vec3 lightSpotDir22 = lightSpotDir2; 188 vec3 lightDir22 = lightDir2; 189 #endif 190 lightContribution += doLighting(oPos, normal2, eyeDir2, exponent, specularFactor, lightDir22, lightPosition2, lightDiffuse2, lightSpecular2, lightAttenuation2, lightSpotlight2, lightSpotDir22); 191 #endif 192 193 fragColour = clamp(textColour * (lightContribution + ambient), 0.0, 1.0); 194 #if FOGLINEAR || FOGEXPONENTIAL || FOGEXPONENTIAL2 195 fragColour = mix(oColor, fogColour, oNormAndFogVal.w); 196 #endif 197 198} 199