Skip to content

Commit 6412f95

Browse files
committed
Add Gaussian blur renderer
1 parent 76f50c0 commit 6412f95

File tree

5 files changed

+180
-2
lines changed

5 files changed

+180
-2
lines changed

GaussianBlurRenderer.js

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
class GaussianBlurRenderer extends BlurRenderer {
2+
constructor(target) {
3+
super(target)
4+
this.fbo2 = target.createFramebuffer()
5+
this.intensity = 0.1
6+
this.numSamples = 20
7+
}
8+
9+
frag() {
10+
return GaussianBlurRenderer.frag
11+
}
12+
13+
getUniforms() {
14+
const uniforms = super.getUniforms()
15+
delete uniforms.uImg
16+
return uniforms
17+
}
18+
19+
draw(cb) {
20+
const prevCamera = this.target._renderer._curCamera
21+
this.fbo.draw(() => {
22+
this.target.push()
23+
cb()
24+
this.target.pop()
25+
})
26+
27+
const uniforms = this.getUniforms()
28+
29+
this.target.push()
30+
this.target.setCamera(this.cam)
31+
this.cam.move(0, 0, 0)
32+
33+
this.fbo2.draw(() => {
34+
this.target.push()
35+
this.target.noStroke()
36+
this.target.rectMode(CENTER)
37+
this.target.shader(this.shader)
38+
for (const key in uniforms) {
39+
this.shader.setUniform(key, uniforms[key])
40+
this.shader.setUniform('uDirection', 0)
41+
this.shader.setUniform('uImg', this.fbo.color)
42+
}
43+
this.target.rect(0, 0, this.target.width, -this.target.height)
44+
this.target.pop()
45+
})
46+
47+
this.target.noStroke()
48+
this.target.rectMode(CENTER)
49+
this.target.shader(this.shader)
50+
for (const key in uniforms) {
51+
this.shader.setUniform(key, uniforms[key])
52+
}
53+
this.shader.setUniform('uDirection', 1)
54+
this.shader.setUniform('uImg', this.fbo2.color)
55+
this.target.rect(0, 0, this.target.width, -this.target.height)
56+
this.target.pop()
57+
this.target.setCamera(prevCamera)
58+
}
59+
60+
remove() {
61+
super.remove()
62+
this.fbo2.remove()
63+
}
64+
}
65+
66+
p5.prototype.createGaussianBlurRenderer = function() {
67+
return new GaussianBlurRenderer(this)
68+
}
69+
70+
GaussianBlurRenderer.frag = `
71+
precision highp float;
72+
varying highp vec2 vVertTexCoord;
73+
uniform sampler2D uImg;
74+
uniform sampler2D uDepth;
75+
uniform vec2 uSize;
76+
uniform float uIntensity;
77+
uniform float uDof;
78+
uniform float maxBlur;
79+
uniform int uNumSamples;
80+
uniform float uTargetZ;
81+
uniform float uNear;
82+
uniform float uFar;
83+
uniform int uDirection;
84+
#define s ${0.5/3}
85+
const int MAX_NUM_SAMPLES = 50;
86+
float depthToZ(float depth) {
87+
float depthNormalized = 2.0 * depth - 1.0;
88+
return 2.0 * uNear * uFar / (uFar + uNear - depthNormalized * (uFar - uNear));
89+
}
90+
float calcBlur(float z, float pixelScale) {
91+
return clamp(abs(z - uTargetZ) - uDof / 2., 0.0, 0.3*pixelScale);
92+
}
93+
void main() {
94+
float total = 1.0;
95+
float origZ = depthToZ(texture2D(uDepth, vVertTexCoord).x);
96+
vec4 color = texture2D(uImg, vVertTexCoord);
97+
if (abs(origZ - uTargetZ) > uDof / 2.) {
98+
float pixelScale = max(uSize.x, uSize.y);
99+
float blurAmt = calcBlur(origZ, pixelScale);
100+
for (int i = 0; i < MAX_NUM_SAMPLES; i++) {
101+
if (i >= uNumSamples) break;
102+
float t = (float(i) / float(uNumSamples - 1));
103+
float radius = (t * 2. - 1.);
104+
float distAway = radius * uIntensity * blurAmt;
105+
vec2 offset = (uDirection == 0 ? vec2(1.,0.) : vec2(0.,1.)) * distAway / pixelScale;
106+
float z = depthToZ(texture2D(uDepth, vVertTexCoord + offset).x);
107+
float sampleBlur = calcBlur(z, pixelScale);
108+
float t2 = distAway / (sampleBlur * uIntensity);
109+
float weight = ${1/Math.sqrt(2*Math.PI)} / s * exp(-0.5*pow(t2/s,2.));
110+
vec4 sample = texture2D(uImg, vVertTexCoord + offset);
111+
color += weight * sample;
112+
total += weight;
113+
}
114+
}
115+
color /= total;
116+
gl_FragColor = color;
117+
}
118+
`

examples/gaussianblur/index.html

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<!DOCTYPE html><html lang="en"><head>
2+
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.min.js"></script>
3+
<script src="../../p5.Framebuffer.js" type="text/javascript"></script>
4+
<script src="../../Renderer.js" type="text/javascript"></script>
5+
<script src="../../BlurRenderer.js" type="text/javascript"></script>
6+
<script src="../../GaussianBlurRenderer.js" type="text/javascript"></script>
7+
<link rel="stylesheet" type="text/css" href="style.css">
8+
<meta charset="utf-8">
9+
10+
</head>
11+
<body>
12+
<script src="sketch.js"></script>
13+
14+
15+
</body></html>

examples/gaussianblur/sketch.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
let blurRenderer
2+
3+
function setup() {
4+
createCanvas(400, 400, WEBGL)
5+
blurRenderer = createGaussianBlurRenderer()
6+
}
7+
8+
function draw() {
9+
blurRenderer.draw(() => {
10+
clear()
11+
push()
12+
background(255)
13+
noStroke()
14+
lights()
15+
16+
push()
17+
fill('red')
18+
translate(50*sin(millis()/500), 50*cos(millis()/500), 100*sin(millis()/800 + 100))
19+
sphere(50)
20+
pop()
21+
22+
push()
23+
fill('blue')
24+
translate(50*cos(millis()/300+12), 50*sin(millis()/600), 100*sin(millis()/800 + 1))
25+
sphere(50)
26+
blurRenderer.focusHere()
27+
pop()
28+
29+
push()
30+
fill('white')
31+
translate(0, 200, -100)
32+
rotateX(PI/2)
33+
plane(900, 900)
34+
pop()
35+
pop()
36+
})
37+
}

examples/gaussianblur/style.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
html, body {
2+
margin: 0;
3+
padding: 0;
4+
}
5+
canvas {
6+
display: block;
7+
}

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@davepagurek/p5.framebuffer",
3-
"version": "0.0.5",
3+
"version": "0.0.6",
44
"main": "p5.Framebuffer.js",
55
"author": "Dave Pagurek <[email protected]>",
66
"license": "MIT",
@@ -19,7 +19,7 @@
1919
},
2020
"scripts": {
2121
"build:core": "minify p5.Framebuffer.js > p5.Framebuffer.core.min.js",
22-
"build:all": "minify p5.Framebuffer.js > p5.Framebuffer.min.js; minify Renderer.js >> p5.Framebuffer.min.js; minify BlurRenderer.js >> p5.Framebuffer.min.js; minify ContactShadowRenderer.js >> p5.Framebuffer.min.js",
22+
"build:all": "minify p5.Framebuffer.js > p5.Framebuffer.min.js; minify Renderer.js >> p5.Framebuffer.min.js; minify BlurRenderer.js >> p5.Framebuffer.min.js; minify GaussianBlurRenderer.js >> p5.Framebuffer.min.js; minify ContactShadowRenderer.js >> p5.Framebuffer.min.js",
2323
"build": "yarn build:core && yarn build:all",
2424
"publish": "npm publish --access public"
2525
},
@@ -29,6 +29,7 @@
2929
"p5.Framebuffer.js",
3030
"Renderer.js",
3131
"BlurRenderer.js",
32+
"GaussianBlurRenderer.js",
3233
"ContactShadowRenderer.js"
3334
]
3435
}

0 commit comments

Comments
 (0)