WebGL lesson 30: parameter adjustment of multiple painting objects - color

Posted by tmharrison on Thu, 04 Nov 2021 14:08:05 +0100


In the previous article, we can see that if we want to change the parameters of an object among multiple painting objects, we directly re apply for the buffer in the gl, and then re pass all vertex data into the buffer to paint.

This method is mainly used when the vertex data has to be changed. For example, you originally drew something in the shape of a grid, but you need to turn it into a sphere. In this case, it is possible to directly replace the new vertex data.

However, sometimes we don't want to make the grid -- > spherical, just want to change the color of the grid. For this reason, it's certainly not good to replace the vertex data as a whole.

Then what shall I do? Use the uniform variable in the shader.

program uniform buffer clarify relationship

Here, review the relationship between program and uniform and buffer.

When we draw the triangle, it is simple to say: when you call the drawing api (for example, gl.drawArrays), you must select a program, then call api, and then program starts running. How do you run? A: iterate the data in the current buffer, such as coordinates, colors and so on, and then draw a point on the screen. For every three points, use the interpolation method to draw the middle area, that is, draw a triangle, so as to draw all the data in a buffer. Before this process, you can set the uniform variable, and this variable will remain unchanged during the drawing process. When the data drawing of a buffer is finished, you can change the uniform variable at any time, and then draw.

Did you find out? In other words, data from different buffers can share a program, but when switching buffers, we can modify the uniform variable to get our purpose, that is, some parameters of different drawing objects can be controlled freely and independently, such as color.

Did you find out again? In this way, there is no need to regenerate buffer data. What a good idea!

Use uniform to set the color

The first step is in the fragment_ A uniform variable is added to the shader. According to custom, we name it: u_color.

Since the color is composed of three RGB numbers, this u_color should be a vec3 type:

    uniform vec3 u_color;
Copy code

Then you need to get the uniform variable reference in the js code:

    u_color = gl.getUniformLocation(program, "u_color");
Copy code

Note that to get a reference to a variable, you need to pass it to program, which just shows that uniform belongs to program.

How do I pass values to this variable? As follows:

        gl.uniform3f(u_color, this.color.R, this.color.G, this.color.B);
Copy code

Notice here, because u_ The color variable is of vec3 type, so when passing values, you need to use the api uniform3f. Later, you need to pass three parameters, representing the first element, the second element and the third element of vec3.

The three values here represent the color RGB.

Well, let's think about this U_ To make color effective, you need to really set the following colors:

      gl_FragColor = vec4(u_color, 1.0);
Copy code

Looking at the code above, we completely use the uniform variable to set the color, ignoring the color part in the buffer. Therefore, when we construct the buffer, we don't need to pass in the color.

    Here's a point, buffer Whether it should be colored or not depends on your needs. Most of the time, buffer It should be colored in. 
    We can use uniform This dynamic variable, and buffer The static colors in are superimposed to get a fun effect.
    I'll talk about that later.
Copy code

Draw multiple grids

In the last article, we defined a GridObject class to describe the behavior of a grid.

According to the new method proposed in this paper, the render method needs to be modified as follows:

    render(gl, program) {
        gl.bindBuffer(gl.ARRAY_BUFFER, this.glbuffer);
        if (this.modelUpdated) {
            this.modelUpdated = false;
            if (this.a_PointVertex == null) {
                this.a_PointVertex = gl.getAttribLocation(program, 'a_PointVertex');
        gl.vertexAttribPointer(this.a_PointVertex, 2, gl.FLOAT, false, 0, 0);
        gl.uniform3f(u_color, this.color.R, this.color.G, this.color.B); // Set color uniform
        gl.drawArrays(gl.TRIANGLES, 0, this.pointCount);                 // Draws the buffer of the current grid

Copy code

As we can see, the main thing is to modify u before drawing_ color.

If there are two GridObject objects and render is called before and after, the order of setting uniform and drawing is as follows:

  • The first grid sets u in the program_ color
  • The first grid draws its own buffer
  • The second grid sets u in the program_ color
  • The second grid draws its own buffer

If there are more grids, as long as you write logic in this order, there will be no chaos between each grid, and from beginning to end, u_color is a variable shared by all grids.

Or do a little experiment with a slide rod

        <b>Color of the first grid R:</b>
        <input id="gridcolorR" type="range" min="0" max="1" value="0" step="0.01" oninput="gl_draw()" />
        <b id="gridcolorRvalue">0</b>

        <b>Color of the first grid G:</b>
        <input id="gridcolorG" type="range" min="0" max="1" value="0" step="0.01" oninput="gl_draw()" />
        <b id="gridcolorGvalue">0</b>
        <b>Color of the first grid B:</b>
        <input id="gridcolorB" type="range" min="0" max="1" value="0" step="0.01" oninput="gl_draw()" />
        <b id="gridcolorBvalue">0</b>

Copy code

In GL_ In the callback function draw, set the color of the first grid, and then draw two grids:

    gridOne.color.R = gridColorRDom.value;
    gridOne.color.G = gridColorGDom.value;
    gridOne.color.B = gridColorBDom.value;

    gridOne.render(gl, program);
    gridTwo.render(gl, program);

Copy code

The effects are as follows:

  At the end of the text, the following is the answer
 Copy code

Xiaoya said: in addition to the color, what else can be adjusted separately?

  • Position, rotation, stretching, etc.