Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl')
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl261
1 files changed, 261 insertions, 0 deletions
diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl
new file mode 100644
index 00000000000..04648f62688
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl
@@ -0,0 +1,261 @@
+
+uniform mat4 ProjectionMatrix;
+
+uniform sampler2D colorBuffer;
+uniform sampler2D depthBuffer;
+
+uniform vec3 dofParams;
+
+#define dof_aperturesize dofParams.x
+#define dof_distance dofParams.y
+#define dof_invsensorsize dofParams.z
+
+uniform vec4 bokehParams;
+
+#define bokeh_sides bokehParams.x /* Polygon Bokeh shape number of sides */
+#define bokeh_rotation bokehParams.y
+#define bokeh_ratio bokehParams.z
+#define bokeh_maxsize bokehParams.w
+
+uniform vec2 nearFar; /* Near & far view depths values */
+
+/* initial uv coordinate */
+in vec2 uvcoord;
+
+layout(location = 0) out vec4 fragData0;
+layout(location = 1) out vec4 fragData1;
+layout(location = 2) out vec4 fragData2;
+
+#define M_PI 3.1415926535897932384626433832795
+#define M_2PI 6.2831853071795864769252868
+
+/* -------------- Utils ------------- */
+
+/* calculate 4 samples at once */
+float calculate_coc(in float zdepth)
+{
+ float coc = dof_aperturesize * (dof_distance / zdepth - 1.0);
+
+ /* multiply by 1.0 / sensor size to get the normalized size */
+ return coc * dof_invsensorsize;
+}
+
+vec4 calculate_coc(in vec4 zdepth)
+{
+ vec4 coc = dof_aperturesize * (vec4(dof_distance) / zdepth - vec4(1.0));
+
+ /* multiply by 1.0 / sensor size to get the normalized size */
+ return coc * dof_invsensorsize;
+}
+
+float max4(vec4 x)
+{
+ return max(max(x.x, x.y), max(x.z, x.w));
+}
+
+float linear_depth(float z)
+{
+ /* if persp */
+ if (ProjectionMatrix[3][3] == 0.0) {
+ return (nearFar.x * nearFar.y) / (z * (nearFar.x - nearFar.y) + nearFar.y);
+ }
+ else {
+ return (z * 2.0 - 1.0) * nearFar.y;
+ }
+}
+
+vec4 linear_depth(vec4 z)
+{
+ /* if persp */
+ if (ProjectionMatrix[3][3] == 0.0) {
+ return (nearFar.xxxx * nearFar.yyyy) / (z * (nearFar.xxxx - nearFar.yyyy) + nearFar.yyyy);
+ }
+ else {
+ return (z * 2.0 - 1.0) * nearFar.yyyy;
+ }
+}
+
+#define THRESHOLD 0.0
+
+/* ----------- Steps ----------- */
+
+/* Downsample the color buffer to half resolution.
+ * Weight color samples by
+ * Compute maximum CoC for near and far blur. */
+void step_downsample(void)
+{
+ ivec4 uvs = ivec4(gl_FragCoord.xyxy) * 2 + ivec4(0, 0, 1, 1);
+
+ /* custom downsampling */
+ vec4 color1 = texelFetch(colorBuffer, uvs.xy, 0);
+ vec4 color2 = texelFetch(colorBuffer, uvs.zw, 0);
+ vec4 color3 = texelFetch(colorBuffer, uvs.zy, 0);
+ vec4 color4 = texelFetch(colorBuffer, uvs.xw, 0);
+
+ /* Leverage SIMD by combining 4 depth samples into a vec4 */
+ vec4 depth;
+ depth.r = texelFetch(depthBuffer, uvs.xy, 0).r;
+ depth.g = texelFetch(depthBuffer, uvs.zw, 0).r;
+ depth.b = texelFetch(depthBuffer, uvs.zy, 0).r;
+ depth.a = texelFetch(depthBuffer, uvs.xw, 0).r;
+
+ vec4 zdepth = linear_depth(depth);
+
+ /* Compute signed CoC for each depth samples */
+ vec4 coc_near = calculate_coc(zdepth);
+ vec4 coc_far = -coc_near;
+
+ /* now we need to write the near-far fields premultiplied by the coc */
+ vec4 near_weights = step(THRESHOLD, coc_near);
+ vec4 far_weights = step(THRESHOLD, coc_far);
+
+ /* now write output to weighted buffers. */
+ fragData0 = color1 * near_weights.x +
+ color2 * near_weights.y +
+ color3 * near_weights.z +
+ color4 * near_weights.w;
+
+ fragData1 = color1 * far_weights.x +
+ color2 * far_weights.y +
+ color3 * far_weights.z +
+ color4 * far_weights.w;
+
+ float norm_near = dot(near_weights, near_weights);
+ float norm_far = dot(far_weights, far_weights);
+
+ if (norm_near > 0.0) {
+ fragData0 /= norm_near;
+ }
+
+ if (norm_far > 0.0) {
+ fragData1 /= norm_far;
+ }
+
+ float max_near_coc = max(max4(coc_near), 0.0);
+ float max_far_coc = max(max4(coc_far), 0.0);
+
+ fragData2 = vec4(max_near_coc, max_far_coc, 0.0, 1.0);
+}
+
+/* coordinate used for calculating radius et al set in geometry shader */
+in vec2 particlecoord;
+flat in vec4 color;
+
+/* accumulate color in the near/far blur buffers */
+void step_scatter(void)
+{
+ /* Early out */
+ float dist_sqrd = dot(particlecoord, particlecoord);
+
+ /* Circle Dof */
+ if (dist_sqrd > 1.0) {
+ discard;
+ }
+
+ /* Regular Polygon Dof */
+ if (bokeh_sides > 0.0) {
+ /* Circle parametrization */
+ float theta = atan(particlecoord.y, particlecoord.x) + bokeh_rotation;
+ float r;
+
+ r = cos(M_PI / bokeh_sides) /
+ (cos(theta - (M_2PI / bokeh_sides) * floor((bokeh_sides * theta + M_PI) / M_2PI)));
+
+ if (dist_sqrd > r * r) {
+ discard;
+ }
+ }
+
+ fragData0 = color;
+}
+
+#define MERGE_THRESHOLD 4.0
+
+uniform sampler2D farBuffer;
+uniform sampler2D nearBuffer;
+
+vec4 upsample_filter_high(sampler2D tex, vec2 uv, vec2 texelSize)
+{
+ /* 9-tap bilinear upsampler (tent filter) */
+ vec4 d = texelSize.xyxy * vec4(1, 1, -1, 0);
+
+ vec4 s;
+ s = textureLod(tex, uv - d.xy, 0.0);
+ s += textureLod(tex, uv - d.wy, 0.0) * 2;
+ s += textureLod(tex, uv - d.zy, 0.0);
+
+ s += textureLod(tex, uv + d.zw, 0.0) * 2;
+ s += textureLod(tex, uv , 0.0) * 4;
+ s += textureLod(tex, uv + d.xw, 0.0) * 2;
+
+ s += textureLod(tex, uv + d.zy, 0.0);
+ s += textureLod(tex, uv + d.wy, 0.0) * 2;
+ s += textureLod(tex, uv + d.xy, 0.0);
+
+ return s * (1.0 / 16.0);
+}
+
+vec4 upsample_filter(sampler2D tex, vec2 uv, vec2 texelSize)
+{
+ /* 4-tap bilinear upsampler */
+ vec4 d = texelSize.xyxy * vec4(-1, -1, +1, +1) * 0.5;
+
+ vec4 s;
+ s = textureLod(tex, uv + d.xy, 0.0);
+ s += textureLod(tex, uv + d.zy, 0.0);
+ s += textureLod(tex, uv + d.xw, 0.0);
+ s += textureLod(tex, uv + d.zw, 0.0);
+
+ return s * (1.0 / 4.0);
+}
+
+/* Combine the Far and Near color buffers */
+void step_resolve(void)
+{
+ /* Recompute Near / Far CoC */
+ float depth = textureLod(depthBuffer, uvcoord, 0.0).r;
+ float zdepth = linear_depth(depth);
+ float coc_signed = calculate_coc(zdepth);
+ float coc_far = max(-coc_signed, 0.0);
+ float coc_near = max(coc_signed, 0.0);
+
+ /* Recompute Near / Far CoC */
+ vec2 texelSize = 1.0 / vec2(textureSize(farBuffer, 0));
+ vec4 srccolor = textureLod(colorBuffer, uvcoord, 0.0);
+ vec4 farcolor = upsample_filter_high(farBuffer, uvcoord, texelSize);
+ vec4 nearcolor = upsample_filter_high(nearBuffer, uvcoord, texelSize);
+
+ float farweight = farcolor.a;
+ if (farweight > 0.0)
+ farcolor /= farweight;
+
+ float mixfac = smoothstep(1.0, MERGE_THRESHOLD, coc_far);
+
+ farweight = mix(1.0, farweight, mixfac);
+
+ float nearweight = nearcolor.a;
+ if (nearweight > 0.0) {
+ nearcolor /= nearweight;
+ }
+
+ if (coc_near > 1.0) {
+ mixfac = smoothstep(1.0, MERGE_THRESHOLD, coc_near);
+ fragData0 = mix(srccolor, nearcolor, mixfac);
+ }
+ else {
+ float totalweight = nearweight + farweight;
+ vec4 finalcolor = mix(srccolor, farcolor, mixfac);
+ fragData0 = mix(finalcolor, nearcolor, nearweight / totalweight);
+ }
+}
+
+void main()
+{
+#ifdef STEP_DOWNSAMPLE
+ step_downsample();
+#elif defined(STEP_SCATTER)
+ step_scatter();
+#elif defined(STEP_RESOLVE)
+ step_resolve();
+#endif
+}