|
@@ -0,0 +1,505 @@
|
|
|
+#ifdef GL_ES
|
|
|
+precision mediump float;
|
|
|
+#endif
|
|
|
+
|
|
|
+#define MAP_PROJECTION 4.
|
|
|
+
|
|
|
+// Constants
|
|
|
+uniform vec3 vEyePosition;
|
|
|
+uniform vec3 vAmbientColor;
|
|
|
+uniform vec4 vDiffuseColor;
|
|
|
+uniform vec4 vSpecularColor;
|
|
|
+uniform vec3 vEmissiveColor;
|
|
|
+
|
|
|
+// Input
|
|
|
+varying vec3 vPositionW;
|
|
|
+varying vec3 vNormalW;
|
|
|
+
|
|
|
+#ifdef VERTEXCOLOR
|
|
|
+varying vec3 vColor;
|
|
|
+#endif
|
|
|
+
|
|
|
+// Lights
|
|
|
+#ifdef LIGHT0
|
|
|
+uniform vec4 vLightData0;
|
|
|
+uniform vec3 vLightDiffuse0;
|
|
|
+uniform vec3 vLightSpecular0;
|
|
|
+#ifdef SHADOW0
|
|
|
+varying vec4 vPositionFromLight0;
|
|
|
+uniform sampler2D shadowSampler0;
|
|
|
+#endif
|
|
|
+#ifdef SPOTLIGHT0
|
|
|
+uniform vec4 vLightDirection0;
|
|
|
+#endif
|
|
|
+#ifdef HEMILIGHT0
|
|
|
+uniform vec3 vLightGround0;
|
|
|
+#endif
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef LIGHT1
|
|
|
+uniform vec4 vLightData1;
|
|
|
+uniform vec3 vLightDiffuse1;
|
|
|
+uniform vec3 vLightSpecular1;
|
|
|
+#ifdef SHADOW1
|
|
|
+varying vec4 vPositionFromLight1;
|
|
|
+uniform sampler2D shadowSampler1;
|
|
|
+#endif
|
|
|
+#ifdef SPOTLIGHT1
|
|
|
+uniform vec4 vLightDirection1;
|
|
|
+#endif
|
|
|
+#ifdef HEMILIGHT1
|
|
|
+uniform vec3 vLightGround1;
|
|
|
+#endif
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef LIGHT2
|
|
|
+uniform vec4 vLightData2;
|
|
|
+uniform vec3 vLightDiffuse2;
|
|
|
+uniform vec3 vLightSpecular2;
|
|
|
+#ifdef SHADOW2
|
|
|
+varying vec4 vPositionFromLight2;
|
|
|
+uniform sampler2D shadowSampler2;
|
|
|
+#endif
|
|
|
+#ifdef SPOTLIGHT2
|
|
|
+uniform vec4 vLightDirection2;
|
|
|
+#endif
|
|
|
+#ifdef HEMILIGHT2
|
|
|
+uniform vec3 vLightGround2;
|
|
|
+#endif
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef LIGHT3
|
|
|
+uniform vec4 vLightData3;
|
|
|
+uniform vec3 vLightDiffuse3;
|
|
|
+uniform vec3 vLightSpecular3;
|
|
|
+#ifdef SHADOW3
|
|
|
+varying vec4 vPositionFromLight3;
|
|
|
+uniform sampler2D shadowSampler3;
|
|
|
+#endif
|
|
|
+#ifdef SPOTLIGHT3
|
|
|
+uniform vec4 vLightDirection3;
|
|
|
+#endif
|
|
|
+#ifdef HEMILIGHT3
|
|
|
+uniform vec3 vLightGround3;
|
|
|
+#endif
|
|
|
+#endif
|
|
|
+
|
|
|
+// Samplers
|
|
|
+#ifdef DIFFUSE
|
|
|
+varying vec2 vDiffuseUV;
|
|
|
+uniform sampler2D diffuseSampler;
|
|
|
+uniform vec2 vDiffuseInfos;
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef AMBIENT
|
|
|
+varying vec2 vAmbientUV;
|
|
|
+uniform sampler2D ambientSampler;
|
|
|
+uniform vec2 vAmbientInfos;
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef OPACITY
|
|
|
+varying vec2 vOpacityUV;
|
|
|
+uniform sampler2D opacitySampler;
|
|
|
+uniform vec2 vOpacityInfos;
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef REFLECTION
|
|
|
+varying vec3 vReflectionUVW;
|
|
|
+uniform samplerCube reflectionCubeSampler;
|
|
|
+uniform sampler2D reflection2DSampler;
|
|
|
+uniform vec3 vReflectionInfos;
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef EMISSIVE
|
|
|
+varying vec2 vEmissiveUV;
|
|
|
+uniform vec2 vEmissiveInfos;
|
|
|
+uniform sampler2D emissiveSampler;
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef SPECULAR
|
|
|
+varying vec2 vSpecularUV;
|
|
|
+uniform vec2 vSpecularInfos;
|
|
|
+uniform sampler2D specularSampler;
|
|
|
+#endif
|
|
|
+
|
|
|
+// Shadows
|
|
|
+#ifdef SHADOWS
|
|
|
+
|
|
|
+float unpack(vec4 color)
|
|
|
+{
|
|
|
+ const vec4 bitShift = vec4(1. / (255. * 255. * 255.), 1. / (255. * 255.), 1. / 255., 1.);
|
|
|
+ return dot(color, bitShift);
|
|
|
+}
|
|
|
+
|
|
|
+float unpackHalf(vec2 color)
|
|
|
+{
|
|
|
+ return color.x + (color.y / 255.0);
|
|
|
+}
|
|
|
+
|
|
|
+float computeShadow(vec4 vPositionFromLight, sampler2D shadowSampler)
|
|
|
+{
|
|
|
+ vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
|
|
|
+ vec2 uv = 0.5 * depth.xy + vec2(0.5, 0.5);
|
|
|
+
|
|
|
+ if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)
|
|
|
+ {
|
|
|
+ return 1.0;
|
|
|
+ }
|
|
|
+
|
|
|
+ float shadow = unpack(texture2D(shadowSampler, uv));
|
|
|
+
|
|
|
+ if (depth.z > shadow)
|
|
|
+ {
|
|
|
+ return 0.;
|
|
|
+ }
|
|
|
+ return 1.;
|
|
|
+}
|
|
|
+
|
|
|
+// Thanks to http://devmaster.net/
|
|
|
+float ChebychevInequality(vec2 moments, float t)
|
|
|
+{
|
|
|
+ if (t <= moments.x)
|
|
|
+ {
|
|
|
+ return 1.0;
|
|
|
+ }
|
|
|
+
|
|
|
+ float variance = moments.y - (moments.x * moments.x);
|
|
|
+ variance = max(variance, 0.);
|
|
|
+
|
|
|
+ float d = t - moments.x;
|
|
|
+ return variance / (variance + d * d);
|
|
|
+}
|
|
|
+
|
|
|
+float computeShadowWithVSM(vec4 vPositionFromLight, sampler2D shadowSampler)
|
|
|
+{
|
|
|
+ vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
|
|
|
+ vec2 uv = 0.5 * depth.xy + vec2(0.5, 0.5);
|
|
|
+
|
|
|
+ if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)
|
|
|
+ {
|
|
|
+ return 1.0;
|
|
|
+ }
|
|
|
+
|
|
|
+ vec4 texel = texture2D(shadowSampler, uv);
|
|
|
+
|
|
|
+ vec2 moments = vec2(unpackHalf(texel.xy), unpackHalf(texel.zw));
|
|
|
+ return clamp(1.3 - ChebychevInequality(moments, depth.z), 0., 1.0);
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef CLIPPLANE
|
|
|
+varying float fClipDistance;
|
|
|
+#endif
|
|
|
+
|
|
|
+// Fog
|
|
|
+#ifdef FOG
|
|
|
+
|
|
|
+#define FOGMODE_NONE 0.
|
|
|
+#define FOGMODE_EXP 1.
|
|
|
+#define FOGMODE_EXP2 2.
|
|
|
+#define FOGMODE_LINEAR 3.
|
|
|
+#define E 2.71828
|
|
|
+
|
|
|
+uniform vec4 vFogInfos;
|
|
|
+uniform vec3 vFogColor;
|
|
|
+varying float fFogDistance;
|
|
|
+
|
|
|
+float CalcFogFactor()
|
|
|
+{
|
|
|
+ float fogCoeff = 1.0;
|
|
|
+ float fogStart = vFogInfos.y;
|
|
|
+ float fogEnd = vFogInfos.z;
|
|
|
+ float fogDensity = vFogInfos.w;
|
|
|
+
|
|
|
+ if (FOGMODE_LINEAR == vFogInfos.x)
|
|
|
+ {
|
|
|
+ fogCoeff = (fogEnd - fFogDistance) / (fogEnd - fogStart);
|
|
|
+ }
|
|
|
+ else if (FOGMODE_EXP == vFogInfos.x)
|
|
|
+ {
|
|
|
+ fogCoeff = 1.0 / pow(E, fFogDistance * fogDensity);
|
|
|
+ }
|
|
|
+ else if (FOGMODE_EXP2 == vFogInfos.x)
|
|
|
+ {
|
|
|
+ fogCoeff = 1.0 / pow(E, fFogDistance * fFogDistance * fogDensity * fogDensity);
|
|
|
+ }
|
|
|
+
|
|
|
+ return clamp(fogCoeff, 0.0, 1.0);
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+// Light Computing
|
|
|
+mat3 computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor) {
|
|
|
+ mat3 result;
|
|
|
+
|
|
|
+ vec3 lightVectorW;
|
|
|
+ if (lightData.w == 0.)
|
|
|
+ {
|
|
|
+ lightVectorW = normalize(lightData.xyz - vPositionW);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ lightVectorW = normalize(-lightData.xyz);
|
|
|
+ }
|
|
|
+
|
|
|
+ // diffuse
|
|
|
+ float ndl = max(0., dot(vNormal, lightVectorW));
|
|
|
+
|
|
|
+ // Specular
|
|
|
+ vec3 angleW = normalize(viewDirectionW + lightVectorW);
|
|
|
+ float specComp = max(0., dot(vNormal, angleW));
|
|
|
+ specComp = max(0., pow(specComp, max(1.0, vSpecularColor.a)));
|
|
|
+
|
|
|
+ result[0] = ndl * diffuseColor;
|
|
|
+ result[1] = specComp * specularColor;
|
|
|
+ result[2] = vec3(0.);
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+mat3 computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec4 lightDirection, vec3 diffuseColor, vec3 specularColor) {
|
|
|
+ mat3 result;
|
|
|
+
|
|
|
+ vec3 lightVectorW = normalize(lightData.xyz - vPositionW);
|
|
|
+
|
|
|
+ // diffuse
|
|
|
+ float cosAngle = max(0., dot(-lightDirection.xyz, lightVectorW));
|
|
|
+ float spotAtten = 0.0;
|
|
|
+
|
|
|
+ if (cosAngle >= lightDirection.w)
|
|
|
+ {
|
|
|
+ cosAngle = max(0., pow(cosAngle, lightData.w));
|
|
|
+ spotAtten = max(0., (cosAngle - lightDirection.w) / (1. - cosAngle));
|
|
|
+
|
|
|
+ // Diffuse
|
|
|
+ float ndl = max(0., dot(vNormal, -lightDirection.xyz));
|
|
|
+
|
|
|
+ // Specular
|
|
|
+ vec3 angleW = normalize(viewDirectionW - lightDirection.xyz);
|
|
|
+ float specComp = max(0., dot(vNormal, angleW));
|
|
|
+ specComp = pow(specComp, vSpecularColor.a);
|
|
|
+
|
|
|
+ result[0] = ndl * spotAtten * diffuseColor;
|
|
|
+ result[1] = specComp * specularColor * spotAtten;
|
|
|
+ result[2] = vec3(0.);
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ result[0] = vec3(0.);
|
|
|
+ result[1] = vec3(0.);
|
|
|
+ result[2] = vec3(0.);
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+mat3 computeHemisphericLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, vec3 groundColor) {
|
|
|
+ mat3 result;
|
|
|
+
|
|
|
+ // Diffuse
|
|
|
+ float ndl = dot(vNormal, lightData.xyz) * 0.5 + 0.5;
|
|
|
+
|
|
|
+ // Specular
|
|
|
+ vec3 angleW = normalize(viewDirectionW + lightData.xyz);
|
|
|
+ float specComp = max(0., dot(vNormal, angleW));
|
|
|
+ specComp = pow(specComp, vSpecularColor.a);
|
|
|
+
|
|
|
+ result[0] = mix(groundColor, diffuseColor, ndl);
|
|
|
+ result[1] = specComp * specularColor;
|
|
|
+ result[2] = vec3(0.);
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+void main(void) {
|
|
|
+ // Clip plane
|
|
|
+#ifdef CLIPPLANE
|
|
|
+ if (fClipDistance > 0.0)
|
|
|
+ discard;
|
|
|
+#endif
|
|
|
+
|
|
|
+ vec3 viewDirectionW = normalize(vEyePosition - vPositionW);
|
|
|
+
|
|
|
+ // Base color
|
|
|
+ vec4 baseColor = vec4(1., 1., 1., 1.);
|
|
|
+ vec3 diffuseColor = vDiffuseColor.rgb;
|
|
|
+
|
|
|
+#ifdef VERTEXCOLOR
|
|
|
+ diffuseColor *= vColor;
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef DIFFUSE
|
|
|
+ baseColor = texture2D(diffuseSampler, vDiffuseUV);
|
|
|
+
|
|
|
+#ifdef ALPHATEST
|
|
|
+ if (baseColor.a < 0.4)
|
|
|
+ discard;
|
|
|
+#endif
|
|
|
+
|
|
|
+ baseColor.rgb *= vDiffuseInfos.y;
|
|
|
+#endif
|
|
|
+
|
|
|
+ // Bump
|
|
|
+ vec3 normalW = vNormalW;
|
|
|
+
|
|
|
+ // Ambient color
|
|
|
+ vec3 baseAmbientColor = vec3(1., 1., 1.);
|
|
|
+
|
|
|
+#ifdef AMBIENT
|
|
|
+ baseAmbientColor = texture2D(ambientSampler, vAmbientUV).rgb * vAmbientInfos.y;
|
|
|
+#endif
|
|
|
+
|
|
|
+ // Lighting
|
|
|
+ vec3 diffuseBase = vec3(0., 0., 0.);
|
|
|
+ vec3 specularBase = vec3(0., 0., 0.);
|
|
|
+ float shadow = 1.;
|
|
|
+
|
|
|
+#ifdef LIGHT0
|
|
|
+#ifdef SPOTLIGHT0
|
|
|
+ mat3 info = computeSpotLighting(viewDirectionW, normalW, vLightData0, vLightDirection0, vLightDiffuse0, vLightSpecular0);
|
|
|
+#endif
|
|
|
+#ifdef HEMILIGHT0
|
|
|
+ mat3 info = computeHemisphericLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0, vLightSpecular0, vLightGround0);
|
|
|
+#endif
|
|
|
+#ifdef POINTDIRLIGHT0
|
|
|
+ mat3 info = computeLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0, vLightSpecular0);
|
|
|
+#endif
|
|
|
+#ifdef SHADOW0
|
|
|
+#ifdef SHADOWVSM0
|
|
|
+ shadow = computeShadowWithVSM(vPositionFromLight0, shadowSampler0);
|
|
|
+#else
|
|
|
+ shadow = computeShadow(vPositionFromLight0, shadowSampler0);
|
|
|
+#endif
|
|
|
+#else
|
|
|
+ shadow = 1.;
|
|
|
+#endif
|
|
|
+ diffuseBase += info[0] * shadow;
|
|
|
+ specularBase += info[1] * shadow;
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef LIGHT1
|
|
|
+#ifdef SPOTLIGHT1
|
|
|
+ info = computeSpotLighting(viewDirectionW, normalW, vLightData1, vLightDirection1, vLightDiffuse1, vLightSpecular1);
|
|
|
+#endif
|
|
|
+#ifdef HEMILIGHT1
|
|
|
+ info = computeHemisphericLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1, vLightSpecular1, vLightGround1);
|
|
|
+#endif
|
|
|
+#ifdef POINTDIRLIGHT1
|
|
|
+ info = computeLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1, vLightSpecular1);
|
|
|
+#endif
|
|
|
+#ifdef SHADOW1
|
|
|
+#ifdef SHADOWVSM1
|
|
|
+ shadow = computeShadowWithVSM(vPositionFromLight1, shadowSampler1);
|
|
|
+#else
|
|
|
+ shadow = computeShadow(vPositionFromLight1, shadowSampler1);
|
|
|
+#endif
|
|
|
+#else
|
|
|
+ shadow = 1.;
|
|
|
+#endif
|
|
|
+ diffuseBase += info[0] * shadow;
|
|
|
+ specularBase += info[1] * shadow;
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef LIGHT2
|
|
|
+#ifdef SPOTLIGHT2
|
|
|
+ info = computeSpotLighting(viewDirectionW, normalW, vLightData2, vLightDirection2, vLightDiffuse2, vLightSpecular2);
|
|
|
+#endif
|
|
|
+#ifdef HEMILIGHT2
|
|
|
+ info = computeHemisphericLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2, vLightSpecular2, vLightGround2);
|
|
|
+#endif
|
|
|
+#ifdef POINTDIRLIGHT2
|
|
|
+ info = computeLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2, vLightSpecular2);
|
|
|
+#endif
|
|
|
+#ifdef SHADOW2
|
|
|
+#ifdef SHADOWVSM2
|
|
|
+ shadow = computeShadowWithVSM(vPositionFromLight2, shadowSampler2);
|
|
|
+#else
|
|
|
+ shadow = computeShadow(vPositionFromLight2, shadowSampler2);
|
|
|
+#endif
|
|
|
+#else
|
|
|
+ shadow = 1.;
|
|
|
+#endif
|
|
|
+ diffuseBase += info[0] * shadow;
|
|
|
+ specularBase += info[1] * shadow;
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef LIGHT3
|
|
|
+#ifdef SPOTLIGHT3
|
|
|
+ info = computeSpotLighting(viewDirectionW, normalW, vLightData3, vLightDirection3, vLightDiffuse3, vLightSpecular3);
|
|
|
+#endif
|
|
|
+#ifdef HEMILIGHT3
|
|
|
+ info = computeHemisphericLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3, vLightSpecular3, vLightGround3);
|
|
|
+#endif
|
|
|
+#ifdef POINTDIRLIGHT3
|
|
|
+ info = computeLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3, vLightSpecular3);
|
|
|
+#endif
|
|
|
+#ifdef SHADOW3
|
|
|
+#ifdef SHADOWVSM3
|
|
|
+ shadow = computeShadowWithVSM(vPositionFromLight3, shadowSampler3);
|
|
|
+#else
|
|
|
+ shadow = computeShadow(vPositionFromLight3, shadowSampler3);
|
|
|
+#endif
|
|
|
+#else
|
|
|
+ shadow = 1.;
|
|
|
+#endif
|
|
|
+ diffuseBase += info[0] * shadow;
|
|
|
+ specularBase += info[1] * shadow;
|
|
|
+#endif
|
|
|
+
|
|
|
+ // Reflection
|
|
|
+ vec3 reflectionColor = vec3(0., 0., 0.);
|
|
|
+
|
|
|
+#ifdef REFLECTION
|
|
|
+ if (vReflectionInfos.z != 0.0)
|
|
|
+ {
|
|
|
+ reflectionColor = textureCube(reflectionCubeSampler, vReflectionUVW).rgb * vReflectionInfos.y;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ vec2 coords = vReflectionUVW.xy;
|
|
|
+
|
|
|
+ if (vReflectionInfos.x == MAP_PROJECTION)
|
|
|
+ {
|
|
|
+ coords /= vReflectionUVW.z;
|
|
|
+ }
|
|
|
+
|
|
|
+ coords.y = 1.0 - coords.y;
|
|
|
+
|
|
|
+ reflectionColor = texture2D(reflection2DSampler, coords).rgb * vReflectionInfos.y;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
+ // Alpha
|
|
|
+ float alpha = vDiffuseColor.a;
|
|
|
+
|
|
|
+#ifdef OPACITY
|
|
|
+ vec4 opacityMap = texture2D(opacitySampler, vOpacityUV);
|
|
|
+ opacityMap.rgb = opacityMap.rgb * vec3(0.3, 0.59, 0.11) * opacityMap.a;
|
|
|
+ alpha *= (opacityMap.x + opacityMap.y + opacityMap.z)* vOpacityInfos.y;
|
|
|
+#endif
|
|
|
+
|
|
|
+ // Emissive
|
|
|
+ vec3 emissiveColor = vEmissiveColor;
|
|
|
+#ifdef EMISSIVE
|
|
|
+ emissiveColor += texture2D(emissiveSampler, vEmissiveUV).rgb * vEmissiveInfos.y;
|
|
|
+#endif
|
|
|
+
|
|
|
+ // Specular map
|
|
|
+ vec3 specularColor = vSpecularColor.rgb;
|
|
|
+#ifdef SPECULAR
|
|
|
+ specularColor = texture2D(specularSampler, vSpecularUV).rgb * vSpecularInfos.y;
|
|
|
+#endif
|
|
|
+
|
|
|
+ // Composition
|
|
|
+ vec3 finalDiffuse = clamp(diffuseBase * diffuseColor + emissiveColor + vAmbientColor, 0.0, 1.0) * baseColor.rgb;
|
|
|
+ vec3 finalSpecular = specularBase * specularColor;
|
|
|
+
|
|
|
+ vec4 color = vec4(finalDiffuse * baseAmbientColor + finalSpecular + reflectionColor, alpha);
|
|
|
+
|
|
|
+#ifdef FOG
|
|
|
+ float fog = CalcFogFactor();
|
|
|
+ color.rgb = fog * color.rgb + (1.0 - fog) * vFogColor;
|
|
|
+#endif
|
|
|
+
|
|
|
+ gl_FragColor = color;
|
|
|
+}
|