1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
uniform vec2 invrendertargetdim;
//texture coordinates for framebuffer read
varying vec4 uvcoordsvar;
varying vec2 uv1;
varying vec2 uv2;
varying vec2 uv3;
varying vec2 uv4;
// color buffer
uniform sampler2D colorbuffer;
// depth buffer
uniform sampler2D depthbuffer;
// circle of confusion buffer
uniform sampler2D cocbuffer;
// this includes focal distance in x and aperture size in y
uniform vec4 dof_params;
// viewvectors for reconstruction of world space
uniform vec4 viewvecs[3];
/* coc calculation, positive is far coc, negative is near */
vec4 calculate_signed_coc(in vec4 zdepth)
{
vec4 coc = dof_params.x * (vec4(1.0) - vec4(dof_params.y) / zdepth);
/* multiply by 1.0 / sensor size to get the normalized size */
return coc * dof_params.z;
}
void half_downsample_frag(void)
{
vec4 depthv, coc;
depthv.r = texture2D(depthbuffer, uv1).r;
depthv.g = texture2D(depthbuffer, uv2).r;
depthv.b = texture2D(depthbuffer, uv3).r;
depthv.a = texture2D(depthbuffer, uv4).r;
coc = calculate_signed_coc(get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depthv));
/* near coc, keep the min here */
gl_FragData[1].r = max(-min(min(coc.r, coc.g), min(coc.b, coc.a)), 0.0);
/* far coc keep the max */
gl_FragData[1].g = max(max(max(coc.r, coc.g), max(coc.b, coc.a)), 0.0);
/* framebuffer output 1 is bound to half size color. linear filtering should take care of averaging here */
gl_FragData[0] = texture2D(colorbuffer, uvcoordsvar.xy);
}
void downsample_coc(void)
{
/* basically here we just assemble all nearby values from the texture and use the maximum for near coc
* this ensures the gathe as scatter technique at the end will work */
vec4 coc;
coc.r = texture2D(cocbuffer, uv1).r;
coc.g = texture2D(cocbuffer, uv2).r;
coc.b = texture2D(cocbuffer, uv3).r;
coc.a = texture2D(cocbuffer, uv4).r;
gl_FragColor.r = max(max(coc.r, coc.g), max(coc.b, coc.a));
}
void final_combine_frag(void)
{
vec4 coc = texture2D(cocbuffer, uvcoordsvar.xy);
/* framebuffer output 1 is bound to half size color. linear filtering should take care of averaging here */
gl_FragColor = texture2D(colorbuffer, uvcoordsvar.xy);
gl_FragColor.g *= coc.g;
gl_FragColor.r *= coc.r;
}
void main(void)
{
#ifdef HALF_DOWNSAMPLE_PASS
half_downsample_frag();
#elif defined(HALF_DOWNSAMPLE_COC_PASS)
final_combine_frag();
#endif
}
|