armory/raw/compositor_pass/compositor_pass.frag.glsl
2016-05-06 11:13:46 +02:00

350 lines
12 KiB
GLSL

#version 450
#ifdef GL_ES
precision highp float;
#endif
uniform sampler2D tex;
uniform sampler2D gbuffer0;
uniform sampler2D gbuffer1;
uniform sampler2D noise256;
//#ifdef (_LensFlare || _Fog)
// #ifdef _Fog
uniform vec3 eye;
uniform vec3 eyeLook;
// #endif
#ifdef _LensFlare
uniform vec3 light;
uniform mat4 VP;
#endif
uniform float time;
in vec2 texCoord;
const float PI = 3.1415926535;
const float fishEyeStrength = -0.01;
const vec2 m = vec2(0.5, 0.5);
const float focus_depth = 0.5;
const float vignout = 1.8; // vignetting outer border
const float vignin = 0.0; // vignetting inner border
const float vignfade = 90.0; // f-stops till vignete fades
const float fstop = 20; // f-stop value
const float aspectRatio = 800.0 / 600.0;
const vec3 fogColor = vec3(0.5, 0.6, 0.7);
// const float b = 0.01;
// const float c = 0.1;
const float b = 1.0;
const float c = 1.0;
vec3 applyFog(vec3 rgb, // original color of the pixel
float distance, // camera to point distance
vec3 rayOri, // camera position
vec3 rayDir) { // camera to point vector
float fogAmount = c * exp(-rayOri.y * b) * (1.0 - exp(-distance * rayDir.y * b)) / rayDir.y;
return mix(rgb, fogColor, fogAmount);
}
// vec3 applyFog(vec3 rgb, // original color of the pixel
// float distance) { // camera to point distance
// float fogAmount = 1.0 - exp(-distance * b);
// return mix(rgb, fogColor, fogAmount);
// }
// https://www.shadertoy.com/view/ltfGzn
float unitSin(float t) {
return 0.5 + 0.5 * sin(t);
}
float processFlake(vec3 rayOrigin, vec3 rayDirection, float b, float a2, float a4, float bbSubAC4, float fallSpeed, float r) {
float sum = 0.0;
float R = r + sin(PI * r * time * 0.05) / (r * 0.25);
float delta = bbSubAC4 + a4 * R*R;
float depth = 100.0;
if (delta >= 0.0) {
float t1 = (-b - sqrt(delta))/a2;
float t2 = (-b + sqrt(delta))/a2;
vec3 p1 = rayOrigin + t1 * rayDirection;
vec3 p2 = rayOrigin + t2 * rayDirection;
if (t1 < depth && t1 > 2.0) {
float teta = atan(p1.z, p1.x) / (2.0 * PI);
float fall = (0.5 + 0.5 * unitSin(r)) * fallSpeed * time + cos(r);
float s = 6.0;
s *= smoothstep(0.65, 1.0, texture(noise256, vec2(0.4 * teta * r, 0.1 * p1.y + fall)).r);
s *= smoothstep(0.65, 1.0, texture(noise256, vec2(0.11 * p1.y + fall, -0.4 * teta * r)).r);
s *= smoothstep(0.65, 1.0, texture(noise256, vec2(-(0.11 * p1.y + fall), 0.4 * teta * r)).r);
sum += s;
}
if (t2 < depth && t2 > 0.0) {
float teta = atan(p2.z, p2.x) / (2.0 * PI);
float fall = (0.5 + 0.5 * unitSin(r)) * fallSpeed * time + cos(r);
float s = 6.0;
s *= smoothstep(0.65, 1.0, texture(noise256, vec2(0.4 * teta * r, 0.1 * p2.y + fall)).r);
s *= smoothstep(0.65, 1.0, texture(noise256, vec2(-(0.11 * p2.y + fall), 0.4 * teta * r)).r);
s *= smoothstep(0.65, 1.0, texture(noise256, vec2(0.11 * p2.y + fall, -0.4 * teta * r)).r);
sum += s;
}
}
return sum;
}
float flakeVolume() {
vec3 rayOrigin = eye;
vec2 p = texCoord.xy * 2.0 - 1.0;
vec3 rayDirection = normalize(p.x * vec3(1.0,0.0,0.0) + p.y * vec3(0.0,0.0,1.0) + 1.0 * eyeLook);
float sum = 0.0;
float fallSpeed = 0.2;
float a = pow(rayDirection.x, 2.0) + pow(rayDirection.z, 2.0);
float b = 2.0 * (rayDirection.x * rayOrigin.x + rayDirection.z * rayOrigin.z);
float c = pow(rayOrigin.x, 2.0) + pow(rayOrigin.z, 2.0);
float ac4 = 4.0 * a*c;
float a4 = 4.0 * a;
float a2 = 2.0 * a;
float bb = b*b;
float bbSubAC4 = bb - ac4;
// for (float r = 1.0; r <= 16.0; r+=0.5) {
processFlake(rayOrigin, rayDirection, b, a2, a4, bbSubAC4, fallSpeed, 1.0);
processFlake(rayOrigin, rayDirection, b, a2, a4, bbSubAC4, fallSpeed, 2.0);
processFlake(rayOrigin, rayDirection, b, a2, a4, bbSubAC4, fallSpeed, 3.0);
processFlake(rayOrigin, rayDirection, b, a2, a4, bbSubAC4, fallSpeed, 4.0);
processFlake(rayOrigin, rayDirection, b, a2, a4, bbSubAC4, fallSpeed, 5.0);
processFlake(rayOrigin, rayDirection, b, a2, a4, bbSubAC4, fallSpeed, 6.0);
processFlake(rayOrigin, rayDirection, b, a2, a4, bbSubAC4, fallSpeed, 7.0);
processFlake(rayOrigin, rayDirection, b, a2, a4, bbSubAC4, fallSpeed, 8.0);
processFlake(rayOrigin, rayDirection, b, a2, a4, bbSubAC4, fallSpeed, 9.0);
processFlake(rayOrigin, rayDirection, b, a2, a4, bbSubAC4, fallSpeed, 10.0);
// }
return sum / 2.0;
}
vec4 screenSpaceSnow() {
float flake = flakeVolume();
return vec4(1.0, 1.0, 1.0, clamp(flake, 0.0, 1.0));
}
vec4 screenSpaceIce(vec3 c) {
vec2 p = texCoord.xy * 2.0 - 1.0;
vec2 P = vec2(p.x, 2.0 * p.y);
float r = length(P);
return vec4(c.rgb, 0.3 * (pow((abs(p.x) + abs(p.y)) * 0.5, 1.0) + pow(r / 1.6, 2.0)));
}
// https://www.shadertoy.com/view/XdSGDc
// float processRain(float dis) {
// vec2 q = texCoord;
// float f = pow(dis, 0.45)+0.25;
// vec2 st = f * (q * vec2(1.5, .05)+vec2(-time*.1+q.y*.5, time*.12));
// f = (texture(noise256, st * .5, -99.0).x + texture(noise256, st*.284, -99.0).y);
// f = clamp(pow(abs(f)*.5, 29.0) * 140.0, 0.00, q.y*.4+.05);
// return f*0.5;
// }
// vec3 screenSpaceRain() {
// float dis = 1.0;
// vec3 col = vec3(0.0);
// // for (int i = 0; i < 12; i++) {
// col += processRain(dis); dis += 3.5;
// col += processRain(dis); dis += 3.5;
// col += processRain(dis); dis += 3.5;
// col += processRain(dis); dis += 3.5;
// col += processRain(dis); dis += 3.5;
// col += processRain(dis); dis += 3.5;
// col += processRain(dis); dis += 3.5;
// col += processRain(dis); dis += 3.5;
// col += processRain(dis); dis += 3.5;
// col += processRain(dis); dis += 3.5;
// // }
// return col;
// }
// https://www.shadertoy.com/view/4dXSzB
vec3 screenSpaceCameraRain() {
vec3 raintex = texture(noise256,vec2(texCoord.x*2.0,texCoord.y*0.4+time*0.1)).rgb/30.0;
vec2 where = (texCoord.xy-raintex.xy);
return texture(tex,vec2(where.x,where.y)).rgb;
}
float vignette() {
float dist = distance(texCoord, vec2(0.5,0.5));
dist = smoothstep(vignout + (fstop / vignfade), vignin + (fstop / vignfade), dist);
return clamp(dist, 0.0, 1.0);
}
vec4 sampleBox(float size) {
vec4 color = vec4(0.0, 0.0, 0.0, 0.0);
color += texture(tex, vec2(texCoord.x - size, texCoord.y - size)) * 0.075;
color += texture(tex, vec2(texCoord.x, texCoord.y - size)) * 0.1;
color += texture(tex, vec2(texCoord.x + size, texCoord.y - size)) * 0.075;
color += texture(tex, vec2(texCoord.x - size, texCoord.y)) * 0.1;
color += texture(tex, vec2(texCoord.x, texCoord.y)) * 0.30;
color += texture(tex, vec2(texCoord.x + size, texCoord.y)) * 0.1;
color += texture(tex, vec2(texCoord.x - size, texCoord.y + size)) * 0.075;
color += texture(tex, vec2(texCoord.x, texCoord.y + size)) * 0.1;
color += texture(tex, vec2(texCoord.x + size, texCoord.y + size)) * 0.075;
return color;
}
float linearize(float depth, float znear, float zfar) {
return -zfar * znear / (depth * (zfar - znear) - zfar);
}
// Based on lense flare implementation by musk
// https://www.shadertoy.com/view/4sX3Rs
vec3 lensflare(vec2 uv, vec2 pos) {
vec2 uvd = uv * (length(uv));
float f2 = max(1.0/(1.0+32.0*pow(length(uvd+0.8*pos),2.0)),0.0)*0.25;
float f22 = max(1.0/(1.0+32.0*pow(length(uvd+0.85*pos),2.0)),0.0)*0.23;
float f23 = max(1.0/(1.0+32.0*pow(length(uvd+0.9*pos),2.0)),0.0)*0.21;
vec2 uvx = mix(uv, uvd, -0.5);
float f4 = max(0.01-pow(length(uvx+0.4*pos),2.4),0.0)*6.0;
float f42 = max(0.01-pow(length(uvx+0.45*pos),2.4),0.0)*5.0;
float f43 = max(0.01-pow(length(uvx+0.5*pos),2.4),0.0)*3.0;
uvx = mix(uv, uvd, -0.4);
float f5 = max(0.01-pow(length(uvx+0.2*pos),5.5),0.0)*2.0;
float f52 = max(0.01-pow(length(uvx+0.4*pos),5.5),0.0)*2.0;
float f53 = max(0.01-pow(length(uvx+0.6*pos),5.5),0.0)*2.0;
uvx = mix(uv, uvd, -0.5);
float f6 = max(0.01-pow(length(uvx-0.3*pos),1.6),0.0)*6.0;
float f62 = max(0.01-pow(length(uvx-0.325*pos),1.6),0.0)*3.0;
float f63 = max(0.01-pow(length(uvx-0.35*pos),1.6),0.0)*5.0;
vec3 c = vec3(0.0);
c.r += f2 + f4 + f5 + f6;
c.g += f22 + f42 + f52 + f62;
c.b += f23 + f43 + f53 + f63;
return c;
}
const float MIDDLE_GREY = 0.18;
float getExposure(float aperture, float shutterSpeed, float iso) {
float q = 0.65;
//float l_avg = (1000.0f / 65.0f) * sqrt(aperture) / (iso * shutterSpeed);
float l_avg = (1.0 / q) * sqrt(aperture) / (iso * shutterSpeed);
//float l_avg = sqrt(aperture) / (iso * shutterSpeed);
return MIDDLE_GREY / l_avg;
}
//Based on Filmic Tonemapping Operators http://filmicgames.com/archives/75
vec3 tonemapFilmic(vec3 color) {
vec3 x = max(vec3(0.0), color - 0.004);
return (x * (6.2 * x + 0.5)) / (x * (6.2 * x + 1.7) + 0.06);
}
vec3 tonemapReinhard(vec3 color) {
return color / (color + vec3(1.0));
}
const float A = 0.15;
const float B = 0.50;
const float C = 0.10;
const float D = 0.20;
const float E = 0.02;
const float F = 0.30;
const float W = 11.2;
vec3 uncharted2Tonemap(vec3 x) {
return ((x * (A * x + C * B) + D * E) / (x * (A * x + B) + D * F)) - E / F;
}
vec3 tonemapUncharted2(vec3 color) {
float exposureBias = 2.0;
vec3 curr = uncharted2Tonemap(exposureBias * color);
vec3 whiteScale = 1.0 / uncharted2Tonemap(vec3(W));
return curr * whiteScale;
}
void main() {
// Fish eye
vec2 d = texCoord - m;
float r = sqrt(dot(d, d));
float power = (2.0 * PI / (2.0 * sqrt(dot(m, m)))) * fishEyeStrength;
float bind;
if (power > 0.0) { bind = sqrt(dot(m, m)); }
else { bind = m.x; }
vec2 uv;
if (power > 0.0) {
uv = m + normalize(d) * tan(r * power) * bind / tan(bind * power);
}
else {
uv = m + normalize(d) * atan(r * -power * 10.0) * bind / atan(-power * bind * 10.0);
}
vec4 col = texture(tex, uv);
// Blur
// float depth = texture(gbuffer0, texCoord).a;
// float blur_amount = abs(depth - focus_depth);
// if (depth < depth - focus_depth) {
// blur_amount *= 10.0;
// }
// blur_amount = clamp(blur_amount, 0.0, 1.0);
// vec4 baseColor = col;//texture(tex, texCoord);
// vec4 blurredColor = vec4(0.0, 0.0, 0.0, 0.0);
// float blurSize = 0.005 * blur_amount;
// blurredColor = 0.75 * sampleBox(blurSize * 0.5) + 0.25 * sampleBox(blurSize * 1.0);
// col = baseColor * (1.0 - blur_amount) + blurredColor * blur_amount;
// Fog
// vec3 pos = texture(gbuffer1, texCoord).rgb;
// float dist = distance(pos, eye);
// vec3 dir = eye + pos;
// dir = normalize(dir);
// col.rgb = applyFog(col.rgb, dist, eye, dir);
// col.rgb = applyFog(col.rgb, dist);
// Lens flare
// vec4 lndc = VP * vec4(light, 1.0);
// lndc.xy /= lndc.w;
// float lightDistance = distance(eye, light);
// vec2 lss = lndc.xy * 0.5 + 0.5;
// float lssdepth = linearize(texture(gbuffer0, lss).a, 0.1, 1000.0);
// if (lssdepth >= lightDistance) {
// vec2 lensuv = (texCoord - 0.5) * 2.0;
// lensuv.x *= aspectRatio;
// vec3 lensflarecol = vec3(1.4, 1.2, 1.0) * lensflare(lensuv, lndc.xy);
// col.rgb += lensflarecol;
// }
// Film grain
// const float grainStrength = 4.0;
// float x = (texCoord.x + 4.0) * (texCoord.y + 4.0 ) * (time * 10.0);
// vec4 grain = vec4(mod((mod(x, 13.0) + 1.0) * (mod(x, 123.0) + 1.0), 0.01)-0.005) * grainStrength;
// col += grain;
// Ice
// vec4 ice = screenSpaceIce(vec3(0.8, 0.9, 1.0));
// col.rgb = ice.a * ice.rgb + (1.0 - ice.a) * col.rgb;
// Snow
// vec4 flake = screenSpaceSnow();
// col.rgb = flake.a * flake.rgb + (1.0 - flake.a) * col.rgb;
// Rain
// col.rgb += screenSpaceRain();
// Camera rain
col.rgb = screenSpaceCameraRain();
// Vignetting
col.rgb *= vignette();
// Exposure
const float aperture = 16;
const float shutterSpeed = 0.5;
const float iso = 100;
// col.rgb *= getExposure(aperture, shutterSpeed, iso);
// Tonemapping
col.rgb = tonemapUncharted2(col.rgb);
// col.rgb = tonemapFilmic(col.rgb); // With gamma
// To gamma
col.rgb = pow(col.rgb, vec3(1.0 / 2.2));
// B&W
// col.rgb = vec3(clamp(dot(col.rgb, col.rgb), 0.0, 1.0));
// col.rgb = vec3((col.r * 0.3 + col.g * 0.59 + col.b * 0.11) / 3.0) * 2.5;
gl_FragColor = col;
}