summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/bgfx/examples/45-bokeh/bokeh_dof.sh
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/bgfx/examples/45-bokeh/bokeh_dof.sh')
-rw-r--r--3rdparty/bgfx/examples/45-bokeh/bokeh_dof.sh176
1 files changed, 176 insertions, 0 deletions
diff --git a/3rdparty/bgfx/examples/45-bokeh/bokeh_dof.sh b/3rdparty/bgfx/examples/45-bokeh/bokeh_dof.sh
new file mode 100644
index 00000000000..43c4885d1d3
--- /dev/null
+++ b/3rdparty/bgfx/examples/45-bokeh/bokeh_dof.sh
@@ -0,0 +1,176 @@
+/*
+* Copyright 2021 elven cache. All rights reserved.
+* License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
+*/
+
+#ifndef BOKEH_DOF_SH
+#define BOKEH_DOF_SH
+
+#define TWO_PI (6.28318531)
+#define GOLDEN_ANGLE (2.39996323)
+#define MAX_BLUR_SIZE (20.0)
+#define RADIUS_SCALE (0.5)
+
+float ShadertoyNoise (vec2 uv) {
+ return fract(sin(dot(uv.xy, vec2(12.9898,78.233))) * 43758.5453123);
+}
+
+float GetCircleOfConfusion (float depth, float focusPoint, float focusScale)
+{
+ // if depth is less than focusPoint, result will be negative. want to keep this
+ // relationship so comparison of (signed) blur size is same as comparing depth.
+ return clamp((1.0/focusPoint - 1.0/depth) * focusScale, -1.0, 1.0);
+}
+
+float GetBlurSize (float depth, float focusPoint, float focusScale)
+{
+ float circleOfConfusion = GetCircleOfConfusion(depth, focusPoint, focusScale);
+ return circleOfConfusion * u_maxBlurSize;
+}
+
+// this is the function at bottom of blog post...
+//vec3 OriginalDepthOfField (vec2 texCoord, float focusPoint, float focusScale)
+//{
+// float depth = texture2D(s_depth, texCoord).x;
+// float centerSize = GetBlurSize(depth, focusPoint, focusScale);
+// vec3 color = texture2D(s_color, texCoord).xyz;
+//
+// float total = 1.0;
+// float radius = RADIUS_SCALE;
+// for (float theta = 0.0; radius < MAX_BLUR_SIZE; theta += GOLDEN_ANGLE)
+// {
+// vec2 spiralCoord = texCoord + vec2(cos(theta), sin(theta)) * u_viewTexel.xy * radius;
+// vec3 sampleColor = texture2D(s_color, spiralCoord).xyz;
+// float sampleDepth = texture2D(s_depth, spiralCoord).x;
+//
+// float sampleSize = GetBlurSize(sampleDepth, focusPoint, focusScale);
+// if (sampleDepth > depth)
+// {
+// sampleSize = clamp(sampleSize, 0.0, centerSize*2.0);
+// }
+// float m = smoothstep(radius-0.5, radius+0.5, sampleSize);
+// color += mix(color/total, sampleColor, m);
+// total += 1.0;
+// radius += RADIUS_SCALE/radius;
+// }
+// return color * (1.0/total);
+//}
+
+
+void GetColorAndBlurSize (
+ sampler2D samplerColor,
+ sampler2D samplerDepth,
+ vec2 texCoord,
+ float focusPoint,
+ float focusScale,
+ out vec3 outColor,
+ out float outBlurSize
+) {
+#if USE_PACKED_COLOR_AND_BLUR
+ vec4 colorAndBlurSize = texture2DLod(samplerColor, texCoord, 0);
+ vec3 color = colorAndBlurSize.xyz;
+ float blurSize = colorAndBlurSize.w;
+
+ outColor = color;
+ outBlurSize = blurSize;
+#else
+ vec3 color = texture2DLod(samplerColor, texCoord, 0).xyz;
+ float depth = texture2DLod(samplerDepth, texCoord, 0).x;
+ float blurSize = GetBlurSize(depth, focusPoint, focusScale);
+
+ outColor = color;
+ outBlurSize = blurSize;
+#endif
+}
+
+float BokehShapeFromAngle (float lobeCount, float radiusMin, float radiusDelta2x, float rotation, float angle)
+{
+ // don't shape for 0, 1 blades...
+ if (lobeCount <= 1.0f)
+ {
+ return 1.0f;
+ }
+
+ // divide edge into some number of lobes
+ float invPeriod = lobeCount / (2.0 * 3.1415926);
+ float periodFraction = fract(angle * invPeriod + rotation);
+
+ // apply triangle shape to each lobe to approximate blades of a camera aperture
+ periodFraction = abs(periodFraction - 0.5);
+ return periodFraction*radiusDelta2x + radiusMin;
+}
+
+vec4 DepthOfField(
+ sampler2D samplerColor,
+ sampler2D samplerDepth,
+ vec2 texCoord,
+ float focusPoint,
+ float focusScale
+) {
+ vec3 color;
+ float centerSize;
+ GetColorAndBlurSize(
+ samplerColor,
+ samplerDepth,
+ texCoord,
+ focusPoint,
+ focusScale,
+ /*out*/color,
+ /*out*/centerSize);
+ float absCenterSize = abs(centerSize);
+
+ // as sample count gets lower, visible banding. disrupt with noise.
+ // use a better random/noise/dither function than this..
+ vec2 pixelCoord = texCoord.xy * u_viewRect.zw;
+ float random = ShadertoyNoise(pixelCoord + vec2(314.0, 159.0)*u_frameIdx);
+ float theta = random * TWO_PI;
+ float thetaStep = GOLDEN_ANGLE;
+
+ float total = 1.0;
+ float totalSampleSize = 0.0;
+ float loopValue = u_radiusScale;
+ float loopEnd = u_maxBlurSize;
+
+ while (loopValue < loopEnd)
+ {
+ float radius = loopValue;
+ float shapeScale = BokehShapeFromAngle(
+ u_lobeCount,
+ u_lobeRadiusMin,
+ u_lobeRadiusDelta2x,
+ u_lobeRotation,
+ theta);
+ vec2 spiralCoord = texCoord + vec2(cos(theta), sin(theta)) * u_viewTexel.xy * (radius * shapeScale);
+
+ vec3 sampleColor;
+ float sampleSize;
+ GetColorAndBlurSize(
+ samplerColor,
+ samplerDepth,
+ spiralCoord,
+ focusPoint,
+ focusScale,
+ /*out*/sampleColor,
+ /*out*/sampleSize);
+ float absSampleSize = abs(sampleSize);
+
+ // using signed sample size as proxy for depth comparison
+ if (sampleSize > centerSize)
+ {
+ absSampleSize = clamp(absSampleSize, 0.0, absCenterSize*2.0);
+ }
+ float m = smoothstep(radius-0.5, radius+0.5, absSampleSize);
+ color += mix(color/total, sampleColor, m);
+ totalSampleSize += absSampleSize;
+ total += 1.0;
+ theta += thetaStep;
+
+ loopValue += (u_radiusScale/loopValue);
+ }
+
+ color *= 1.0/total;
+ float averageSampleSize = totalSampleSize / (total-1.0);
+ return vec4(color, averageSampleSize);
+}
+
+#endif