This is the 10th day of my participation in the August Text Challenge.More challenges in August
WebGL Lesson 24: Drawing polygons | August More Text ChallengeCopy the code
The final code of this article, given in a separate article, requires friends to jump directly:Lesson 24 Code
primers
Last time, we drew a triangle with three points. The center is filled with black (actually WebGL interpolated it).
So this time, we’re going to expand and draw an n-edge, and this N-edge can be controlled by a slider on the page, immediately.
The final effect is as follows:
As we can see from the GIF above, as the number of n-sided sides increases, the shape we draw tends to be more like a circle.
This is exactly how WebGL simulates some complex curves and surfaces, that is, constant approximation. (To consider the effect and performance, do not make too many data points)
Prepare coordinate point
Let’s use the quadrilateral, or square, as an example.
Let’s look at the square first:
A square has four vertices. We divide the square into four small triangles by dividing areas.
And each triangle has three vertices, which means that we need 12 coordinate points in advance.
Let’s describe the twelve points manually, as follows:
The three points of the first triangle: OAB
Three points of the second triangle: OBC
Three points of the third triangle: OCD
The three points of the fourth triangle: ODA
Notice, I’ve been following the counterclockwise rule.
When you write the code, you’re going to do it in that order.
Write a function that generates n-sided coordinate points
Let’s write the function header first:
function GetPolyN(center, R, N) {
}
Copy the code
Center: a center
R: distance from center to vertex
N: the number of sides of a polygon
Our mindset is:
-
- Bisect a circle N and find the coordinate points of this N bisect.
-
- And then I’m going to take these N bisected points, and I’m going to pair them up with the center points, so that’s exactly three points.
-
- I’m going to flatten out all of these points
Based on the above idea, the following code is obtained:
Function GetTri(A, B, C) {return [A[0], A[1], B[0], B[1], C[0], C[1]]; function GetTri(A, B, C) {return [A[0], A[1], B[0], C[0], C[1]]; } function GetPolyN(center, R, N) {// 1. First, uniformly obtain N points on the circumference let IDx = 0; let x = 0; let y = 0; let rad = 0; let pointArr = []; for (; idx ! = N; idx++) { rad = ((2 * Math.PI) / N) * idx; x = R * Math.cos(rad) + center[0]; // Consider the length from center to vertex center y = R * math. sin(rad) + center[1]; // Consider the length from center to vertex center pointarr.push ([x, y]); } // 2. Group the N points with the center, which is exactly three points, to form N triangles. // Flat array for (idx = 0; idx ! = N; idx++) { res.push(... GetTri(pointArr[idx], pointArr[(idx + 1) % N], center)); } return res; }Copy the code
Add a slider to the page to control N
This belongs to HTML knowledge, we just write the listing code as follows:
< p > < b > N form: < / b > < input id = "N" type = "range" min = "3" Max = "100" value = "three step" = "1" the oninput = "updatefunc ()" / > < b id="Nvalue">0</b> </p>Copy the code
And notice that we set min to be 3, which is the smallest triangle that we can draw. The maximum is 100, and we’ll find out that 100 is enough to simulate a circle.
Delete and create buffers
There is a different process in this lesson, that is, when N changes, we need to regenerate the data points, and then regenerate a buffer in WebGL. In order not to cause memory leaks, we also need to delete the previous buffer.
In other words, we need to move the code that generates the buffer, the incoming data, into the updatefunc function.
The final updateFunc looks like this:
Function updatefunc() {if (buffer_id) {gl.deleteBuffer(buffer_id); } // Generate n-polyn data = GetPolyN([0, 0], 0.5, ndom.value); dataArr = new Float32Array(data); pointCount = data.length / 2; // recreate WebGL's buffer and pass the polygon points to buffer_id = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buffer_id); gl.bufferData(gl.ARRAY_BUFFER, dataArr, gl.STATIC_DRAW); // Specify the format of data gl.vertexAttribPointer(a_PointVertex, 2, gl.float, false, 0, 0); gl.enableVertexAttribArray(a_PointVertex); / *... . No changes to the code... . */ gl.clearColor(0, 0, 0, 0); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.drawArrays(gl.TRIANGLES, 0, pointCount); }Copy the code
Spend the hour live
It does make polygons, but we still don’t know if it’s made up of little triangles.
Then you might as well. Let’s separate out the little triangles, one by one, in different colors. That’s easy to see.
Ideas:
Since WE want different points, let me do it in a different color. The colors must also be passed into the WebGL buffer.
There are two approaches:
-
- Using the old buffer, as follows
[coordinate data points 1] [data points 1 color] [coordinate data points 2] [data points 2 color] [data points 3 coordinates]] [data points 3 color………………………
-
- Open a new buffer
Buffer_point buffer (old) :
[Data point 1 coordinates][Data point 2 coordinates][Data point 3 coordinates]………………
buffer_color:
[Data point 1 color][Data point 2 color][Data point 3 color]………………
Either way, I’m going to choose the second option, which is to leave the original buffer untouched and create a new buffer_color.
We know that a data point corresponds to a color, and a color is composed of RGB three fields.
So when we receive in the shader, we use vec3.
So let’s compare the coordinates, the coordinates are xy, and we just need vec2.
Vertex_shader changes
Add an attribute variable a_PointColor to vertex_shader:
attribute vec3 a_PointColor;
Copy the code
To pass the a_PointColor to fragment_shader, we must add another variable VARYING:
attribute vec3 a_PointColor;
varying vec3 color;
Copy the code
So the final vertex_shader
<script id="vertex_shader" type="myshader"> // Vertex Shader precision mediump int; precision mediump float; uniform mat3 u_all; attribute vec2 a_PointVertex; attribute vec3 a_PointColor; varying vec3 color; Void main() {vec3 coord = u_all * vec3(a_PointVertex, 1.0); Gl_Position = vec4(coord.x, coord.y, 0.0, 1.0); color = a_PointColor; } </script>Copy the code
Fragment_shader changes
Add a variable varying with the same name and use that variable as the color:
<script id="fragment_shader" type="myshader"> // Fragment shader precision mediump int; precision mediump float; varying vec3 color; Void main() {gl_FragColor = vec4(color, 1.0); } </script>Copy the code
Generates a color array for a coordinate point set
We just need to remember that each coordinate point corresponds to a color, and a color has three RGB components:
function GetRandomColor(pointCount) { let res = []; let idx = 0; for (; idx ! = pointCount; idx++) { res.push(Math.random()); //R res.push(Math.random()); //G res.push(Math.random()); //B } return res; }Copy the code
Note that our top colors are randomly generated to make them look more colorful.
The final result
The final code is not shown here, but is available directly from the link at the beginning of this article.
In fact, as long as the above said, a little save a save, on the line.
The final floral effect is as follows:
With the end of the text, here is the q&ACopy the code
Little ya ya said: I finally see colorful things!
- A: Bells and whistles!