how webgl draws a rectangle

how webgl draws a rectangle

There are many ways to draw rectangles. The following is my summary of 5 drawing methods. The drawing of the rectangle is based on the triangle. So the code hasn't changed much. The only difference is that the number of vertices required is different when constructing the data.

  • Vertex shader code
<script id= "vertexShader" type= "x-shader/x-vertex" > //attribute declares vec3 type variable apos attribute vec3 apos; void main () { //Assign vertex coordinates apos to the built-in variable gl_Position //Process data per vertex gl_Position = vec4(apos, 1.0 ); } </script> Copy code
  • Fragment shader code
<script id= "fragmentShader" type= "x-shader/x-fragment" > void main () { //Process data fragment by fragment, all fragments (pixels) are set to red gl_FragColor = vec4( 1.0 , 0.0 , 0.0 , 1.0 ); } </script> Copy code
  • javascript code part
    • WebGL
      Context acquisition
    function init () { const canvas = document .getElementById( 'webgl' ); const gl = canvas.getContext( 'webgl' ); //Create a shader program const program = initShader(gl); const count = assignValue(gl,program); render(gl,count); } Copy code
    • Declare the initialization shader function
    function initShader ( gl ) { //Vertex shader source code const vertexShaderSource = document .getElementById( 'vertexShader' ).innerText; //Fragment shader source code const fragmentShaderSource = document .getElementById( 'fragmentShader' ).innerText; const vertexShader = gl.createShader(gl.VERTEX_SHADER); const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(vertexShader, vertexShaderSource); gl.shaderSource(fragmentShader, fragmentShaderSource); gl.compileShader(vertexShader); gl.compileShader(fragmentShader); var program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.linkProgram(program); gl.useProgram(program); return program; } Copy code
    • Shader code variable assignment
    //Define the 4 triangles that make up the rectangle, with a total of 6 vertices, the left triangle V0->V1->V2; the lower triangle V0->V4->V1; the right triangle V0->V3->V4; the upper triangle V0-> V4-V1. const Positions = new new Float32Array ([ //V0 - 0.5 , 0.5 , 1.0 , 1.0 , 0.0 , 1.0 , //Vl 0.5 , 0.5 , 1.0 , 0.0 , 0.0 , 1.0 , //V2 0.5 , - 0.5 , 1.0 , 1.0 , 0.0 ,1.0, //V3 - 0.5 , 0.5 , 1.0 , 0.0 , 0.0 , 1.0 , //V4 0.5 , - 0.5 , 0.0 , 0.0 , 1.0 , 1.0 , //V5 - 0.5 , - 0.5 , 0.0 , 1.0 , 0.0 , 1.0 , ]); const a_Position = gl.getAttribLocation(program, 'a_Position' ); const a_Color = gl.getAttribLocation(program, 'a_Color' ); gl.enableVertexAttribArray(a_Position); gl.enableVertexAttribArray(a_Color); //Create a buffer let buffer = gl.createBuffer(); //Bind the buffer to the current buffer gl.bindBuffer(gl.ARRAY_BUFFER, buffer); //Set the a_Position attribute to read data from the buffer mode gl.vertexAttribPointer(a_Position, 2 , gl.FLOAT, false , 24 , 0 ); //Set the a_Color attribute to read data from the buffer mode gl.vertexAttribPointer(a_Color, 4 , gl.FLOAT, false , 24 , 8 ); //Pass data to the buffer gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW); return positions.length/6 ; copy the code
    • WebGL
      Rendering function
    function render ( program, gl ) { //Get the location variable apos of the vertex shader, that is, aposLocation points to the apos variable. const aposLocation = gl.getAttribLocation(program, "apos" ); //Type array constructor Float32Array creates vertex array const data = new Float32Array ([ - 0.5 , 0.5 , 0.0 , 0.5 , 0.5 , 0.0 , 0.5 , - 0.5 , 0.0 , - 0.5 , 0.5 , 0.0 , 0.5 , - 0.5 , 0.0 , - 0.5 , - 0.5 , 0.0 , ]); //Create a buffer object const buffer = gl.createBuffer(); //Bind the buffer object and activate the buffer gl.bindBuffer(gl.ARRAY_BUFFER, buffer); //Vertex array data data is transferred to the buffer gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW); //Allow data transfer gl.enableVertexAttribArray(aposLocation); //The data in the buffer is transferred to the location variable according to certain rules apos gl.vertexAttribPointer(aposLocation, 3 , gl.FLOAT, false , 0 , 0 ); //Set the color of the canvas gl.clearColor( 0.0 , 0.0 , 0.0 , 0.3 ); gl.clear(gl.COLOR_BUFFER_BIT); //Start drawing graphics data.length/3 indicates the number of top data gl.drawArrays(gl.TRIANGLES, 0 , data.length/3 ); } Copy code

The main difference between the following methods of drawing rectangles lies in the data structure and drawing methods .

1. Conventional way

  • Data structure
//definition of the composition of the four rectangular triangles, a total of six vertices of the let Positions = new new Float32Array ([ @ V0 - 0.5 , 0.5 , 1.0 , 1.0 , 0.0 , 1.0 , //Vl 0.5 , 0.5 , 1.0 , 0.0 , 0.0 , 1.0 , //V2 0.5 , - 0.5 , 1.0 , 1.0 , 0.0 , 1.0 , //V3 - 0.5 ,0.5 , 1.0 , 0.0 , 0.0 , 1.0 , //V4 0.5 , - 0.5 , 0.0 , 0.0 , 1.0 , 1.0 , //V5 - 0.5 , - 0.5 , 0.0 , 1.0 , 0.0 , 1.0 , ]); Copy code
  • Drawing method
//start the shape data.length/3 represents the number of data Digg gl.drawArrays (gl.TRIANGLES, 0 , data.length/. 3 ); duplicated code

The renderings are as follows:

2. Triangular fan

In this drawing method, when drawing a triangle, draw the first two vertices of the next triangle. The first vertex is the first vertex of the triangle, and the second vertex is the last vertex of the previous triangle.

  • Data structure
//definition of the composition of the four rectangular triangles, a total of six vertices of the let Positions = new new Float32Array ([ @ V0 - 0.5 , 0.5 , 1.0 , 1.0 , 0.0 , 1.0 , //Vl 0.5 , 0.5 , 1.0 , 0.0 , 0.0 , 1.0 , //V2 0.5 , - 0.5 , 1.0 , 1.0 , 0.0 , 1.0 , //V3 - 0.5 , -0.5 , 0.0 , 1.0 , 0.0 , 1.0 , ]); Copy code
  • Drawing method
//start the shape data.length/3 is the number of data and best of gl.drawArrays (gl.TRIANGLE_FAN, 0 , data.length/. 3 ); duplicated code

The renderings are as follows:

3. Triangular belt

In this drawing method, when drawing a triangle, the first two vertices of the next triangle are drawn as the last two vertices of the previous triangle.

  • Data structure
//definition of the composition of the four rectangular triangles, a total of six vertices const Positions = new new Float32Array ([ @ V0 0.5 , 0.5 , 1.0 , 0.0 , 0.0 , 1.0 , //Vl - 0.5 , 0.5 , 1.0 , 1.0 , 0.0 , 1.0 , //V2 0.5 , - 0.5 , 1.0 , 1.0 , 0.0 , 1.0 , //V3 - 0.5 , -0.5 , 0.0 , 1.0 , 0.0 , 1.0 , ]); Copy code
  • Drawing method
//Draw method of each row of six data gl.drawArrays (gl.TRIANGLE_STRIP, 0 , positions.length/. 6 ); duplicated code

The renderings are as follows:

4. Close the line segment

  • Data structure
//define the four vertices of a rectangle composed const Positions = new new Float32Array ([ @ V0 0.5 , 0.5 , 1.0 , 0.0 , 0.0 , 1.0 , //Vl - 0.5 , 0.5 , 1.0 , 1.0 , 0.0 , 1.0 , //V2 - 0.5 , - 0.5 , 0.0 , 1.0 , 0.0 , 1.0 , //V3 0.5 , - 0.5, 1.0 , 1.0 , 0.0 , 1.0 , ]); Copy code
  • Drawing method
//Draw method of each row of six data gl.drawArrays (gl.LINE_LOOP, 0 , positions.length/. 6 ); duplicated code

5. Vertex index

The difference between the vertex index and the above is the structure and rendering of the buffer data.

  • Data structure
//Create a buffer function assignValue ( GL, Program ) { //definition of the composition of the four rectangular triangles, a total of six vertices const Positions = new new Float32Array ([ @ V0 - 0.5 , 0.5 , 1.0 , 1.0 , 0.0 , 1.0 , //V1 0.5 , 0.5 , 1.0 , 0.0 , 0.0 , 1.0 , //V2 0.5 , -0.5 , 1.0 , 1.0, 0.0 , 1.0 , //V3 - 0.5 , - 0.5 , 0.0 , 1.0 , 0.0 , 1.0 , ]); //Create vertex buffer object let vertexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW); const indexes = new Uint8Array ([ 0 , 1 , 2 , 0 , 2 , 3 ]); //Create index buffer object var indexesBuffer = gl.createBuffer(); //Binding buffer object gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexesBuffer); //The index array indexes data is transferred to the buffer gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indexes, gl.STATIC_DRAW); let a_Position = gl.getAttribLocation(program, 'a_Position' ); let a_Color = gl.getAttribLocation(program, 'a_Color' ); gl.enableVertexAttribArray(a_Position); gl.enableVertexAttribArray(a_Color); //Set the a_Position attribute to read data from the buffer mode gl.vertexAttribPointer(a_Position, 2 , gl.FLOAT, false , 24 , 0 ); //Set the a_Color attribute to read data from the buffer mode gl.vertexAttribPointer(a_Color, 4 , gl.FLOAT, false , 24 , 8 ); return indexes.length; } Copy code
  • Drawing method
//Drawing method This count represents the number of i index data count=indexes.length gl.drawElements(gl.TRIANGLES, count, gl.UNSIGNED_BYTE, 0); Copy code

The renderings are as follows:

reference

WebGL zero-based introductory tutorial (Guo Longbang) ;
WebGL introduction and practiceWebGL
official document