Eevee: Fix Missing alpha when rendering with DOF
[blender.git] / source / blender / draw / engines / eevee / shaders / effect_dof_vert.glsl
1
2 uniform vec4 bokehParams[2];
3
4 #define bokeh_rotation      bokehParams[0].x
5 #define bokeh_ratio         bokehParams[0].y
6 #define bokeh_maxsize       bokehParams[0].z
7
8 uniform sampler2D nearBuffer;
9 uniform sampler2D farBuffer;
10 uniform sampler2D cocBuffer;
11
12 flat out vec4 color;
13 flat out float weight;
14 flat out float smoothFac;
15 flat out ivec2 edge;
16 out vec2 particlecoord;
17
18 #define M_PI 3.1415926535897932384626433832795
19
20 /* Scatter pass, calculate a triangle covering the CoC. */
21 void main()
22 {
23         ivec2 tex_size = textureSize(cocBuffer, 0);
24         /* We render to a double width texture so compute
25          * the target texel size accordingly */
26         vec2 texel_size = vec2(0.5, 1.0) / vec2(tex_size);
27
28         int t_id = gl_VertexID / 3; /* Triangle Id */
29
30         ivec2 texelco = ivec2(0);
31         /* some math to get the target pixel */
32         texelco.x = t_id % tex_size.x;
33         texelco.y = t_id / tex_size.x;
34
35         vec2 cocs = texelFetch(cocBuffer, texelco, 0).rg;
36
37         bool is_near = (cocs.x > cocs.y);
38         float coc = (is_near) ? cocs.x : cocs.y;
39
40         /* Clamp to max size for performance */
41         coc = min(coc, bokeh_maxsize);
42
43         if (coc >= 1.0) {
44                 if (is_near) {
45                         color = texelFetch(nearBuffer, texelco, 0);
46                 }
47                 else {
48                         color = texelFetch(farBuffer, texelco, 0);
49                 }
50                 /* find the area the pixel will cover and divide the color by it */
51                 /* HACK: 4.0 out of nowhere (I suppose it's 4 pixels footprint for coc 0?)
52                  * Makes near in focus more closer to 1.0 alpha. */
53                 weight = 4.0 / (coc * coc * M_PI);
54                 color *= weight;
55
56                 /* Compute edge to discard fragment that does not belong to the other layer. */
57                 edge.x = (is_near) ? 1 : -1;
58                 edge.y = (is_near) ? -tex_size.x + 1 : tex_size.x;
59         }
60         else {
61                 /* Don't produce any fragments */
62                 color = vec4(0.0);
63                 gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
64                 return;
65         }
66
67         /* Generate Triangle : less memory fetches from a VBO */
68         int v_id = gl_VertexID % 3; /* Vertex Id */
69
70         /* Extend to cover at least the unit circle */
71         const float extend = (cos(M_PI / 4.0) + 1.0) * 2.0;
72         /* Crappy diagram
73          * ex 1
74          *    | \
75          *    |   \
76          *  1 |     \
77          *    |       \
78          *    |         \
79          *  0 |     x     \
80          *    |   Circle    \
81          *    |   Origin      \
82          * -1 0 --------------- 2
83          *   -1     0     1     ex
84          **/
85         gl_Position.x = float(v_id / 2) * extend - 1.0; /* int divisor round down */
86         gl_Position.y = float(v_id % 2) * extend - 1.0;
87         gl_Position.z = 0.0;
88         gl_Position.w = 1.0;
89
90         /* Generate Triangle */
91         particlecoord = gl_Position.xy;
92
93         gl_Position.xy *= coc * texel_size * vec2(bokeh_ratio, 1.0);
94         gl_Position.xy -= 1.0 - 0.5 * texel_size; /* NDC Bottom left */
95         gl_Position.xy += (0.5 + vec2(texelco) * 2.0) * texel_size;
96
97         /* Push far plane to left side. */
98         if (!is_near) {
99                 gl_Position.x += 2.0 / 2.0;
100         }
101
102         /* don't do smoothing for small sprites */
103         if (coc > 3.0) {
104                 smoothFac = 1.0 - 1.5 / coc;
105         }
106         else {
107                 smoothFac = 1.0;
108         }
109 }