Files
starruler-linux/data/shaders/source/ringworld_ps.txt
T
2018-07-17 14:15:37 +02:00

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);
}