[WebGL Primer] 18, drawing with index cache

Source: Internet
Author: User

Note: The article is translated from http://wgld.org/, the original author Sambonja 広 (doxas), the article if there is my additional instructions, I will add [Lufy:], in addition, The WEBGL research is not deep enough, some professional words, if the translation is wrong, you are welcome to correct.



The results of this demo run


correspond to complex models

Last, by manipulating the model coordinate transformation matrix, we realized the movement, rotation and zoom reduction of multiple models. However, the rendering is still a simple triangle, a construct and a simple model.
But in practice, the chance to draw a simple triangle with WEBGL is rare. At least a four-sided polygon, usually a more complex model.
With the complexity of the model, the number of vertices will also increase greatly, the more precise the smooth model, the amount of vertices required will also become hypertrophy. There is no limit in JavaScript, nor is it to save memory or to save code, and to draw these large numbers of vertex data directly is not a no-no, but the idea of reducing the amount of data as much as possible is the programmer's nature.
In WebGL, there is a way to prevent the hypertrophy of vertex data by using an index cache to manage vertex data. The index cache is also called IBO (index buffer objact), which is a cache. Also, similar caches that have been used so far have been used by Vbo,ibo General and VBO.


increase of vertices As you just said, the more vertices you add, the greater the amount of vertex data you manage. However, you can use a small number of vertices repeatedly to form polygons.
Let's take a look at the concrete examples.
Polygons are made up of triangles, such as a rectangle that consists of two triangles.

So how many vertices do you need at this time?
Look at the picture just now, need four vertices, and define a triangle requires three vertices, two polygons, it is supposed to need six vertices.
Vertex coordinate intelligence is exactly the same, and if repeated vertices are defined multiple times, it is obviously wasteful. Therefore, the reuse of vertices should be considered.

Re-use of repeated vertices, minimizing vertex data, when the vertex cache appears. The vertex cache, which is used to hold the index information of the vertex. Like the previous figure, the first polygon uses the three vertices of [1, 2, 3], and similarly, the second polygon uses 2 vertices of [3, 4, three].
This way, when you draw a polygon to tell WebGL which vertices to use is the vertex index, this time the quadrilateral effect is not obvious, and the larger the complex model, the role of using the index cache will be greater.
With the index cache, there is also a significant benefit in addition to the amount of code saved.
With index caching, you can use the GPU's memory directly, without having to pass data to the GPU every time you draw, so it's faster.
Ability to save code and achieve high speed, so there is no reason not to use IBO.


generation of Ibo The build step for the index cache is similar to the vertex cache, although there are several parameters that vary, but are essentially the same process.
This time the demo has a new definition of a Create_ibo function, take a look at the code.
> Custom Function Create_ibo

Ibo generation function Create_ibo (data) {    //Generate Cache object    var ibo = Gl.createbuffer ();        Bind Cache    Gl.bindbuffer (GL. Element_array_buffer, IBO);        Writes data to the cache    Gl.bufferdata (GL. Element_array_buffer, new Int16array (data), GL. Static_draw);        Invalidates the cached binding    Gl.bindbuffer (GL. Element_array_buffer, null);        Returns the generated IBO    return IBO;}

As with generating VBO, first use the Createbuffer function to generate an empty cache object, then bind the cache, and the first parameter of the Bindbuffer function is a built-in constant GL that is not the same as VBO. Element_array_buffer, specifies that the cache generated by this constant is IBO.
Then bind the cache and write the data, when VBO, the parameters passed in is the Float32array type of data, but the index cache uses not floating-point decimals, but integers, so this is the Int16array type of data.
This custom function Create_ibo, the passed parameter is an array, and the function that generates VBO CREATE_VBO is the same. The array data used by IBO is defined in advance, as well as VBO.
> Examples of array definitions for index data

var index = [    0, 1, 2,    1, 2, 3];

With four vertices, like the one above, the first triangle uses vertices [0, 1, 2], and the second triangle uses vertices [1, 2, 3] to draw the meaning. The index of the vertex is starting at 0, and it is important to note that the array is a one-dimensional array.


drawing-related change points Learn about the generation of index caches, and then take a look at the steps used for index caching.
Using IBO for rendering requires binding IBO and WebGL in advance, which can be done with the following code.
>ibo-bound Code

Gl.bindbuffer (GL. Element_array_buffer, IBO);
passing in the generated IBO (variable IBO), this completes the binding of the IBO, but the binding IBO, there is no way to draw, but also need to modify the drawing command.
So far, the rendered polygon has been using the Drawarrays function, and in order to draw with IBO, you need to use the Drawelements function. Examples of using this function are as follows.
> Examples of drawing commands using the Drawelements function
Gl.drawelements (GL. Triangles, Index.length, GL. Unsigned_short, 0);
This drawelements function has four parameters, the first parameter is the constant that represents what vertex is rendered, the second parameter is the number of elements in the index cache, the third parameter is the data size of the index data, and the fourth parameter is the index offset of the indexed data.
more difficult to understand is the second parameter, here, the input to save the index of the array length of the data can be, the other parameters there is no special restrictions, do not modify the use of the words on the line.


Summaryusing the index cache IBO can save data and improve the efficiency of rendered vertices, and the more complex the model, the greater the impact, which programmers would love to see.
The index cache, like the vertex cache, can be generated using a purely one-dimensional array, the resulting IBO can be used after binding, and using the Drawelements function is the focus when drawing with IBO.
This time the demo, vertex shader and fragment shader is no change, so, also use the previous HTML code, JavaScript content some changes, the final will give the complete code, in addition, the article will be posted at the end of this demo link, you can refer to.


next time, we will introduce the occlusion culling and depth.


Complete code for >script.js

onload = function () {//Canvas object gets var c = document.getElementById (' canvas ');    C.width = 500;        C.height = 300; WebGL context gets var gl = c.getcontext (' WebGL ') | |        C.getcontext (' Experimental-webgl ');    Generation of vertex shader and fragment shader var v_shader = Create_shader (' vs ');        var f_shader = Create_shader (' FS ');        Program object generation and connection var PRG = Create_program (V_shader, F_shader);    Attributelocation gets the var attlocation = new Array (2);    Attlocation[0] = gl.getattriblocation (PRG, ' position ');        ATTLOCATION[1] = gl.getattriblocation (PRG, ' color ');    Save the number of elements attribute to the array var attstride = new Array (2);    Attstride[0] = 3;        ATTSTRIDE[1] = 4; Save the vertex's color information array var position = [0.0, 1.0, 0.0, 1.0, 0.0, 0.0,-1.0, 0.0, 0.0, 0.0 ,-1.0, 0.0];//The array of color information that holds the vertex var color = [1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0        , 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]; Array of index of the saved Vertex vAR index = [0, 1, 2, 1, 2, 3];    Generate VBO var Pos_vbo = Create_vbo (position);        var Col_vbo = Create_vbo (color);        Bind Vbo and add Set_attribute ([Pos_vbo, Col_vbo], attlocation, attstride);        Generate IBO var IBO = Create_ibo (index); IBO to bind and add Gl.bindbuffer (GL.        Element_array_buffer, IBO);        Uniformlocationの obtained var unilocation = gl.getuniformlocation (PRG, ' Mvpmatrix ');        Generate var m = new Mativ () using minmatrix.js to the related processing//Mativ object of the matrix;    Generation and initialization of various matrices var Mmatrix = m.identity (M.create ());    var Vmatrix = m.identity (M.create ());    var PMatrix = m.identity (M.create ());    var Tmpmatrix = m.identity (M.create ());        var Mvpmatrix = m.identity (M.create ());    View x projection coordinate transformation matrix M.lookat ([0.0, 0.0, 5.0], [0, 0, 0], [0, 1, 0], Vmatrix);    M.perspective (GB, C.width/c.height, 0.1, PMatrix);        M.multiply (PMatrix, Vmatrix, Tmpmatrix);        Defines the counter var count = 0; Continuous cycle (function () {// Canvasを initial Gl.clearcolor (0.0, 0.0, 0.0, 1.0);        Gl.cleardepth (1.0); Gl.clear (GL. Color_buffer_bit | Gl.                Depth_buffer_bit);                The counter increments count++;                Use counter to calculate the angle var rad = (count%) * MATH.PI/180;        The generation of model coordinate transformation matrices (rotated along the y axis) m.identity (Mmatrix);        M.rotate (Mmatrix, Rad, [0, 1, 0], Mmatrix);        M.multiply (Tmpmatrix, Mmatrix, Mvpmatrix);                GL.UNIFORMMATRIX4FV (Unilocation, False, Mvpmatrix); Use the index for drawing gl.drawelements (GL. Triangles, Index.length, GL.                Unsigned_short, 0);                Context refresh Gl.flush ();    In order to cycle, the recursive processing setTimeout (Arguments.callee, 1000/30);        })();                    Generate Shader function Create_shader (ID) {//variable var shader to hold the shader;                    Gets the specified script tag from HTML based on id var scriptelement = document.getElementById (ID); If the specified script tag does not exist, returns if (!scriptelement) {return;}                    When you determine the Type property of the script tag, switch (scriptelement.type) {//vertex shader) Case ' X-shader/x-vertex ': shader = Gl.createshader (gl.                  Vertex_shader);                                Break Fragment shader when case ' x-shader/x-fragment ': shader = Gl.createshader (gl.                  Fragment_shader);              Break          Default:return;                    }//Assign the code in the tag to the generated shader Gl.shadersource (shader, Scriptelement.text);                    Compiler shader Gl.compileshader (shader); Determine if the shader compiles successfully if (Gl.getshaderparameter (shader, GL.          Compile_status)) {//compile successfully, return the shader return shader;          }else{//compilation failed, pop-up error message alert (Gl.getshaderinfolog (shader)); }}///program object generation and shader connection function Create_program (VS, FS) {//program Object generation var programs = Gl.createprogram ();          Assigns shader Gl.attachshader (program, VS) to the Application object;                    Gl.attachshader (program, FS);                    Connect the shader to the Gl.linkprogram (program); Determines if the connection to the shader is successful if (Gl.getprogramparameter (program, GL).                            Link_status)) {//successfully set the program object to a valid Gl.useprogram (Programs);          Returns the program object return to Programs;          }else{//If failed, pop-up error message alert (Gl.getprograminfolog (program));                    }}//Generate VBO function Create_vbo (data) {//Generate cache object var Vbo = Gl.createbuffer (); Bind Cache Gl.bindbuffer (GL.                    Array_buffer, VBO); Writes data to the cache Gl.bufferdata (GL. Array_buffer, new Float32array (data), GL.                    Static_draw); Set the bound cache to an invalid Gl.bindbuffer (GL.                    Array_buffer, NULL); Returns the buildThe Vbo return VBO; }//Bind VBO related functions function Set_attribute (VBO, Attl, Atts) {//Handle the array obtained from the parameter for (var i in Vbo) {//Bind Fixed cache Gl.bindbuffer (GL.                    Array_buffer, Vbo[i]);                    Set Attributelocation to valid Gl.enablevertexattribarray (Attl[i]); Notify and add Attributelocation gl.vertexattribpointer (Attl[i], atts[i], GL.      FLOAT, False, 0, 0);        }}//IBO Generate function Create_ibo (data) {//Generate cache object var ibo = Gl.createbuffer (); Bind Cache Gl.bindbuffer (GL.        Element_array_buffer, IBO); Writes data to the cache Gl.bufferdata (GL. Element_array_buffer, new Int16array (data), GL.        Static_draw); Invalidates the cached binding Gl.bindbuffer (GL.        Element_array_buffer, NULL); Returns the generated IBO return IBO;};

Demo with index cache (IBO) drawing

http://wgld.org/s/sample_006/


reprint Please specify: transfer from Lufy_legend's blog Http://blog.csdn.net/lufy_legend

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.