@davepagurek/p5.filterrenderer
v0.0.16
Published
A library for p5.js WebGL mode to draw with depth blur and shadows.
Downloads
5
Readme
p5.filterRenderer
A library for p5.js WebGL mode to draw with depth blur and shadows.
Read more about the motivation for this and how focal blur shaders work in this blog post on the subject.
Above: a screenshot from a sketch using blurring out-of-focus areas
Get the library
Add the library to your source code, after loading p5 but before loading your own code.
Via CDN
<script src="https://cdn.jsdelivr.net/npm/@davepagurek/[email protected]/p5.filterRenderer.min.js"></script>
On OpenProcessing, paste this link into a new library slot:
https://cdn.jsdelivr.net/npm/@davepagurek/[email protected]/p5.filterRenderer.min.js
Self-hosted
Download the minified or unminified source code from the releases tab, then add it to your HTML:
<script type="text/javascript" src="p5.filterRenderer.min.js"></script>
Usage
Depth of field blur
The library provides a helper that bundles a Framebuffer with a shader that applies focal blur, leaving objects at a provided distance in focus and blurring things more the farther away from that point they are.
Create a blur renderer and draw inside its draw
callback. When you tell it to focusHere()
, anything drawn at that transformed position will be in focus. You can use standard p5 translate
calls to position the focal point.
Gaussian blur
This is likely the best-looking blur renderer, although it uses two render passes. Start by using this one, but look out the other BlurRenderer
if it's slow.
let blurRenderer
function setup() {
createCanvas(400, 400, WEBGL)
blurRenderer = createGaussianBlurRenderer()
blurRenderer.setIntensity(0.15)
blurRenderer.setSamples(20)
blurRenderer.setDof(50)
}
function draw() {
blurRenderer.draw(() => {
clear()
push()
background(255)
noStroke()
lights()
push()
fill('blue')
translate(-80, -80, -300)
blurRenderer.focusHere()
sphere(50)
pop()
push()
fill('red')
sphere(50)
pop()
pop()
})
}
Methods on GaussianBlurRenderer
:
GaussianBlurRenderer.prototype.draw(callback: () => void)
- Draw the scene defined in the callback with blur
GaussianBlurRenderer.prototype.focusHere()
- Tell the renderer what point in space should be in focus. It will move based on any calls to
translate()
or other transformations that you have applied. - Defaults to the origin
- Tell the renderer what point in space should be in focus. It will move based on any calls to
GaussianBlurRenderer.prototype.setIntensity(intensity: number)
- Control the intensity of the blur, between 0 and 1: the lower the intensity, the farther objects have to be from the focal point to be blurred
- Defaults to 0.1
GaussianBlurRenderer.prototype.setDof(dof: number)
- Control the depth of field (dof), which is the distance away from the focal point that is also in focus, from 0 up
- The lower the dof, the smaller range will be that has no blur. Blur amount will start to accumulate when objects are outside of the dof range
- The focal target (set by
focusHere
) is located in the centre of the clear range. So assume the focal target's depth value isz
, then the clear range becomes fromz - dof / 2
toz + dof / 2
. - Defaults to 0
GaussianBlurRenderer.prototype.setSamples(numSamples: number)
- Control how many random samples to use in the blur shader. More samples will look smoother but is more computationally intensive.
- Defaults to 20
A live example: https://davepagurek.github.io/p5.Framebuffer/examples/gaussianblur
One-pass blur
Another implementation of blur, but using a single shader pass. This will likely produce a grainier result, but might be faster on some systems.
let blurRenderer
function setup() {
createCanvas(400, 400, WEBGL)
blurRenderer = createBlurRenderer()
}
function draw() {
blurRenderer.draw(() => {
clear()
push()
background(255)
noStroke()
lights()
push()
fill('blue')
translate(-80, -80, -300)
blurRenderer.focusHere()
sphere(50)
pop()
push()
fill('red')
sphere(50)
pop()
pop()
})
}
Methods on BlurRenderer
:
BlurRenderer.prototype.draw(callback: () => void)
- Draw the scene defined in the callback with blur
BlurRenderer.prototype.focusHere()
- Tell the renderer what point in space should be in focus. It will move based on any calls to
translate()
or other transformations that you have applied. - Defaults to the origin
- Tell the renderer what point in space should be in focus. It will move based on any calls to
BlurRenderer.prototype.setIntensity(intensity: number)
- Control the intensity of the blur, between 0 and 1: the lower the intensity, the farther objects have to be from the focal point to be blurred
- Defaults to 0.05
BlurRenderer.prototype.setDof(dof: number)
- Control the depth of field (dof), which is the distance away from the focal point that is also in focus, from 0 up
- The lower the dof, the smaller range will be that has no blur. Blur amount will start to accumulate when objects are outside of the dof range
- The focal target (set by
focusHere
) is located in the centre of the clear range. So assume the focal target's depth value isz
, then the clear range becomes fromz - dof / 2
toz + dof / 2
. - Defaults to 0
BlurRenderer.prototype.setSamples(numSamples: number)
- Control how many random samples to use in the blur shader. More samples will look smoother but is more computationally intensive.
- Defaults to 15
A live example: https://davepagurek.github.io/p5.Framebuffer/examples/blur
Contact Shadows
The library provides a helper that bundles a Framebuffer with a shader that applies Ambient Occlusion shadows. This approximates the shadows one would see if there was uniform light hitting an object from all sides. In practice, it adds shadows in areas where objects get close to each other.
Create a shadow renderer and draw inside its draw
callback. The renderer will add shadows to the result.
let contactShadowRenderer
function setup() {
createCanvas(400, 400, WEBGL)
contactShadowRenderer = createContactShadowRenderer()
}
function draw() {
contactShadowRenderer.draw(() => {
clear()
push()
background(255)
fill(255)
noStroke()
lights()
push()
translate(50, -50, 10)
sphere(50)
pop()
push()
translate(-50, 50, -10)
sphere(90)
pop()
})
}
Methods on ContactShadowRenderer
:
ContactShadowRenderer.prototype.draw(callback: () => void)
- Draw the scene defined in the callback with shadows added
ContactShadowRenderer.prototype.setIntensity(intensity: number)
- Control how dark shadows are: 0 is no shadows, and 1 is full darkness
- Defaults to 0.5
ContactShadowRenderer.prototype.setShadowSamples(numSamples: number)
- Control how many random samples to use in the shadow shader. More samples will be more accurate but is more computationally intensive.
- Defaults to 15
ContactShadowRenderer.prototype.setBlurSamples(numSamples: number)
- Control how many random samples to use in the blur shader. More samples will be smoother but is more computationally intensive.
- Defaults to 20
ContactShadowRenderer.prototype.setBlurRadius(radius: number)
- Sets how far the blur extends when blurring shadows, in pixels, ignoring the pixel density
- Defaults to 50
ContactShadowRenderer.prototype.setSearchRadius(radius: number)
- Control how close together objects need to be for them to cast shadows
- This is defined in world space, meaning all transformations are applied when checking distances
- Defaults to 100
ContactShadowRenderer.prototype.setTintColor(color)
- This is the color that the original render will be mixed with when there are shadows
- Defaults to black
A live example: https://davepagurek.github.io/p5.Framebuffer/examples/shadows
External examples
- Rolling Shutter
- Uses 120 framebuffers to store previous frames of video for a slit scanning effect
- Wizard Pondering Orb
- Uses the Gaussian blur renderer
- 3D Text
- Uses two framebuffers to do a feedback effect
- Disassemble
- Uses the contact shadow renderer
- Train Knots
- Uses the depth buffer in a focal blur shader
- Modern Vampires of the City
- Uses the depth buffer to create a fog effect
More coming soon!