multipass filter

This commit is contained in:
2019-03-27 20:16:59 +01:00
parent 338602172b
commit dc42c474a1
3 changed files with 148 additions and 9 deletions

82
src/nodes/WebGL/Blur.js Normal file
View File

@@ -0,0 +1,82 @@
import WebGL from './WebGl';
export default class Blur extends WebGL {
constructor() {
super('Blur', {
amount: {
type: 'Number',
default: 0,
},
})
}
_passes() {
const passes = Array(this.in.amount.value)
.fill(null)
.map((x, i) => (gl, program) => this._setParams(gl, program));
return passes;
}
get frag() {
return `
precision mediump float;
// our texture
uniform sampler2D u_image;
uniform vec2 u_resolution;
uniform vec2 u_textureSize;
// the texCoords passed in from the vertex shader.
varying vec2 v_texCoord;
uniform float kernel[9];
void main() {
vec2 onePixel = vec2(1.0, 1.0) / u_textureSize;
float weight = kernel[0] +
kernel[1] +
kernel[2] +
kernel[3] +
kernel[4] +
kernel[5] +
kernel[6] +
kernel[7] +
kernel[8];
vec4 colorSum =
texture2D(u_image, v_texCoord + onePixel * vec2(-1, -1)) * kernel[0] +
texture2D(u_image, v_texCoord + onePixel * vec2(0, -1)) * kernel[1] +
texture2D(u_image, v_texCoord + onePixel * vec2(1, -1)) * kernel[2] +
texture2D(u_image, v_texCoord + onePixel * vec2(-1, 0)) * kernel[3] +
texture2D(u_image, v_texCoord + onePixel * vec2(0, 0)) * kernel[4] +
texture2D(u_image, v_texCoord + onePixel * vec2(1, 0)) * kernel[5] +
texture2D(u_image, v_texCoord + onePixel * vec2(-1, 1)) * kernel[6] +
texture2D(u_image, v_texCoord + onePixel * vec2(0, 1)) * kernel[7] +
texture2D(u_image, v_texCoord + onePixel * vec2(1, 1)) * kernel[8];
gl_FragColor = colorSum / weight;
}
`
}
get amount() {
return this.in.amount.value;
}
/**
*
* @param {WebGLRenderingContext} gl
* @param {*} program
*/
_setParams(gl, program) {
gl.uniform1fv(gl.getUniformLocation(program, 'kernel'), [
0.045, 0.122, 0.045,
0.122, 0.332, 0.122,
0.045, 0.122, 0.045
]);
}
}

View File

@@ -30,10 +30,13 @@ export default class WebGL extends Node {
get vert() {
return `
precision mediump float;
attribute vec2 a_position;
attribute vec2 a_texCoord;
uniform vec2 u_resolution;
uniform vec2 u_textureSize;
uniform float u_flip_y;
varying vec2 v_texCoord;
@@ -47,7 +50,7 @@ export default class WebGL extends Node {
// convert from 0->2 to -1->+1 (clipspace)
vec2 clipSpace = zeroToTwo - 1.0;
gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
gl_Position = vec4(clipSpace * vec2(1, u_flip_y), 0, 1);
// pass the texCoord to the fragment shader
// The GPU will interpolate this value between points.
@@ -133,6 +136,37 @@ export default class WebGL extends Node {
return texture;
}
_createFrameBuffer(gl, {width, height}) {
const texture = this.createTexture(gl);
const frameBuffer = gl.createFramebuffer();
gl.texImage2D(
gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0,
gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
gl.framebufferTexture2D(
gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
return {frameBuffer, texture};
}
_passes() {
return [
(gl, program, image) => {
console.log('pass1')
this._setParams(gl, program);
},
(gl, program, image) => {
console.log('pass2')
this._setParams(gl, program);
},
(gl, program, image) => {
console.log('pass3')
this._setParams(gl, program);
}
]
}
_setParams(gl, program) {
}
@@ -146,7 +180,6 @@ export default class WebGL extends Node {
if (!this.program) {
this.program = this.compileProgram(gl);
gl.useProgram(this.program);
this.createTexture(gl);
}
}
@@ -161,6 +194,7 @@ export default class WebGL extends Node {
if (width === 0 || height === 0) {
return;
}
this.setup();
const canvas = this.canvas;
canvas.width = width;
@@ -169,6 +203,14 @@ export default class WebGL extends Node {
const gl = canvas.getContext('webgl');
const program = this.program;
const frameBuffers = [
this._createFrameBuffer(gl, {width, height}),
this._createFrameBuffer(gl, {width, height}),
];
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
this.createTexture(gl);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.clearColor(0, 0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
@@ -177,13 +219,13 @@ export default class WebGL extends Node {
const positionLocation = gl.getAttribLocation(program, "a_position");
const texcoordLocation = gl.getAttribLocation(program, "a_texCoord");
const resolutionLocation = gl.getUniformLocation(program, "u_resolution");
const flipLocation = gl.getUniformLocation(program, "u_flip_y");
if (this.image) {
// Upload the image into the texture.
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, await createImageBitmap(this.image));
}
const texcoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
@@ -226,14 +268,28 @@ export default class WebGL extends Node {
gl.vertexAttribPointer(
texcoordLocation, size, type, normalize, stride, offset);
const passes = this._passes();
for (let iter = 0; iter < passes.length; iter++) {
const frameBuffer = frameBuffers[iter%2];
if (iter === passes.length -1) { // last
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.uniform1f(flipLocation, -1);
} else {
gl.uniform1f(flipLocation, 1);
gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer.frameBuffer);
}
passes[iter](gl, program);
// set the resolution
gl.uniform2f(resolutionLocation, gl.canvas.width, gl.canvas.height);
this._setParams(gl, program);
gl.uniform2f(gl.getUniformLocation(program, "u_textureSize"), width, height);
// Draw the rectangle.
gl.drawArrays(gl.TRIANGLES, 0, 6);
gl.bindTexture(gl.TEXTURE_2D, frameBuffer.texture);
}
const resultCanvas = canvasPool2D.createCanvas();
resultCanvas.width = 1;
resultCanvas.height = 1;

View File

@@ -11,7 +11,8 @@ export {default as BrightnessContrast} from './WebGL/BrightnessContrast';
export {default as HSV} from './WebGL/HSV';
export {default as Sepia} from './WebGL/Sepia';
export {default as GreenScreen} from './WebGL/Greenscreen';
export {default as Channels} from './WebGL/Channels'
export {default as Channels} from './WebGL/Channels';
export {default as Blur} from './WebGL/Blur';
// Math
export {default as Numbers} from './Math/Numbers';
export {default as NumberBinaryOperation} from './Math/NumberBinaryOperation';