xxxxxxxxxx
100
// A proof of concept using a Framebuffer instead of a p5.RendererGL
// as the main target for user drawing,
// cobbled from user-facing functions.
//
// Some pros:
// - textures share a single webgl context
// - no need to createGraphics() and pass data with another context
//
// References:
// https://github.com/davepagurek/p5.Framebuffer#usage
// https://github.com/processing/p5.js/issues/5571
let fbo, fbo2, s, vert, frag;
function setup() {
createCanvas(400, 400, WEBGL)
fbo = createFramebuffer() // main render target, probably stored in _renderer
fbo2 = createFramebuffer() // a helper to demonstrate post-processing
s = createShader(vert, frag)
}
function draw() {
// user's main drawing loop happens with the framebuffer bound
fbo.draw(() => {
clear()
push()
userSketch()
pop()
})
// post processing the texture from the initial framebuffer
// the easiest way to demonstrate this in a sketch is inside another framebuffer
fbo2.draw(() => {
clear()
push()
// shader needs to be set before the texture is set
postProcessing()
// easiest way to write to fbo2.color is to draw fbo.color onto to a flat surface
texture(fbo.color)
plane(width, height)
pop()
})
// render result onto main canvas
clear()
texture(fbo2.color) // compare with unfiltered fbo.color
noStroke()
plane(width, height)
}
function userSketch() {
// example of normal user drawing functions
stroke(0)
fill('YELLOW')
rotateX(frameCount * 0.01)
rotateY(frameCount * 0.01)
box(150)
}
function postProcessing() {
// example of a filter applied to the scene
// an aside: not sure why the shader turns the background black
shader(s)
s.setUniform('tex0', fbo.color) // Using p5.framebuffer here means data is still
// passed from CPU to GPU. I think this is preventable
// by manually binding webgl textures.
// Not that I've noticed a performance problem yet.
}
// a grayscale shader, from https://github.com/aferriss/p5jsShaderExamples/blob/gh-pages/4_image-effects/4-14_rgb-to-grayscale/effect.frag
vert = `attribute vec3 aPosition;
attribute vec2 aTexCoord;
varying vec2 vTexCoord;
void main() {
vTexCoord = aTexCoord;
vec4 positionVec4 = vec4(aPosition, 1.0);
positionVec4.xy = positionVec4.xy * 2.0;
gl_Position = positionVec4;
}`
frag = `precision mediump float;
varying mediump vec2 vTexCoord;
uniform sampler2D tex0;
float luma(vec3 color) {
return dot(color, vec3(0.299, 0.587, 0.114));
}
void main() {
vec4 sampledColor = texture2D(tex0, vTexCoord);
float gray = luma(sampledColor.rgb);
gl_FragColor = vec4(gray, gray, gray, 1);
}`