Webgl -- start to make some real 3D objects
Original article of Lesson 4:
Http://learningwebgl.com/blog? P = 370
Case study: http://learningwebgl.com/lessons/lesson04/index.html
The difference between the code in this lesson and the previous one is completely concentrated in the animate, initbuffers and drawscene features. If you scroll down to animate, you will see some very small changes: variables, remember that the two objects in the current scenario have been renamed, they used to be rtri and rsquare, now we have:
Rpyramid + = (90 * elapsed)/1000.0;
Rcube-= (75 * elapsed)/1000.0;
This is the change. Let's look up drawscene. In the above function declaration, we have two variables with a new definition:
VaR rpyramid = 0; var rcube = 0;
Next, let's take a look at the function header, where we made corresponding modifications based on our pre-code, and then began to draw our pyramid (a three-dimensional triangle ). After completing these steps, we rotate the Y axis as we did before:
Mat4.rotate (mvmatrix, degtorad (rpyramid), [0, 1]);
Then we start to draw this image. This is the difference from the previous lesson. Easy! But because we need to make more colors here and the triangle vertices also become more, we need to use initbuffers to process more vertices and colors. Therefore, apart from the above changes, we also need to add the following code in the buffer to adapt to changes:
Gl. bindbuffer (GL. array_buffer, pyramidvertexpositionbuffer );
Gl. vertexattribpointer (shaderprogram. vertexpositionattribute, pyramidvertexpositionbuffer. itemsize, GL. Float, false, 0, 0 );
Gl. bindbuffer (GL. array_buffer, pyramidvertexcolorbuffer );
Gl. vertexattribpointer (shaderprogram. vertexcolorattribute, pyramidvertexcolorbuffer. itemsize, GL. Float, false, 0, 0 );
Setmatrixuniforms ();
Gl. drawarrays (GL. triangles, 0, pyramidvertexpositionbuffer. numitems );
Let's take a look at the code of the cube. The first step is to rotate, but it is not just the rotation of the X axis, because as you can see in the animation, the angle we want to present to the audience is (up, right, to the front ):
Mat4.rotate (mvmatrix, degtorad (rcube), [1, 1]);
PS: here we insert a small explanation: the rotate rotation is implemented in this way:
(X, y, z)
X:
Y:
Z:
The next step is to plot a cube. You can draw a cube by using the following three methods. You need to consider and select the method you choose.
1. Use a tirangle strip. If the cube is a color, the creation process is very simple. We can use vertex positions to draw a plane (that is, a plane of the cube), then add the other two points to add the other two faces. And so on to create a new surface;
2. We use a form of deception, that is, to draw our cube with six independent square faces. In this case, we need to set a good position for each face, a good color, and an independent set of fixed points. In fact, this method is the most accurate, and the results are the best. However, it also has a major drawback, which not only increases the workload of your code input, but also increases the computing cost of the computer, every time you draw a surface, you must tell the webgl template what the color is.
3. The final solution is to create two cubes as a cube (that is, to combine the two pyramid into a cube, you can understand it ). In the previous steps, we have mentioned that if you want to create a new one, you just need to create two new ones and then combine them to form a new one. This is like the method of constructing a square by using a triangle. It seems that every time we make a whole triangle (that is to say, two triangles are connected together ). By doing so, we can make our points overlap and better specify the color of each edge. Because the writing method is the most concise, we need to use this method to construct the image we want! Below we will use drawelements
If we want to construct our cubes, we need to first make the vertices and colors of the entire cube. We just create a cube like a triangle.
Initbuffers, and make it with appropriate attributes:
Gl. bindbuffer (GL. array_buffer, cubevertexpositionbuffer); Gl. vertexattribpointer (shaderprogram. vertexpositionattribute, cubevertexpositionbuffer. itemsize, GL. Float, false, 0, 0 );
Gl. bindbuffer (GL. array_buffer, cubevertexcolorbuffer); Gl. vertexattribpointer (shaderprogram. vertexcolorattribute, cubevertexcolorbuffer. itemsize, GL. Float, false, 0, 0 );
The next step is to draw a triangle. There is a problem here, you look at a square (a plane of our cube, which has four vertices), and each vertex has a color definition. When drawing this square, we need to draw it with two triangles, because we use a simple triangle, and he needs to specify his own vertex separately (specify the vertex of the triangle) and share the vertex, instead of a triangle band (tirangle strip ). That is to say, we need to specify six vertices because two of them overlap. However, in the end, we only use four of them and put them in the Array Buffer (because there is no need to say that we have to make two vertices to influence the city appearance .)
It is like "using the first three vertices (vertex) buffers to draw the triangle and then draw another one". This is what we need to do. This makes the rest of the Quartet we have drawn similar.
At this time, we will give this element a new name for the data buffer, Which is drawelement. Just as we have been using the current array buffer (Array Buffer), the value of this element's Array Buffer will be filled in inibuffers, in addition, it will arrange the vertices on the list we use. If you want to know the details, you can view the code.
To use it, make one of the element array buffers of our cube (webgl retains the Array Buffer (Array Buffer) and element array buffers (Array Buffer of the element ), so we need to keep the GL that we are currently using. bindbuffer), then we make a code to implement our model and drive our graphics card. We call this code block drawelements, and we use it to draw triangles:
Gl. bindbuffer (GL. element_array_buffer, cubevertexindexbuffer); reverse (); Gl. drawelements (GL. triangles, cubevertexindexbuffer. numitems, GL. unsigned_short, 0 );
This is the case of drawscene, and the rest of the code is for initbuffers. The name we define and the new buffer reflect the new buffer to display the object to be processed. As mentioned above, we have added a new buffer to define the vertex of the cube:
VaR pyramidvertexpositionbuffer; var pyramidvertexcolorbuffer; var cubevertexpositionbuffer; var cubevertexcolorbuffer; var cubevertexindexbuffer;
We change the values in some projects with the appropriate values, and then place them in the buffer zone at the vertex position of the triangle (pyramid:
Pyramidvertexpositionbuffer = gl. createbuffer (); GL. bindbuffer (GL. array_buffer, pyramidvertexpositionbuffer); var vertices = [// front face 0.0, 1.0, 0.0,-1.0,-1.0, 1.0, 1.0,-1.0, 1.0, // right face 0.0, 1.0, 0.0, 1.0,-1.0, 1.0, 1.0,-1.0,-1.0, // back face 0.0, 1.0, 0.0, 1.0,-1.0,-1.0,-1.0, -1.0,-1.0, // left face 0.0, 1.0, 0.0,-1.0,-1.0,-1.0,-1.0,-1.0, 1.0]; GL. bufferdata (GL. array_buffer, new float32array (vertices), GL. static_draw); pyramidvertexpositionbuffer. itemsize = 3; pyramidvertexpositionbuffer. numitems = 12;
In the same principle, here is the color buffer of the triangle:
Pyramidvertexcolorbuffer = gl. createbuffer (); GL. bindbuffer (GL. array_buffer, pyramidvertexcolorbuffer); var colors = [// front face 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, // right face 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, // back face 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, // left face 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0]; GL. bufferdata (GL. array_buffer, new float32array (colors), GL. static_draw); pyramidvertexcolorbuffer. itemsize = 4; pyramidvertexcolorbuffer. numitems = 12;
This is the buffer zone that refers to the vertex position of the cube:
Cubevertexpositionbuffer = gl. createbuffer (); GL. bindbuffer (GL. array_buffer, cubevertexpositionbuffer); vertices = [// front face-1.0,-1.0, 1.0, 1.0,-1.0,-1.0, 1.0, 1.0, 1.0,-1.0, 1.0, 1.0, // back face-1.0,-1.0,-1.0,-1.0, 1.0,-1.0, 1.0, 1.0,-1.0,-1.0,-1.0, // top face-1.0, 1.0,-1.0,-1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,-1.0, // bottom face-1.0, -1.0,-1.0, 1.0,-1.0,-1.0, 1.0,-1.0, 1.0,-1.0,-1.0, 1.0, // right face 1.0,-1.0, -1.0, 1.0, 1.0,-1.0, 1.0, 1.0, 1.0, 1.0,-1.0, 1.0, // left face-1.0,-1.0,-1.0,-1.0, -1.0, 1.0,-1.0, 1.0, 1.0,-1.0, 1.0,-1.0,]; GL. bufferdata (GL. array_buffer, new float32array (vertices), GL. static_draw); cubevertexpositionbuffer. itemsize = 3; cubevertexpositionbuffer. numitems = 24;
However, the color buffer of the cube is slightly more complicated during design. Here, we want to create a color list by creating a loop, so we do not need to say that each color must be specified four times repeatedly:
Cubevertexcolorbuffer = gl. createbuffer (); GL. bindbuffer (GL. array_buffer, cubevertexcolorbuffer); colors = [[1.0, 0.0, 0.0, 1.0], // front face [1.0, 1.0, 0.0, 1.0], // back face [0.0, 1.0, 0.0, 1.0], // top face [1.0, 0.5, 0.5, 1.0], // bottom face [1.0, 0.0, 1.0, 1.0], // right face [0.0, 0.0, 1.0, 1.0], // left face]; var unpackedcolors = []; for (var I in colors) {var color = colors [I]; for (VAR J = 0; j <4; j ++) {unpackedcolors = unpackedcolors. concat (color) ;}} GL. bufferdata (GL. array_buffer, new float32array (unpackedcolors), GL. static_draw); cubevertexcolorbuffer. itemsize = 4; cubevertexcolorbuffer. numitems = 24;
Finally, we define the Array Buffer.
Cubevertexindexbuffer = gl. createbuffer (); GL. bindbuffer (GL. element_array_buffer, cubevertexindexbuffer); var cubevertexindices = [0, 1, 2, 0, 2, 3, // front face 4, 5, 6, 4, 6, 7, // back face 8, 9, 10, 8, 10, 11, // top face 12, 13, 14, 12, 14, 15, // bottom face 16, 17, 18, 16, 18, 19, // right face 20, 21, 22, 20, 22, 23 // left face] GL. bufferdata (GL. element_array_buffer, new uint16array (cubevertexindices), GL. static_draw); cubevertexindexbuffer. itemsize = 1; cubevertexindexbuffer. numitems = 36;
Here, you should note the number of each buffer zone, because it is used to index the vertex position and the vertex color. Therefore, we can combine the tips here to draw the drawscene of a triangle, successfully using Vertex 0, 1, 2 of the triangle, and then using, 3. Because the two triangles are of the same color and they are adjacent, the vertices of the obtained Square are 0, 1, 2, and 3. Repeat the related steps to create a cube.