p5.Framebufferからの深度情報を使用して、焦点のぼかし(被写界深度)を伴うシーンを描画するシェーダー。
framebuffer depth dof
3D Shader Rendering
View Source Code
/*
* @name Blur using Framebuffer Depth
* @frame 710,400
* @arialabel A line of five spheres rotating in front of the camera, with ones too close and too far to the camera appearing blurred
* @description A shader that uses depth information from a p5.Framebuffer to
* draw a scene with focal blur.
*/
let layer;
let blur;
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
layer = createFramebuffer();
blur = createShader(vert, frag);
noStroke();
}
function draw() {
// Draw a scene
layer.begin();
background(255);
ambientLight(100);
directionalLight(255, 255, 255, -1, 1, -1);
ambientMaterial(255, 0, 0);
fill(255, 255, 100);
specularMaterial(255);
shininess(150);
rotateY(millis() * 0.001);
for (let i = 0; i < 5; i++) {
push();
translate((i-2)*100, 0, 0);
sphere();
pop();
}
layer.end();
// Render the scene with depth of field blur
shader(blur);
blur.setUniform('img', layer.color);
blur.setUniform('depth', layer.depth);
rect(0, 0, width, height);
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
}
let vert = `
precision highp float;
attribute vec3 aPosition;
attribute vec2 aTexCoord;
varying vec2 vTexCoord;
void main() {
vec4 positionVec4 = vec4(aPosition, 1.0);
positionVec4.xy = positionVec4.xy * 2.0 - 1.0;
positionVec4.y *= -1.0;
gl_Position = positionVec4;
vTexCoord = aTexCoord;
}`;
let frag = `
precision highp float;
varying vec2 vTexCoord;
uniform sampler2D img;
uniform sampler2D depth;
float getBlurriness(float d) {
// Blur more the farther away we go from the
// focal point at depth=0.9
return abs(d - 0.9) * 40.;
}
float maxBlurDistance(float blurriness) {
return blurriness * 0.01;
}
void main() {
vec4 color = texture2D(img, vTexCoord);
float samples = 1.;
float centerDepth = texture2D(depth, vTexCoord).r;
float blurriness = getBlurriness(centerDepth);
for (int sample = 0; sample < 20; sample++) {
// Sample nearby pixels in a spiral going out from the
// current pixel
float angle = float(sample);
float distance = float(sample)/20.
* maxBlurDistance(blurriness);
vec2 offset = vec2(cos(angle), sin(angle)) * distance;
// How close is the object at the nearby pixel?
float sampleDepth = texture2D(depth, vTexCoord + offset).r;
// How far should its blur reach?
float sampleBlurDistance =
maxBlurDistance(getBlurriness(sampleDepth));
// If it's in front of the current pixel, or its blur overlaps
// with the current pixel, add its color to the average
if (
sampleDepth >= centerDepth ||
sampleBlurDistance >= distance
) {
color += texture2D(img, vTexCoord + offset);
samples++;
}
}
color /= samples;
gl_FragColor = color;
}`;
License
Source code is available on GitHub p5.js website legacy.
All examples are licensed under CC BY-NC-SA 4.0.