#version 120 #define USE_LIGHTMAP #define MAX_LIGHTS_PER_OBJECT 4 varying vec4 Normal; varying vec3 WorldNormal; varying vec4 WorldPosition; varying vec4 ReflectionMapSamplingPos; varying vec4 ShadowMapSamplingPos; varying vec4 ShadowMapSamplingPos2; varying vec4 ShadowMapSamplingPos3; varying vec4 MVar; varying float testColor; varying float ClipDistance; // **************************************************************************** // Texture Samplers // **************************************************************************** uniform sampler2D diffuseSampler; uniform sampler2D NormalMapSampler; uniform sampler2D SpecularMapSampler; uniform sampler2D LightMapSampler; uniform sampler2D ShadowMapSampler; uniform sampler2D ShadowMapSampler2; uniform sampler2D ShadowMapSampler3; #ifdef USE_REFLECTION uniform sampler2D ReflectionMapSampler; #endif #ifdef USE_CAUSTICS uniform sampler2D CausticMapSampler; #endif // **************************************************************************** // Light Parameters // **************************************************************************** #ifndef MAX_LIGHTS_PER_OBJECT #define MAX_LIGHTS_PER_OBJECT 4 #endif #define LIGHT_OFFSET 5 #define LIGHT_COLOR 0 #define LIGHT_POSITION 1 #define LIGHT_DIRECTION 2 #define LIGHT_ATTENUATION 3 #define LIGHT_SPOT 4 uniform vec4 lights[MAX_LIGHTS_PER_OBJECT * LIGHT_OFFSET]; struct ColorInfo { vec4 mAmbientLightColor; vec4 mDiffuseBaseColor; vec3 mCameraPosition; float mAlphaOverride; float mSpecularPower; float mSpecularIntensity; }; uniform ColorInfo cinfo; uniform float dtnlLight; uniform vec3 dtnlLightDirection; uniform vec3 dtnlLightColor; uniform int iLightDirIni; uniform int iLightDirNum; uniform int iLightPointIni; uniform int iLightPointNum; uniform int iLightSpotIni; uniform int iLightSpotNum; // **************************************************************************** // Shadowmap Defines // **************************************************************************** #define SAMPLES_COUNT 4 #define INV_SAMPLES_COUNT (1.0 / float(SAMPLES_COUNT)) uniform bool mLightingEnabled;// = true; uniform bool mShadowsEnabled;// = true; uniform vec3 mSplitDistance; // **************************************************************************** // Material Parameters // **************************************************************************** #define DIFFUSE_TEX_ENABLED 0 #define NORMAL_TEX_ENABLED 1 #define SPECULAR_TEX_ENABLED 2 #define RIM_SHADING_ENABLED 3 uniform bool material[4]; uniform vec4 mHighlightColor; // **************************************************************************** // Calculates phong shading for a single light // **************************************************************************** vec3 CalculateSingleLight( in vec4 lightColor, in vec4 lightPosition, in vec4 lightDirection, in vec4 lightAttenuation, in vec4 lightSpot, in vec4 worldPosition, in vec3 worldNormal, in vec3 directionToCamera, in vec3 diffuseColor, in vec3 specularColor) { vec3 lightVector = lightPosition.xyz - worldPosition.xyz; float lightDist = length(lightVector); vec3 directionToLight = normalize(lightVector); // Calculate the intensity of the light with exponential falloff float baseIntensity = pow( clamp((lightSpot.w - lightDist) / lightSpot.w, 0.0 ,1.0), lightSpot.z); float diffuseIntensity = clamp( max(0.0, dot(directionToLight, worldNormal)), 0.0, 1.0); float fAttenSpot = 1.0 / (lightAttenuation.x + lightAttenuation.y*lightDist + lightAttenuation.z*lightDist*lightDist); float d2 = sqrt(diffuseIntensity); float ramp = ((1.0 - d2) * 0.5) + (d2); vec3 diffuse = ramp * lightColor.xyz * diffuseColor * fAttenSpot; if (cinfo.mSpecularIntensity > 0.0) { vec3 H = normalize(directionToLight + directionToCamera); //half vector float rDotV = max(0.0, dot(H, worldNormal)); vec3 specular = cinfo.mSpecularIntensity * specularColor * pow(rDotV, cinfo.mSpecularPower); specular *= baseIntensity; diffuse += specular; } return max(baseIntensity, 0.0) * diffuse; } vec3 CalculateSingleSpotlight( in vec4 lightColor, in vec4 lightPosition, in vec4 lightDirection, in vec4 lightAttenuation, in vec4 lightSpot, in vec4 worldPosition, in vec3 worldNormal, in vec3 diffuseColor, in vec3 specularColor) { vec3 L = normalize(lightPosition.xyz - worldPosition.xyz); vec3 V = -normalize(worldPosition.xyz); //viewer vec3 Color = vec3(0.0); vec3 ColorSpec = vec3(0.0); float NdotL = dot(worldNormal, L); float fAttenSpot = 1.0; if(NdotL >= 0.0) { //compute diffuse color Color += NdotL * lightColor.rgb * diffuseColor; //add specular component if(cinfo.mSpecularIntensity > 0.0) { vec3 H = normalize(L + V); //half vector ColorSpec = pow(max(0.0, dot(H, worldNormal)), cinfo.mSpecularIntensity) * specularColor; } float LD = length(lightPosition.xyz - worldPosition.xyz); if(LD > lightSpot.w) { fAttenSpot = 0.0; } else { fAttenSpot *= 1.0 /(lightAttenuation.x + lightAttenuation.y*LD + lightAttenuation.z*LD*LD); } //spot cone computation vec3 L2 = -lightDirection.xyz; float rho = dot(L, L2); fAttenSpot *= pow(clamp((rho - lightSpot.y)/(lightSpot.x - lightSpot.y), 0.0, 1.0), lightSpot.z); Color *= fAttenSpot; ColorSpec *= fAttenSpot; } Color += ColorSpec; return Color; } vec3 CalculateDirectionalLight( in vec4 lightColor, in vec4 lightPosition, in vec4 lightDirection, in vec4 lightAttenuation, in vec4 lightSpot, in vec4 worldPosition, in vec3 worldNormal, in vec3 directionToCamera, in vec3 diffuseColor, in vec3 specularColor) { vec3 L = lightDirection.xyz; vec3 V = directionToCamera; float NdotL = dot(worldNormal, -L); vec3 Color = vec3(0.0); vec3 ColorSpec = vec3(0.0); if(NdotL >= 0.0) { //compute diffuse color Color += NdotL * diffuseColor * lightColor.rgb; //add specular component if(cinfo.mSpecularIntensity > 0.0) { vec3 H = normalize(L + V); ColorSpec = cinfo.mSpecularIntensity * specularColor * pow(max(0.0, dot(H, worldNormal)), cinfo.mSpecularPower); } } Color += ColorSpec; return Color; } // **************************************************************************** // Reflection // **************************************************************************** void CalculatePlanarReflectionColor(inout vec4 color, in vec4 reflectPos) { #ifdef USE_REFLECTION vec2 ProjectedReflectionTexCoords = clamp(reflectPos.xy / reflectPos.z, 0.0, 1.0); vec4 reflectiveColor = texture2D(ReflectionMapSampler, ProjectedReflectionTexCoords); const float mReflectionStrength = 1.0; color.rgb = (color.rgb * (1.0 - mReflectionStrength)) + (reflectiveColor * mReflectionStrength).rgb; #endif } // **************************************************************************** // Shadow Lookup // **************************************************************************** float calcShadow(in vec2 texCoords, in vec2 offset, in float RealDist, sampler2D shadowSampler) { vec4 shadTexCol = texture2D(shadowSampler, texCoords + offset);//, 0.0); float extractedDistance = shadTexCol.r; return (extractedDistance <= RealDist ? 1.0 : 0.0); } void main() { #ifdef USE_HD4000_OSX mat4 spots; spots[0] = lights[iLightPointIni * LIGHT_OFFSET + LIGHT_SPOT]; spots[1] = lights[int(clamp(float(iLightPointIni)+1.0, 0.0, 3.0)) * LIGHT_OFFSET + LIGHT_SPOT]; spots[2] = lights[int(clamp(float(iLightPointIni)+2.0, 0.0, 3.0)) * LIGHT_OFFSET + LIGHT_SPOT]; spots[3] = lights[int(clamp(float(iLightPointIni)+3.0, 0.0, 3.0)) * LIGHT_OFFSET + LIGHT_SPOT]; #endif if (ClipDistance < 0.0) discard; vec4 mFogColor = vec4(1.0); float mFogStart = 0.0; float mFogEnd = 1000.0; // ************************************************************************* // Set the diffuse and specular colors // ************************************************************************* vec4 diffuseColor = cinfo.mDiffuseBaseColor; vec4 specularColor = vec4(1.0); vec3 directionToCamera = cinfo.mCameraPosition - WorldPosition.xyz; float distanceToCamera = length(directionToCamera); directionToCamera = normalize(directionToCamera); if(material[DIFFUSE_TEX_ENABLED]) { diffuseColor *= texture2D(diffuseSampler, gl_TexCoord[0].xy); #ifdef USE_LIGHTMAP diffuseColor *= texture2D(NormalMapSampler, gl_TexCoord[1].xy); #endif } if (!mLightingEnabled) { diffuseColor.a *= cinfo.mAlphaOverride; gl_FragColor = diffuseColor; return; } if(material[SPECULAR_TEX_ENABLED]) { specularColor *= texture2D(SpecularMapSampler, gl_TexCoord[0].xy); } // ************************************************************************* // Get the normal from the normal map // ************************************************************************* vec3 normalFromMap = WorldNormal; #ifndef USE_LIGHTMAP #ifndef USE_SKINNING if (material[NORMAL_TEX_ENABLED]) { vec3 normalLookup = texture2D(NormalMapSampler, gl_TexCoord[0].xy).xyz; normalLookup -= vec3(0.5, 0.5, 0.5); normalLookup *= 2.0; normalFromMap = WorldNormal * normalLookup; } #endif #endif normalFromMap = normalize(normalFromMap); // ************************************************************************* // Calculate the directional light // ************************************************************************* // Create the default color base as ambient + directional light. vec4 color = cinfo.mAmbientLightColor * diffuseColor; // ************************************************************************* // Calculate the reflection // ************************************************************************* #ifdef USE_REFLECTION CalculatePlanarReflectionColor(color, ReflectionMapSamplingPos); #endif // ************************************************************************* // Calculate the point lights // ************************************************************************* for(int i = 0; i < iLightDirNum; i++) { int j = (i+iLightDirIni) * LIGHT_OFFSET; color.rgb += CalculateDirectionalLight( lights[j + LIGHT_COLOR], lights[j + LIGHT_POSITION], lights[j + LIGHT_DIRECTION], lights[j + LIGHT_ATTENUATION], lights[j + LIGHT_SPOT], WorldPosition, normalFromMap, directionToCamera, diffuseColor.rgb, specularColor.rgb * lights[j + LIGHT_COLOR].rgb ); } for(int i = 0; i < iLightSpotNum; i++) { int j = (i+iLightSpotIni) * LIGHT_OFFSET; color.rgb += CalculateSingleSpotlight( lights[j + LIGHT_COLOR], lights[j + LIGHT_POSITION], lights[j + LIGHT_DIRECTION], lights[j + LIGHT_ATTENUATION], lights[j + LIGHT_SPOT], WorldPosition, normalFromMap, diffuseColor.rgb, specularColor.rgb * lights[j + LIGHT_COLOR].rgb ); } for(int i = 0; i < iLightPointNum; i++) { int j = (i+iLightPointIni) * LIGHT_OFFSET; color.rgb += CalculateSingleLight( lights[j + LIGHT_COLOR], lights[j + LIGHT_POSITION], lights[j + LIGHT_DIRECTION], lights[j + LIGHT_ATTENUATION], #ifdef USE_HD4000_OSX spots[i], #else lights[j + LIGHT_SPOT], #endif WorldPosition, normalFromMap, directionToCamera, diffuseColor.rgb, specularColor.rgb * lights[j + LIGHT_COLOR].rgb ); } // ************************************************************************* // Calculate additional object highlight // ************************************************************************* #ifdef USE_HIGHLIGHT vec3 fadeColor = mix(color.rgb, mHighlightColor.rgb, mHighlightColor.a); color = mix(vec4(fadeColor, 1.0), color, min(1.0, dot(directionToCamera, normalFromMap) * 2.0)); color.rgb += (mHighlightColor.rgb * vec3(0.2, 0.2, 0.2)); #endif if (material[RIM_SHADING_ENABLED]) { const float Rim_Start = 0.7; const float Rim_End = 1.0; const float Rim_Multiplier = 0.6; const vec3 Rim_Color = vec3(1.0,0.9,0.9); float rim = smoothstep(Rim_Start , Rim_End , 1.0 - dot(normalFromMap, directionToCamera)); rim *= smoothstep(Rim_Start, Rim_End, 1.0 - dot(normalFromMap,vec3(0.0, -1.0, 0.0))); color.rgb += rim * Rim_Multiplier * Rim_Color * (color.rgb * 0.5 + vec3(0.5, 0.5, 0.5)); } #ifdef USE_OCTODAD vec3 octoHighlight = texture2D(LightMapSampler, vec2(gl_TexCoord[0].x, -gl_TexCoord[0].y)).xyz; vec3 mHighlightColor = mix(vec3(1.0), vec3(0.1), clamp( dot(directionToCamera, normalFromMap), 0.0 ,1.0)); color.rgb += octoHighlight * mHighlightColor; #endif // ************************************************************************* // Shadow Color Calculation // ************************************************************************* float lightFactor = 1.0; if (mShadowsEnabled) { vec2 SMPos = ShadowMapSamplingPos.xy / ShadowMapSamplingPos.w + vec2(0.5, 0.5); vec2 clampedSMPos = clamp(SMPos.xy, vec2(0.001, 0.001), vec2(0.99, 0.99)); vec2 SMPos2 = ShadowMapSamplingPos2.xy / ShadowMapSamplingPos2.w + vec2(0.5, 0.5); vec2 clampedSMPos2 = clamp(SMPos2.xy, vec2(0.001, 0.001), vec2(0.99, 0.99)); vec2 SMPos3 = ShadowMapSamplingPos3.xy / ShadowMapSamplingPos3.w + vec2(0.5, 0.5); vec2 clampedSMPos3 = clamp(SMPos3.xy, vec2(0.001, 0.001), vec2(0.99, 0.99)); float Distance = MVar[0]; #ifndef USE_SKINNING float bias = 0.03 * min(0.01 + 1.0 - abs(dot(normalize(normalFromMap), vec3(0.0,1.0,0.0))), 1.0); #else float bias = 0.003; #endif if(Distance < mSplitDistance.x && clampedSMPos.x == SMPos.x && clampedSMPos.y == SMPos.y && ShadowMapSamplingPos.z > 0.0 && ShadowMapSamplingPos.z < MVar.z) { float realDistance = ShadowMapSamplingPos.z / MVar.z - bias; float shadowAmount = 0.0; shadowAmount += calcShadow(SMPos.xy, vec2(0.5 * MVar.w), realDistance, ShadowMapSampler); shadowAmount += calcShadow(SMPos.xy, vec2(-0.5 * MVar.w), realDistance, ShadowMapSampler); shadowAmount += calcShadow(SMPos.xy, vec2(1.5 * MVar.w), realDistance, ShadowMapSampler); shadowAmount += calcShadow(SMPos.xy, vec2(-1.5 * MVar.w), realDistance, ShadowMapSampler); lightFactor -= shadowAmount * INV_SAMPLES_COUNT; //color.rgb = vec3(0.0,0.0, 1.0); } else if(Distance < mSplitDistance.y && clampedSMPos2.x == SMPos2.x && clampedSMPos2.y == SMPos2.y && ShadowMapSamplingPos2.z > 0.0 && ShadowMapSamplingPos2.z < MVar.z) { float realDistance = ShadowMapSamplingPos2.z / MVar.z - bias; //realDistance *= min(0.5 + abs(dot(normalFromMap, vec3(0.0,1.0,0.0))), 1.0); float shadowAmount = 0.0; shadowAmount += calcShadow(SMPos2.xy, vec2(0.5 * MVar.w), realDistance, ShadowMapSampler2); shadowAmount += calcShadow(SMPos2.xy, vec2(-0.5 * MVar.w), realDistance, ShadowMapSampler2); shadowAmount += calcShadow(SMPos2.xy, vec2(1.5 * MVar.w), realDistance, ShadowMapSampler2); shadowAmount += calcShadow(SMPos2.xy, vec2(-1.5 * MVar.w), realDistance, ShadowMapSampler2); lightFactor -= shadowAmount * INV_SAMPLES_COUNT; //color.rgb = vec3(0.0,1.0, 0.0); } else if(Distance < mSplitDistance.z && clampedSMPos3.x == SMPos3.x && clampedSMPos3.y == SMPos3.y && ShadowMapSamplingPos3.z > 0.0 && ShadowMapSamplingPos3.z < MVar.z) { float realDistance = ShadowMapSamplingPos3.z / MVar.z - bias; float shadowAmount = 0.0; shadowAmount += calcShadow(SMPos3.xy, vec2(0.0, 0.0), realDistance, ShadowMapSampler3); lightFactor -= shadowAmount; //color.rgb = vec3(1.0,0.0, 0.0); } } color.rgb *= 0.75 + (0.25 * lightFactor * MVar.y); #ifdef USE_OCTOTRANS if (cinfo.mAlphaOverride > 0.0 && cinfo.mAlphaOverride < 1.0) { float alpha = color.a; color.a = mix(0.0, 1.0, 0.5 + dot(normalFromMap, -directionToCamera)); color.a = clamp(color.a, 0.0, 1.0); color.a += cinfo.mAlphaOverride; color.a += (alpha - 0.01); } #else color.a *= cinfo.mAlphaOverride; #endif /* #ifdef USE_CAUSTICS color.rgb += tex2D(CausticMapSampler, input.CausticTexCoords ).rgb * 0.25; #endif*/ // Fog calculation float d = distanceToCamera; float l = clamp((d-mFogStart)/(mFogEnd-mFogStart), 0.0, 1.0); gl_FragColor = color;//mix(color, mFogColor, l);;//vec4(normalize(lightPositions[0].xyz), 1.0); }