205 lines
7.0 KiB
Plaintext
205 lines
7.0 KiB
Plaintext
#version 120
|
|
const int nLightCount = 2;
|
|
|
|
//Amount of population considered 'half full'
|
|
const float basePopulation = 7.0;
|
|
|
|
const float distortDist = 4.0 / 2048.0;
|
|
const float distortScale = 128.0;
|
|
|
|
const float mergeNoise = 2.0;
|
|
const float mergeScale = 2.0;
|
|
const float mergeA = 5.0, mergeB = 7.0;
|
|
const float extremeness = 1.8;
|
|
|
|
const float baseSpec = 0.5;
|
|
|
|
uniform sampler2D surfaces[3], cities, masks, diffNoise;
|
|
uniform float population, time[2];
|
|
|
|
varying vec3 normal, binormal, tangent;
|
|
varying vec3 npos, vertPaint, origo;
|
|
varying vec2 uv;
|
|
|
|
vec3 light[nLightCount];
|
|
float dist[nLightCount];
|
|
|
|
vec2 nightLights(vec3 incidentLight, float devLevel) {
|
|
float brightness = clamp(max(incidentLight.r, max(incidentLight.g, incidentLight.b)) * 0.9, 0.0, 1.0);
|
|
brightness /= 0.4;
|
|
|
|
float popDensity = population / (population + basePopulation);
|
|
float city = texture2D(cities, uv).r;
|
|
float buildup = clamp((popDensity - (1.0 - devLevel)) * 2.0, 0.0, 1.0);
|
|
|
|
float lightFactor = sqrt(max(popDensity, 0.4));
|
|
|
|
return vec2(lightFactor * max(1.0 - brightness, 0.0) * buildup, max(buildup - 0.5, 0.0) * 2.0) * city;
|
|
}
|
|
|
|
|
|
float hash2D(vec2 n) {
|
|
return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453);
|
|
}
|
|
|
|
float hash3D(float n ) {
|
|
return fract(sin(n)*753.5453123);
|
|
}
|
|
|
|
float noise2D(vec2 n) {
|
|
const vec2 d = vec2(0.0, 1.0);
|
|
vec2 b = floor(n), f = smoothstep(vec2(0.0), vec2(1.0), fract(n));
|
|
return mix(mix(hash2D(b), hash2D(b + d.yx), f.x), mix(hash2D(b + d.xy), hash2D(b + d.yy), f.x), f.y);
|
|
}
|
|
|
|
float noise3D(vec3 x )
|
|
{
|
|
vec3 p = floor(x);
|
|
vec3 f = fract(x);
|
|
f = f*f*(3.0-2.0*f);
|
|
|
|
float n = p.x + p.y*157.0 + 113.0*p.z;
|
|
return mix(mix(mix( hash3D(n+ 0.0), hash3D(n+ 1.0),f.x),
|
|
mix( hash3D(n+157.0), hash3D(n+158.0),f.x),f.y),
|
|
mix(mix( hash3D(n+113.0), hash3D(n+114.0),f.x),
|
|
mix( hash3D(n+270.0), hash3D(n+271.0),f.x),f.y),f.z);
|
|
}
|
|
|
|
float fbm3D(vec3 n) {
|
|
float total = 0.0, amplitude = 1.0;
|
|
for (int i = 0; i < 5; i++) {
|
|
total += noise3D(n) * amplitude;
|
|
n += n;
|
|
amplitude *= 0.5;
|
|
}
|
|
return total;
|
|
}
|
|
|
|
float fbm2D(vec2 n) {
|
|
float total = 0.0, amplitude = 1.0;
|
|
for (int i = 0; i < 5; i++) {
|
|
total += noise2D(n) * amplitude;
|
|
n += n;
|
|
amplitude *= 0.5;
|
|
}
|
|
return total;
|
|
}
|
|
|
|
float extremify(float x, float treme) {
|
|
if(x < 0.5)
|
|
x = pow(x, treme);
|
|
else
|
|
x = 1.0 - pow(1.0 - x, treme);
|
|
return x;
|
|
}
|
|
|
|
void main() {
|
|
vec3 color = gl_FrontMaterial.diffuse.rgb;
|
|
|
|
vec2 mask = texture2D(masks, uv).rg;
|
|
float distort = mask.r;
|
|
vec2 lookup = uv;
|
|
lookup.x *= 36.0;
|
|
|
|
mask = texture2D(masks, lookup).rg;
|
|
|
|
vec2 noise = texture2D(diffNoise, uv * distortScale).rg;
|
|
lookup += distort * (noise - vec2(0.5)) * distortDist * vec2(1.0,0.5);
|
|
|
|
vec3 surfA = texture2D(surfaces[0], lookup).rgb;
|
|
vec3 surfB = texture2D(surfaces[1], lookup).rgb;
|
|
vec3 surfC = texture2D(surfaces[2], lookup).rgb;
|
|
|
|
float surf = lookup.x + (texture2D(diffNoise, lookup * mergeScale).b * mergeNoise - mergeNoise/2.0);
|
|
surf = mod(surf, mergeA) / mergeA;
|
|
surf = extremify(abs(surf - 0.5) * 2.0, extremeness);
|
|
float surf2 = lookup.x + (texture2D(diffNoise, lookup * mergeScale).b * mergeNoise - mergeNoise/2.0);
|
|
surf2 = mod(surf2, mergeB) / mergeB;
|
|
surf2 = extremify(abs(surf2 - 0.5) * 2.0, extremeness);
|
|
|
|
vec3 diffuseSamp = mix(surfA, surfB, surf);
|
|
diffuseSamp = mix(diffuseSamp, surfC, surf2);
|
|
|
|
float gloss = 0.5;
|
|
float shininess = gl_FrontMaterial.shininess * (gloss + baseSpec);
|
|
|
|
vec3 n = normalize(normal);
|
|
vec3 v = normalize(npos);
|
|
|
|
if(nLightCount > 0) {
|
|
const int i = 0;
|
|
light[i] = gl_LightSource[i].position.xyz + npos;
|
|
dist[i] = length(light[i]);
|
|
light[i] = light[i] / dist[i];
|
|
}
|
|
if(nLightCount > 1) {
|
|
const int i = 1;
|
|
light[i] = gl_LightSource[i].position.xyz + npos;
|
|
dist[i] = length(light[i]);
|
|
light[i] = light[i] / dist[i];
|
|
}
|
|
|
|
vec3 ambient = gl_LightModel.ambient.rgb * gl_FrontMaterial.ambient.rgb;
|
|
vec3 diffuse = vec3(0.0);
|
|
vec3 specular = vec3(0.0);
|
|
|
|
float shadow = abs(mod(uv.x + time[0] + 0.0, 1.0/8.0) * 8.0 - 0.5) * 2.0;
|
|
shadow = smoothstep(0.7,0.8, shadow);
|
|
|
|
if(nLightCount > 0) {
|
|
const int i = 0;
|
|
float falloff = 1.0 / (1.0 + (gl_LightSource[i].quadraticAttenuation * dist[i] * dist[i]));
|
|
float intensity = max(0.0, dot(n, light[i])) * falloff * (1.0 - shadow * 0.9);
|
|
|
|
diffuse += gl_LightSource[i].diffuse.rgb * intensity;
|
|
|
|
vec3 r = -reflect(light[i], n);
|
|
specular += gl_LightSource[i].specular.rgb * (pow(max(0.0, dot(r, v)), shininess) * intensity);
|
|
}
|
|
if(nLightCount > 1) {
|
|
const int i = 1;
|
|
float falloff = 1.0 / (1.0 + (gl_LightSource[i].quadraticAttenuation * dist[i] * dist[i]));
|
|
float intensity = max(0.0, dot(n, light[i])) * falloff * (1.0 - shadow * 0.9);
|
|
|
|
diffuse += gl_LightSource[i].diffuse.rgb * intensity;
|
|
|
|
vec3 r = -reflect(light[i], n);
|
|
specular += gl_LightSource[i].specular.rgb * (pow(max(0.0, dot(r, v)), shininess) * intensity);
|
|
}
|
|
specular *= gl_FrontMaterial.specular.rgb * (0.5 + gloss - 0.5);
|
|
|
|
vec2 cityState = nightLights(diffuse, mask.g);
|
|
/*
|
|
float turbulence = noise2D(vec2(uv.x * 100.0 -time * 15.0, uv.y * 6.0));
|
|
color = ((diffuse + ambient) * color * mix(diffuseSamp.rgb, vec3(0.5), cityState.y)) + specular + cityState.x * vec3(1.0,0.9,0.55);
|
|
float clouds = max(0.0, fbm2D(vec2(uv.x * 125.0 + time * 17.0, uv.y * 5.0 + time * 1.0) + turbulence) * (fbm2D(vec2(uv.x*400 - time * 16.0, uv.y * 18.0 - time * 6.0)) * 0.5 + 0.5) - 0.75);
|
|
clouds *= min(1.0, uv.x * (1.0 - uv.x) * 25.0);
|
|
vec3 atmosphere = pow((1.0 - dot(v, n)), 4.0) * vec3(0.5,0.75,1.0) * vertPaint.r * 2.0;
|
|
shadow = (1.0 - shadow * 0.8);
|
|
|
|
|
|
|
|
|
|
|
|
gl_FragColor.rgb = mix(atmosphere + clouds, mix(color, color * 0.25, clouds), vertPaint.r);// * gl_LightSource[0].diffuse.rgb;
|
|
gl_FragColor.a = mix(min(1.0, clouds + atmosphere.r), 1.0, vertPaint.r);
|
|
*/
|
|
|
|
|
|
float clearSky = clamp(abs(mod(uv.x * 5.0 + 0.5, 1.0) * 2.0 - 1.0) * 3.0 - 0.1, 0.0, 1.0);
|
|
float turbulence = noise2D(vec2(uv.x * 300.0 -time[1] * 50.0, uv.y * 25.0)) * (1.0 - clearSky * 0.8);
|
|
color = ((diffuse + ambient) * color * mix(diffuseSamp.rgb, vec3(0.5), cityState.y)) + specular + cityState.x * vec3(1.0,0.9,0.55);
|
|
float clouds = min(1.0, (1.0 - max(0.0, fbm2D(vec2(uv.x * 125.0 + time[1] * 25, uv.y * 5.0 + time[1] * 5.0) + turbulence))) * 2.0);// * (fbm2D(vec2(uv.x*400 - time[1] * 16.0, uv.y * 18.0 - time[1] * 6.0)) * 0.5 + 0.5) - 0.75);
|
|
|
|
// calculate a mask that makes clear skies over deserts and hides the UV seam that generates bad noise.
|
|
clouds *= clearSky;
|
|
|
|
//<0.5,0.7,1.0> <1.0,0.5,0.1>
|
|
vec3 atmosphere = pow((1.0 - dot(v, n)), 2.0) * (mix(vec3(0.5,0.7,1.0), vec3(1.0,0.5,0.1), shadow) * (1.0 - pow(shadow, 2.0))) * (1.0 - vertPaint.r) * 2.0;
|
|
shadow = (1.0 - shadow * 0.75);
|
|
|
|
gl_FragColor.rgb = mix(mix(atmosphere, gl_LightSource[0].diffuse.rgb, clouds) * shadow, mix(color, color * 0.75, clouds), vertPaint.r);
|
|
gl_FragColor.a = mix(min(1.0, clouds + atmosphere.r * shadow), 1.0, vertPaint.r);
|
|
|
|
}
|