WebGL2 fbo_blit

230 阅读1分钟

image.png webglsamples.org/WebGL2Sampl…

  • Program
// -- Init program
var program = createProgram(gl, getShaderSource('vs'), getShaderSource('fs'));
var mvpLocation = gl.getUniformLocation(program, 'MVP');
var diffuseLocation = gl.getUniformLocation(program, 'diffuse');
  • vertexPosBuffer Position
// -- Init buffers:
var positions = new Float32Array([
    -1.0, -1.0,
     1.0, -1.0,
     1.0,  1.0,
     1.0,  1.0,
    -1.0,  1.0,
    -1.0, -1.0
]);
var vertexPosBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer);
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
  • vertexTexBuffer texcoords
var texCoords = new Float32Array([
    0.0, 1.0,
    1.0, 1.0,
    1.0, 0.0,
    1.0, 0.0,
    0.0, 0.0,
    0.0, 1.0
]);
var vertexTexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexTexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, texCoords, gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
  • vertexArray
// -- Init VertexArray
var vertexArray = gl.createVertexArray();
gl.bindVertexArray(vertexArray);

var vertexPosLocation = 0; // set with GLSL layout qualifier
gl.enableVertexAttribArray(vertexPosLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer);
gl.vertexAttribPointer(vertexPosLocation, 2, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, null);

var vertexTexLocation = 4; // set with GLSL layout qualifier
gl.enableVertexAttribArray(vertexTexLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, vertexTexBuffer);
gl.vertexAttribPointer(vertexTexLocation, 2, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, null);

gl.bindVertexArray(null);
  • FRAMEBUFFER_SIZE
var FRAMEBUFFER_SIZE = {
    x: image.width,
    y: image.height
};
  • Init Texture
// -- Init Texture
var textureDiffuse = gl.createTexture(); //就是那个主人公
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, textureDiffuse);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
  • FrameBuffer 为啥会有Framebuffer
var textureColorBuffer = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, textureColorBuffer);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, FRAMEBUFFER_SIZE.x, FRAMEBUFFER_SIZE.y, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); //
gl.bindTexture(gl.TEXTURE_2D, null);

// -- Init Frame Buffer
var colorRenderbuffer = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, colorRenderbuffer);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, FRAMEBUFFER_SIZE.x, FRAMEBUFFER_SIZE.y);

var framebufferRender = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, framebufferRender);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorRenderbuffer);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);

var framebufferResolve = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, framebufferResolve);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textureColorBuffer, 0);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  • image.png
  • clearBufferfv那个颜色就是[0.3, 0.3, 0.3, 1.0]
  • bindframebuffer
// -- Render
gl.useProgram(program);
gl.uniform1i(diffuseLocation, 0);
// Pass 1
gl.bindFramebuffer(gl.FRAMEBUFFER, framebufferRender);
gl.viewport(0, 0, FRAMEBUFFER_SIZE.x, FRAMEBUFFER_SIZE.y);
gl.clearBufferfv(gl.COLOR, 0, [0.3, 0.3, 0.3, 1.0]); 
var SCALE = new Float32Array([
    0.8, 0.0, 0.0, 0.0,
    0.0, 0.8, 0.0, 0.0,
    0.0, 0.0, 0.8, 0.0,
    0.0, 0.0, 0.0, 1.0
]);
gl.uniformMatrix4fv(mvpLocation, false, SCALE);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, textureDiffuse);
gl.bindVertexArray(vertexArray);
gl.drawArrays(gl.TRIANGLES, 0, 6);
gl.bindTexture(gl.TEXTURE_2D, null);
  • bindFramebuffer
  • blitFramebuffer贴出多张贴图的感觉
// Blit framebuffers
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, framebufferRender); //bind buffer
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, framebufferResolve);
gl.clearBufferfv(gl.COLOR, 0, [0.7, 0.0, 0.0, 1.0]); //红色
var TILE = 4;
var BORDER = 2;
for(var j = 0; j < TILE; j++) {
    for(var i = 0; i < TILE; i++) {
        if((i + j) % 2) {
            continue;
        }
        gl.blitFramebuffer(
            0, 0, FRAMEBUFFER_SIZE.x, FRAMEBUFFER_SIZE.y,
            FRAMEBUFFER_SIZE.x / TILE * (i + 0) + BORDER,
            FRAMEBUFFER_SIZE.x / TILE * (j + 0) + BORDER,
            FRAMEBUFFER_SIZE.y / TILE * (i + 1) - BORDER,
            FRAMEBUFFER_SIZE.y / TILE * (j + 1) - BORDER,
            gl.COLOR_BUFFER_BIT, gl.LINEAR
        );
    }
}
  • 展示textureColorBuffer FBO贴图
// Pass 2
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.viewport(0, 0, canvas.width, canvas.height);
gl.clearBufferfv(gl.COLOR, 0, [0.0, 0.0, 0.0, 1.0]);

// Render FB
var IDENTITY = new Float32Array([
    1.0, 0.0, 0.0, 0.0,
    0.0, 1.0, 0.0, 0.0,
    0.0, 0.0, 1.0, 0.0,
    0.0, 0.0, 0.0, 1.0
]);
gl.uniformMatrix4fv(mvpLocation, false, IDENTITY);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, textureColorBuffer);
gl.bindVertexArray(vertexArray);
gl.drawArrays(gl.TRIANGLES, 0, 6);
// Delete WebGL resources
gl.deleteFramebuffer(framebufferRender);
gl.deleteFramebuffer(framebufferResolve);
gl.deleteRenderbuffer(colorRenderbuffer);
gl.deleteBuffer(vertexPosBuffer);
gl.deleteBuffer(vertexTexBuffer);
gl.deleteTexture(textureDiffuse);
gl.deleteTexture(textureColorBuffer);
gl.deleteProgram(program);
gl.deleteVertexArray(vertexArray);