JavaScript webgl setting colors



JavaScript webgl draws a faceThen I thought I could try something more complex. Unexpectedly, there was a problem when setting the color.

Set color

In the previous examples, a single color was set, but each vertex can have its own color information.

be based onDraw triangleThere are mainly the following changes:

  • data
  • Vertex Shader
  • Fragment Shader
  • Buffer color data


Color data has four components: R, G, B and a.

  let colors = [
    1.0, 0.0, 0.0, 1.0, // red
    0.0, 1.0, 0.0, 1.0, // green
    0.0, 0.0, 1.0, 1.0, // blue

Vertex Shader

Previously, only location variables were provided. For colors, additional color variables need to be provided for storage. In addition, you also need to output the corresponding color to the next stage.

  const source = `
    attribute vec3 vertexPos;
    attribute vec4 vertexColor;

    varying vec4 vColor;
    void main(void){
      gl_Position = vec4(vertexPos, 1);
      vColor = vertexColor;

There’s one more in herevaryingType, which is a way for vertex shaders to pass values to fragment shaders.

Fragment Shader

The slice shader accepts the corresponding variables and also declares them.

  const fragmentSource = `
    precision highp float;
    varying vec4 vColor;
    void main(void){
      gl_FragColor = vColor;

Here is a variable, which needs to be usedprecision highp floatSets the floating point precision of the slice shader. Vertex shaders have default precision and can be set without explicit.

Buffer color data

Vertex position data is buffered, and color data is buffered.

   *Buffer color data
   *@ param {*} GL webgl context
   *@ param {*} shaderprogram shader program
   *@ param {*} colordata color data
  function setColorBuffers(gl, shaderProgram, colorData) {
    //Create a blank buffer object
    const buffer = gl.createBuffer();
    //Bind target
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    //Webgl does not support the direct use of JavaScript original array types, which requires conversion
    const dataFormat = new Float32Array(colorData);
    //Initialize data store
    gl.bufferData(gl.ARRAY_BUFFER, dataFormat, gl.DYNAMIC_DRAW);

    //Get the corresponding data index, and the variable corresponds to the vertex shader
    const vertexPos = gl.getAttribLocation(shaderProgram, "vertexColor");
    //Parse vertex data
    gl.vertexAttribPointer(vertexPos, 4, gl.FLOAT, false, 0, 0);
    //Enable vertex attributes, which are disabled by default.


This isExample, the effect is as follows:

JavaScript webgl setting colors

It is found that the color gradient diverges because the color is interpolated when it is transformed into pixels in the rasterization process.

In the program, only the colors of three vertices are defined, and the color of pixels between them will change with the pixel position. The difference of the same monochrome between adjacent pixels is a fixed value. If you don’t want this effect, you can customize it in the slice shader.

Dynamic customization example

This isExample, the main changes of the slice shader are as follows:

  const fragmentSource = `
    precision highp float;
    varying vec4 vColor;

    int findMax(float r, float g, float b) {
        if (r > g && r > b) {
            return 0;
        if (g > r && g > b) {
            return 1;
        return 2;

    void main(void){
      float red = vColor.r;
      float green = vColor.g;
      float blue = vColor.b;
      int max = findMax(red, green, blue);
      vec4 finalColor = vColor;
      if (max == 0) {
          finalColor = vec4(1.0, 0.0, 0.0, 1.0);
      else if (max == 1) {
          finalColor = vec4(0.0, 1.0, 0.0, 1.0);
      else if (max == 2) {
          finalColor = vec4(0.0, 0.0, 1.0, 1.0);
      gl_FragColor = finalColor;

findMaxThe method compares the color components of each pixel and sets the final color to the largest component. Here are the effects:

JavaScript webgl setting colors

reference material