precision mediump float;
// phong material
struct PhongMaterial
{
vec4 ambient; // Acm
vec4 diffuse; // Dcm
vec4 specular; // Scm
float shininess; // Srm
};
// uniforms
uniform PhongMaterial material;
uniform mat4 u_WorldViewProjection;
uniform sampler2D texture_01; // day and seasonal
uniform sampler2D texture_02; // night
uniform sampler2D texture_03; // clouds
uniform sampler2D texture_04; // specular
uniform sampler2D texture_05; // bump map
uniform int u_ShowClouds;
int u_LightOn = 1;
uniform vec3 u_LightPosition;
uniform vec3 u_LightDirection;
uniform vec3 u_LightIntensity;
vec3 u_LightColor = vec3(1.0, 1.0, 1.0);
uniform vec2 u_CloudShift;
uniform float u_CloudIntensity;
int u_ShowNight = 1;
vec3 ambientLight = vec3(0.4, 0.4, 0.4);
// in
varying vec3 v_Position;
varying vec3 v_Normal;
varying vec3 v_EyeDir;
varying vec2 v_TexCoords;
vec3 getDayNightColor(sampler2D day, sampler2D night, vec2 uv, float cosineAngleSunToNormal) {
vec3 dayColor = texture2D( day, uv ).rgb;
vec3 nightColor = texture2D( night, uv ).rgb;
// sharpen the edge beween the transition
cosineAngleSunToNormal = clamp( cosineAngleSunToNormal * 5.0, -1.0, 1.0);
// convert to 0 to 1 for mixing
float mixAmount = cosineAngleSunToNormal * 0.5 + 0.5;
// Select day or night texture based on mixAmount.
return mix( nightColor, dayColor, mixAmount );
}
// clouds
vec4 clouds(vec3 baseColor, sampler2D cloudTexture, vec2 uv, float intensity, float cosineAngleSunToNormal) {
// cloud map
float c = texture2D(cloudTexture, uv).r;
// sharpen the edge beween the transition
cosineAngleSunToNormal = clamp( cosineAngleSunToNormal * 5.0, -1.0, 1.0);
// convert to 0 to 1 for mixing
float mixAmount = cosineAngleSunToNormal * 0.5 + 0.2;
// mix intensity
c = pow(c,intensity);
// mixed cloud color
vec4 mixedColor = vec4((1.0-c) * baseColor + c * vec3(1,1,1),1.0);
return mix(vec4(baseColor,1.0),mixedColor, mixAmount);
}
/*
Calculate surface color based on Phong illumination model.
- pos: position of point on surface, in eye coordinates
- n: surface normal at pos
- v: direction pointing towards the viewer, in eye coordinates
+ assuming directional light
*/
vec3 phong(vec3 pos, vec3 n, vec3 v, PhongMaterial material) {
// ambient part
vec3 ambient = material.ambient.rgb * ambientLight;
// back face towards viewer?
float ndotv = dot(n,v);
if(ndotv<0.0)
return vec3(0,0,0);
// light enabled?
if(u_LightOn != 1)
return ambient + texture2D(texture_01, v_TexCoords).rgb;
// vector from light to current point
vec3 l = normalize(u_LightDirection);
// cos of angle between light and surface. 0 = light behind surface
float ndotl = dot(n,-l);
// diffuse contribution
vec3 diffuse;
// day night
if(u_ShowNight == 1)
// compute day and night contribution
diffuse = ambient + getDayNightColor(texture_01, texture_02, v_TexCoords, ndotl);
else {
// no light only ambient color
if(ndotl<=0.0)
return ambient;
// compute day contribution only
diffuse = texture2D(texture_01,v_TexCoords).rgb * u_LightColor * ndotl;
}
// clouds & night
if(u_ShowClouds == 1)
diffuse = clouds(diffuse, texture_03, mod(v_TexCoords+u_CloudShift,1.0), u_CloudIntensity, ndotl).rgb;
// reflected light direction = perfect reflection direction
vec3 r = reflect(l,n);
// angle between reflection dir and viewing dir
float rdotv = max( dot(r,v), 0.0);
// shininess
float shininess = material.shininess;
// specular contribution
vec3 ps = material.specular.rgb * u_LightColor * pow(rdotv,shininess);
// mix specular map with specular
vec3 specular = ps;
// return sum of all contributions
return ambient + diffuse + specular;
}
void main() {
// normalize normal after projection
vec3 normalEC = normalize(v_Normal);
// do we use a perspective or an orthogonal projection matrix?
bool usePerspective = u_WorldViewProjection[2][3] != 0.0;
// for perspective mode, the viewing direction (in eye coords) points
// from the vertex to the origin (0,0,0) --> use -ecPosition as direction.
// for orthogonal mode, the viewing direction is simply (0,0,1)
vec3 viewdirEC = usePerspective ? normalize(-v_Position.xyz) : vec3(0,0,1);
// calculate color using phong illumination
vec3 phongColor = phong( v_Position.xyz, normalEC, viewdirEC, material);
// set fragment color
gl_FragColor = vec4(phongColor,1.0);
}