armory/Shaders/std/dof.glsl

93 lines
3 KiB
Plaintext
Raw Normal View History

2016-10-21 19:36:08 +02:00
// DoF with bokeh GLSL shader by Martins Upitis (martinsh) (devlog-martinsh.blogspot.com)
// Creative Commons Attribution 3.0 Unported License
#include "compiled.inc"
2017-12-15 12:52:58 +01:00
#include "std/math.glsl"
2016-10-21 19:36:08 +02:00
// const float compoDOFDistance = 10.0; // Focal distance value in meters
// const float compoDOFLength = 160.0; // Focal length in mm 18-200
// const float compoDOFFstop = 128.0; // F-stop value
2017-07-31 14:30:56 +02:00
const int samples = 6; // Samples on the first ring
const int rings = 6; // Ring count
2017-02-25 17:13:22 +01:00
const vec2 focus = vec2(0.5, 0.5);
2017-07-31 14:30:56 +02:00
const float coc = 0.11; // Circle of confusion size in mm (35mm film = 0.03mm)
2016-10-21 19:36:08 +02:00
const float maxblur = 1.0;
const float threshold = 0.5; // Highlight threshold
const float gain = 2.0; // Highlight gain
const float bias = 0.5; // Bokeh edge bias
const float fringe = 0.7; // Bokeh chromatic aberration/fringing
const float namount = 0.0001; // Dither amount
vec3 color(vec2 coords, const float blur, const sampler2D tex, const vec2 texStep) {
vec3 col = vec3(0.0);
2018-12-06 15:23:08 +01:00
col.r = textureLod(tex, coords + vec2(0.0, 1.0) * texStep * fringe * blur, 0.0).r;
col.g = textureLod(tex, coords + vec2(-0.866, -0.5) * texStep * fringe * blur, 0.0).g;
col.b = textureLod(tex, coords + vec2(0.866, -0.5) * texStep * fringe * blur, 0.0).b;
2016-10-21 19:36:08 +02:00
const vec3 lumcoeff = vec3(0.299, 0.587, 0.114);
float lum = dot(col.rgb, lumcoeff);
float thresh = max((lum - threshold) * gain, 0.0);
return col + mix(vec3(0.0), col, thresh * blur);
}
vec3 dof(
const vec2 texCoord,
const float gdepth,
const sampler2D tex,
const sampler2D gbufferD,
const vec2 texStep,
const vec2 cameraProj,
const bool autoFocus,
const float DOFDistance,
const float DOFLength,
const float DOFFStop) {
2017-11-04 18:35:34 +01:00
float depth = linearize(gdepth, cameraProj);
float fDepth = 0.0;
if(autoFocus) {
fDepth = linearize(textureLod(gbufferD, focus, 0.0).r * 2.0 - 1.0, cameraProj);
} else {
fDepth = DOFDistance;
}
float f = DOFLength; // Focal length in mm
float d = fDepth * 1000.0; // Focal plane in mm
2016-10-21 19:36:08 +02:00
float o = depth * 1000.0; // Depth in mm
float a = (o * f) / (o - f);
float b = (d * f) / (d - f);
float c = (d - f) / (d * DOFFStop * coc);
2016-10-21 19:36:08 +02:00
float blur = abs(a - b) * c;
blur = clamp(blur, 0.0, 1.0);
vec2 noise = rand2(texCoord) * namount * blur;
float w = (texStep.x) * blur * maxblur + noise.x;
float h = (texStep.y) * blur * maxblur + noise.y;
vec3 col = vec3(0.0);
if (blur < 0.05) {
2018-12-06 15:23:08 +01:00
col = textureLod(tex, texCoord, 0.0).rgb;
2016-10-21 19:36:08 +02:00
}
else {
2018-12-06 15:23:08 +01:00
col = textureLod(tex, texCoord, 0.0).rgb;
2016-10-21 19:36:08 +02:00
float s = 1.0;
int ringsamples;
2017-07-31 14:30:56 +02:00
for (int i = 1; i <= rings; ++i) {
ringsamples = i * samples;
for (int j = 0 ; j < ringsamples; ++j) {
float step = PI2 / float(ringsamples);
float pw = (cos(float(j) * step) * float(i));
float ph = (sin(float(j) * step) * float(i));
float p = 1.0;
// if (pentagon) p = penta(vec2(pw, ph));
col += color(texCoord + vec2(pw * w, ph * h), blur, tex, texStep) * mix(1.0, (float(i)) / (float(rings)), bias) * p;
s += 1.0 * mix(1.0, (float(i)) / (float(rings)), bias) * p;
}
}
2016-10-21 19:36:08 +02:00
col /= s;
}
return col;
}