Multi-Level Image Processing (FrameBuffer) in WebGL ),

Source: Internet
Author: User

Multi-Level Image Processing (FrameBuffer) in WebGL ),

When using webgl, we usually want to perform multi-level processing on texture and display it on the surface.

For more precise edge detection, gray-scale shader, fuzzy shader, and edge shader must be used for processing, and each processing object is the last processed texture, this will overwrite and save the processed results.

 

Among the many webgl libraries, there is a direct option rederToTarget to render the texture after the shader processing and overwrite the original texture. How does one complete this step?

This leads to the main character of this article-FrameBuffer

 

What is FrameBuffer?

 

FBO (Frame Buffer Object) is an extension recommended for rendering data to a texture Object.

FrameBuffer is like a webgl display container. We usually use gl. drawArrays or gl. drawElements draws the object in the default window. When we specify a FrameBuffer as the current window, we use these two methods to draw the object, the object is drawn in the specified FrameBuffer.

 

Use of FrameBuffer

 

Internalformat, int x, int y, sizei width,
Sizei height, int border );
Target: TEXTURE_2D, TEXTURE _

FBO creation:

// Create a Framebuffervar fb = gl. createFramebuffer (); // bind the fb to the current window gl. bindFramebuffer (gl. FRAMEBUFFER, fb );

 

In this way, we have created a new buffer that can be drawn and it will not be displayed.

But can this be done? What we think of is to render the texture after the shader rendering and hand it to the next shader. Then the method framebufferTexture2D is introduced.

Reference from OpenGL ES Reference Pages about FramebufferTexture2D:

 

To render directly into a texture image, a specified image from a texture object can be attached as one of the logical buffers of the currently bound framebuffer object by calling the command

To render the image directly to a texture image, the image specified in a texture object can be bound to a logical cache on the currently used FBO using the following method.

Void FramebufferTexture2D (enum target, enum attachment, enum textarget, uint texture, int level );

 

Target:

• FRAMEBUFFER

Attachment:

• If attachment is COLOR_ATTACHMENT0, then image must have a colorrenderable internal format. (color)

• If attachment is DEPTH_ATTACHMENT, then image must have a depthrenderable internal format. (depth)

• If attachment is STENCIL_ATTACHMENT, then image must have a stencilrenderable internal format. (Template)

Textarget:

• TEXTURE_2D (two-dimen1_texture)

• TEXTURE_CUBE_MAP_POSITIVE_X (three-dimenure + x texture)

• TEXTURE_CUBE_MAP_POSITIVE_Y (three-dimenure + y texture)

• TEXTURE_CUBE_MAP_POSITIVE_Z (three-dimenure + z texture)

• TEXTURE_CUBE_MAP_NEGATIVE_X (three-dimen1_x texture)

• TEXTURE_CUBE_MAP_NEGATIVE_Y (three-dimen1_- y texture)

• TEXTURE_CUBE_MAP_NEGATIVE_Z (three-dimen1_- z texture)

Texture:

Texture object

Level:

Specifies the mipmap level of the texture image to be attached to the framebuffer and must be 0.

 

We use this method for binding (this article only describes the binding of colors, and tries to be similar to the template, but there are differences, not discussed here)

// Create a texture object var texture = gl. createTexture (); // use the following settings to create texture. In this way, texture settings allow us to process images of any size in gl. bindTexture (gl. TEXTURE_2D, texture); gl. texParameteri (gl. TEXTURE_2D, gl. TEXTURE_WRAP_S, gl. CLAMP_TO_EDGE); gl. texParameteri (gl. TEXTURE_2D, gl. TEXTURE_WRAP_T, gl. CLAMP_TO_EDGE); gl. texParameteri (gl. TEXTURE_2D, gl. TEXTURE_MIN_FILTER, gl. NEAREST); gl. texParameteri (gl. TEXTURE_2D, gl. TEXTURE_MAG_FILTER, gl. NEAREST );
Var fb = gl. createFramebuffer (); gl. bindFramebuffer (gl. FRAMEBUFFER, fb); // use this method to bind the color value of texture to FBO gl. framebufferTexture2D (gl. FRAMEBUFFER, gl. COLOR_ATTACHMENT0, gl. TEXTURE_2D, texture, 0 );

 

After binding, when we execute gl. drawArrays or gl. when the drawElements method is used, it will be directly rendered to the currently bound FBO, and FBO is bound to the texture color, so the color will also be rendered to texture during painting.

In this way, we can use two fbrs for queue processing:

OriginalImage --> texture1

Texture1 --> gray --> texture2

Texture2 --> blur --> texture1

Texture1 --> edge --> texture2

 

The specific implementation process is as follows:

var FBOs = [],    textures = [];    for(var i = 0; i < 2; i++){    var texture = gl.createTexture();    gl.bindTexture(gl.TEXTURE_2D, texture);    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);    var fb = gl.createFramebuffer();    gl.bindFramebuffer(gl.FRAMEBUFFER,fb);    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);        //store corresponding texture and fb    textures.push(texture);    FBOs.push(fb);}gl.bindTexture(gl.TEXTURE_2D, originalImageTexture);for(var i = 0; i < 3; i++){    switch(i){case 0:            //set gray shader to current shader program            //handle arguments to vs shader and fs shader            break;        case 1:            //set blur shader to current shader program            //handle arguments to vs shader and fs shader            break;        case 2:            //set edge shader to current shader program            //handle arguments to vs shader and fs shader            break;    }        gl.bindFramebuffer(gl.FRAMEBUFFER, FBOs[i%2]);    //set the viewport fits the images size    gl.viewport(0, 0, imgWidth, imgHeight);    gl.drawArrays(....); //or gl.drawElements(....);        //set the rendered texture to current texture for next frambuffer using    gl.bindTexture(gl.TEXTURE_2D, texture[i%2]);}

 

The complete process is:

originalTexture --> gray program --> set FBO1 --> draw --> FBO1 --> set texture1texture1 --> blur program --> set FBO2 --> draw --> FBO2 --> set texture2texture2 --> edge program --> set FBO1 --> draw --> FBO1 --> set texture1

 

In this process, FBO1 and texture1 are color rendering bound, so after set FBO1 is rendered, it will be directly rendered to texture1

When we finish the entire painting, we need to display the processed image normally, then we need to jump out of FBO:

//set FBO to null to use default framebuffergl.bindFramebuffer(gl.FRAMEBUFFER, null);

 

Other functions of FrameBuffer

 

Gl. readPixels

Read pixel color data from FrameBuffer

Reference from 《webgl_2.0_reference_card》/《OpenGL ES Reference Pages about readPixels》:

 

Pixels in the current framebuffercan be read back into an ArrayBufferView object.

void readPixels(int x, int y, long width, long height,enum format, enum type, Object pixels)

 

x,y

• Specify the window coordinates of the first pixel that is read from the frame buffer. This location is the lower left corner of a rectangular block of pixels.

width,height

 

• Specify the dimensions of the pixel rectangle. width and height of one correspond to a single pixel.

format

• Specifies the format of the pixel data. The following symbolic values are accepted  RGBA in WebGL

type

• Specifies the data type of the pixel data. Must be UNSIGNED_BYTEin WebGL

pixels

  • Returns the pixel data.

 

 

During use, we need to create a pixels object to store data.

//using ArrayBufferView to store pixels data only, Unit8Array is the best because each color data is a bytevar pixels = new Uint8Array(ImageWidth * ImageHeight * 4);gl.readPixels(0, 0, ImageWidth, ImageHeight, gl.RGBA, gl.UNSIGNED_BYTE, pixels);

 

In this way, we can obtain the color data of the entire FBO.

 

Gl. CopyTexImage2D Gl. CopyTexSubImage2D

Both functions are used to copy data from FBO to the currently bound texture

CopyTexImage2D method:

Reference from 《OpenGL ES Reference Pages about CopyTexImage2D》:

 

copy pixels into a 2D texture image

void CopyTexImage2D(enum target, int level,enum internalformat, int x, int y, sizei width,sizei height, int border);

 

target:

• TEXTURE_2D

• TEXTURE_CUBE_MAP_POSITIVE_{X, Y, Z},

• TEXTURE_CUBE_MAP_NEGATIVE_{X, Y, Z}

internalformat:

• ALPHA

• LUMINANCE

• LUMINANCE_ALPHA

• RGB

• RGBA

x,y

Specify the window coordinates of the lower left corner of the rectangular region of pixels to be copied.

width

Specifies the width of the texture image. Must be 0 or 2 n + 2  border for some integer n.

height

Specifies the height of the texture image. Must be 0 or 2 m + 2  border for some integer m.

border

Specifies the width of the border. Must be either 0 or 1.

CopyTexSubImage2D method:

Reference from 《OpenGL ES Reference Pages about CopyTexSubImage2D》:

 

copy a two-dimensional texture subimage

void CopyTexSubImage2D(enum target, int level, int xoffset,int yoffset, int x, int y, sizei width, sizei height);

 

target:

• TEXTURE_2D

• TEXTURE_CUBE_MAP_POSITIVE_{X, Y, Z},

• TEXTURE_CUBE_MAP_NEGATIVE_{X, Y, Z}

level:

Specifies the level-of-detail number. Level 0 is the base image level. Level n is the nth mipmap reduction image.

xoffset:

Specifies a texel offset in the x direction within the texture array.

yoffset:

Specifies a texel offset in the y direction within the texture array.

x,y:

Specify the window coordinates of the lower left corner of the rectangular region of pixels to be copied.

width:

Specifies the width of the texture subimage.

height:

Specifies the height of the texture subimage.

The differences between the two methods are as follows:

 

CopyTexSubImage2D adds offset to CopyTexImage2D to change the copy region.

The final copying region is [x, xoffset + width-1] and [y, yoffset + height-1].

 

CopyTexImage2D has an internelformat parameter greater than CopyTexSubImage2D to control the types of pixel data replication.

 

Conclusion:

With flexible texture operations, we can make more interesting things, And framebuffer is also a very important role in it.

  Appendix:

WebGL-1.0 reference card: http://files.cnblogs.com/files/zhiyishou/webgl-reference-card-1_0.pdf

OpenGL-ES-2.0 reference card: http://files.cnblogs.com/files/zhiyishou/OpenGL-ES-2_0-Reference-card.pdf

OpenGL-ES-2.0 Reference Manual: https://www.khronos.org/opengles/sdk/docs/man/

 

The end.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.