Skip to main content

Using shaders to apply color in WebGL

Applying color to the vertices

In WebGL objects are built using sets of vertices, each of which has a position and a color. By default, all other pixels' colors (and all its other attributes, including position) are computed using interpolation, automatically creating smooth gradients. Previously, our vertex shader didn't apply any specific colors to the vertices. Between this and the fragment shader assigning the fixed color of white to each pixel, the entire square was rendered as solid white.


Let's say we want to render a gradient in which each corner of the square is a different color: red, blue, green, and white. The first thing to do is to establish these colors for the four vertices. To do this, we first need to create an array of vertex colors, then store it into a WebGL buffer. We'll do that by adding the following code to our initBuffers() function:


function initBuffers(){

  ...

  const colors = [

    1.0, 1.0, 1.0, 1.0, // white

    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

  ];


  const colorBuffer = gl.createBuffer();

  gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);

  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);


  return {

    position: positionBuffer,

    color: colorBuffer,

  };

}

This code starts by creating a JavaScript array containing four 4-value vectors, one for each vertex color. Then a new WebGL buffer is allocated to store these colors, and the array is converted into floats and stored into the buffer.


To use these colors, the vertex shader needs to be updated to pull the appropriate color from the color buffer:


  const vsSource = `

    attribute vec4 aVertexPosition;

    attribute vec4 aVertexColor;


    uniform mat4 uModelViewMatrix;

    uniform mat4 uProjectionMatrix;


    varying lowp vec4 vColor;


    void main(void) {

      gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;

      vColor = aVertexColor;

    }

  `;

The key difference here is that for each vertex, we pass its color using a varying to the fragment shader.


Coloring the fragments

As a refresher, here's what our fragment shader looked like previously:


  const fsSource = `

    void main() {

      gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);

    }

  `;

In order to pick up the interpolated color for each pixel, we need to change this to fetch the value from the vColor varying:


  const fsSource = `

    varying lowp vec4 vColor;


    void main(void) {

      gl_FragColor = vColor;

    }

  `;

Each fragment receives the interpolated color based on its position relative to the vertex positions instead of a fixed value.


Drawing using the colors

Next, it's necessary to add code to look up the attribute location for the colors and setup that attribute for the shader program:


  const programInfo = {

    program: shaderProgram,

    attribLocations: {

      vertexPosition: gl.getAttribLocation(shaderProgram, 'aVertexPosition'),

      vertexColor: gl.getAttribLocation(shaderProgram, 'aVertexColor'),

    },

    ...

Then, drawScene() can have the following added to it so it actually uses these colors when drawing the square:


  // Tell WebGL how to pull out the colors from the color buffer

  // into the vertexColor attribute.

  {

    const numComponents = 4;

    const type = gl.FLOAT;

    const normalize = false;

    const stride = 0;

    const offset = 0;

    gl.bindBuffer(gl.ARRAY_BUFFER, buffers.color);

    gl.vertexAttribPointer(

        programInfo.attribLocations.vertexColor,

        numComponents,

        type,

        normalize,

        stride,

        offset);

    gl.enableVertexAttribArray(

        programInfo.attribLocations.vertexColor);

  }

<meta charset='utf-8'><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAgAElEQVR4Xu3dB5QsW1k24N2HKCIiOecoIiI5SM4gIiI55ygiIhn7L0RERERyjiIiIiI5XpKIiIiI5BxFRERE4r3/qpkzfXvmTHfvqtpdX1fX41ouZ901c77ez+7ZvmverqpJSumE5H8IECBAgAABAgRGIzARAEez1xZKgAABAgQIENgREAC9EQgQIECAAAECIxMQAEe24ZZLgAABAgQIEBAAvQcIECBAgAABAiMTEABHtuGWS4AAAQIECBAQAL0HCBAgQIAAAQIjExAAR7bhlkuAAAECBAgQEAC9BwgQIECAAAECIxMQAEe24ZZLgAABAgQIEBAAvQcIECBAgAABAiMTEABHtuGWS4AAAQIECBAQAL0HCBAgQIAAAQIjExAAR7bhlkuAAAECBAgQEAC9BwgQIECAAAECIxMQAEe24ZZLgAABAgQIEBAAvQcIECBAgAABAiMTEABHtuGWS4AAAQIECBAQAL0HCBAgQIAAAQIjExAAR7bhlkuAAAECBAgQEAC9BwgQIECAAAECIxMQAEe24ZZLgAABAgQIEBAAvQcIECBAgAABAiMTEABHtuGWS4AAAQIECBAQAL0HCBAgQIAAAQIjExAAR7bhlkuAAAECBAgQEAC9BwgQIECAAAECIxMQAEe24ZZLgAABAgQIEBAAvQcIECBAgAABAiMTEABHtuGWS4AAAQIECBAQAL0HCBAgQIAAAQIjExAAR7bhlkuAAAECBAgQEAC9BwgQIECAAAECIxMQAEe24ZZLgAABAgQIEBAAvQcIECBAgAABAiMTEABHtuGWS4AAAQIECBAQAL0HCBAgQIAAAQIjExAAR7bhlkuAAAECBAgQEAC9BwgQIECAAAECIxMQAEe24ZZLgAABAgQIEBAAvQcIECBAgAABAiMTEABHtuGWS4AAAQIECBAQAL0HCBAgQIAAAQIjExAAR7bhlkuAAAECBAgQEAC9BwgQIECAAAECIxMQAEe24ZZLgAABAgQIEBAAvQcIECBAgAABAiMTEABHtuGWS4AAAQIECBAQAL0HCBAgQIAAAQIjExAAR7bhlkuAAAECBAgQEAC9BwgQIECAAAECIxMQAEe24ZZLgAABAgQIEBAAvQcIECBAgAABAiMTEABHtuGWS4AAAQIECBAQAL0HCBAgQIAAAQIjExAAR7bhlkuAAAECBAgQEAC9BwgQIECAAAECIxMQAEe24ZZLgAABAgQIEBAAvQcIECBAgAABAiMTEABHtuGWS4AAAQIECBAQAL0HCBAgQIAAAQIjExAAR7bhlkuAAAECBAgQEAC9BwgQIECAAAECIxMQAEe24ZZLgAABAgQIEBAAvQcIECBAgAABAiMTEABHtuGWS4AAAQIECBAQAL0HCBAgQIAAAQIjExAAR7bhlkuAAAECBAgQEAC9BwgQIECAAAECIxMQAEe24ZZLgAABAgQIEBAAvQcIECBAgAABAiMTEABHtuGWS4AAAQIECBAQAL0HCBAgQIAAAQIjExAAR7bhlkuAAAECBAgQEAC9BwgQIECAAAECIxMQAEe24ZZLgAABAgQIEBAAvQcIECBAgAABAiMTEABHtuGWS4AAAQIECBAQAL0HCBAgQIAAAQIjExAAR7bhlkuAAAECBAgQEAC9BwgQIECAAAECIxMQAEe24ZZLgAABAgQIEBAAvQcIECBAgAABAiMTEABHtuGWS4AAAQIECBAQAL0HCBAgQIAAAQIjExAAR7bhlkuAAAECBAgQEAC9BwgQIECAAAECIxMQAEe24ZZLgAABAgQIEBAAvQcIECBAgAABAiMTEABHtuGWS4AAAQIECBAQAL0HCBAgQIAAAQIjExAAR7bhlkuAAAECBAgQEAC9BwgQIECAAAECIxMQAEe24ZZLgAABAgQIEBAAvQcIECBAgAABAiMTEABHtuGWS4AAAQIECBAQAL0HCBAgQIAAAQIjExAAR7bhlkuAAAECBAgQEAC9BwgQIECAAAECIxMQAEe24ZZLgAABAgQIEBAAvQcIECBAgAABAiMTEABHtuGWS4AAAQIECBAQAL0HCBAgQIAAAQIjExAAR7bhlkuAAAECBAgQEAC9BwgQIECAAAECIxMQAEe24ZZLgAABAgQIEBAAvQcIECBAgAABAiMTEABHtuGWS4AAAQIECBAQAL0HCBAgQIAAAQIjExAAR7bhlkuAAAECBAgQEAC9BwgQIECAAAECIxMQAEe24ZZLgAABAgQIEBAAvQcIECBAgAABAiMTEABHtuGWS4AAAQIECBAQAL0HCBAgQIAAAQIjExAAR7bhlkuAAAECBAgQEAC9BwgQIECAAAECIxMQAEe24ZZLgAABAgQIEBAAvQcIECBA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gAABAoECAmAgvtEECBAgQIAAgQgBATBC3UwCBAgQIECAQKCAABiIbzQBAgQIECBAIEJAAIxQN5MAAQIECBAgECggAAbiG02AAAECBAgQiBAQACPUzSRAgAABAgQIBAoIgIH4RhMgQIAAAQIEIgQEwAh1MwkQIECAAAECgQICYCC+0QQIECBAgACBCAEBMELdTAIECBAgQIBAoIAAGIhvNAECBAgQIEAgQkAAjFA3kwABAgQIECAQKCAABuIbTYAAAQIECBCIEBAAI9TNJECAAAECBAgECgiAgfhGEyBAgAABAgQiBATACHUzCRAgQIAAAQKBAgJgIL7RBAgQIECAAIEIAQEwQt1MAgQIECBAgECggAAYiG80AQIECBAgQCBCQACMUDeTAAECBAgQIBAoIAAG4htNgAABAgQIEIgQEAAj1M0kQIAAAQIECAQKCICB+EYTIECAAAECBCIEBMAIdTMJECBAgAABAoECAmAgvtEECBAgQIAAgQgBATBC3UwCBAgQIECAQKCAABiIbzQBAgQIECBAIEJAAIxQN5MAAQIECBAgECggAAbiG02AAAECBAgQiBAQACPUzSRAgAABAgQIBAoIgIH4RhMgQIAAAQIEIgQEwAh1MwkQIECAAAECgQICYCC+0QQIECBAgACBCAEBMELdTAIECBAgQIBAoIAAGIhvNAECBAgQIEAgQkAAjFA3kwABAgQIECAQKCAABuIbTYAAAQIECBCIEBAAI9TNJECAAAECBAgECgiAgfhGEyBAgAABAgQiBATACHUzCRAgQIAAAQKBAgJgIL7RBAgQIECAAIEIAQEwQt1MAgQIECBAgECggAAYiG80AQIECBAgQCBCQACMUDeTAAECBAgQIBAoIAAG4htNgAABAgQIEIgQEAAj1M0kQIAAAQIECAQKCICB+EYTIECAAAECBCIEBMAIdTMJECBAgAABAoECAmAgvtEECBAgQIAAgQgBATBC3UwCBAgQIECAQKCAABiIbzQBAgQIECBAIEJAAIxQN5MAAQIECBAgECggAAbiG02AAAECBAgQiBAQACPUzSRAgAABAgQIBAoIgIH4RhMgQIAAAQIEIgQEwAh1MwkQIECAAAECgQICYCC+0QQIECBAgACBCAEBMELdTAIECBAgQIBAoIAAGIhvNAECBAgQIEAgQkAAjFA3kwABAgQIECAQKCAABuIbTYAAAQIECBCIEBAAI9TNJECAAAECBAgECgiAgfhGEyBAgAABAgQiBATACHUzCRAgQIAAAQKBAgJgIL7RBAgQIECAAIEIAQEwQt1MAgQIECBAgECggAAYiG80AQIECBAgQCBCQACMUDeTAAECBAgQIBAoIAAG4htNgAABAgQIEIgQEAAj1M0kQIAAAQIECAQKCICB+EYTIECAAAECBCIEBMAIdTMJECBAgAABAoECAmAgvtEECBAgQIAAgQgBATBC3UwCBAgQIECAQKCAABiIbzQBAgQIECBAIEJAAIxQN5MAAQIECBAgECggAAbiG02AAAECBAgQiBAQACPUzSRAgAABAgQIBAoIgIH4RhMgQIAAAQIEIgQEwAh1MwkQIECAAAECgQICYCC+0QQIECBAgACBCAEBMELdTAIECBAgQIBAoIAAGIhvNAECBAgQIEAgQkAAjFA3kwABAgQIECAQKCAABuIbTYAAAQIECBCIEBAAI9TNJECAAAECBAgECgiAgfhGEyBAgAABAgQiBATACHUzCRAgQIAAAQKBAgJgIL7RBAgQIECAAIEIAQEwQt1MAgQIECBAgECggAAYiG80AQIECBAgQCBCQACMUDeTAAECBAgQIBAoIAAG4htNgAABAgQIEIgQEAAj1M0kQIAAAQIECAQKCICB+EYTIECAAAECBCIEBMAIdTMJECBAgAABAoECAmAgvtEECBAgQIAAgQgBATBC3UwCBAgQIECAQKCAABiIbzQBAgQIECBAIEJAAIxQN5MAAQIECBAgECggAAbiG02AAAECBAgQiBAQACPUzSRAgAABAgQIBAoIgIH4RhMgQIAAAQIEIgQEwAh1MwkQIECAAAECgQICYCC+0QQIECBAgACBCAEBMELdTAIECBAgQIBAoIAAGIhvNAECBAgQIEAgQkAAjFA3kwABAgQIECAQKCAABuIbTYAAAQIECBCIEBAAI9TNJECAAAECBAgECgiAgfhGEyBAgAABAgQiBATACHUzCRAgQIAAAQKBAgJgIL7RBAgQIECAAIEIAQEwQt1MAgQIECBAgECggAAYiG80AQIECBAgQCBCQACMUDeTAAECBAgQIBAoIAAG4htNgAABAgQIEIgQEAAj1M0kQIAAAQIECAQKCICB+EYTIECAAAECBCIEBMAIdTMJECBAgAABAoECAmAgvtEECBAgQIAAgQgBATBC3UwCBAgQIECAQKDA/wf8lYaTjEosYQAAAABJRU5ErkJggg=="/>


Comments

Popular posts from this blog

Using textures in WebGL

Loading textures The first thing to do is add code to load the textures. In our case, we'll be using a single texture, mapped onto all six sides of our rotating cube, but the same technique can be used for any number of textures. Note: It's important to note that the loading of textures follows cross-domain rules; that is, you can only load textures from sites for which your content has CORS approval. See Cross-domain textures below for details. The code that loads the texture looks like this: // // Initialize a texture and load an image. // When the image finished loading copy it into the texture. // function loadTexture(gl, url) {   const texture = gl.createTexture();   gl.bindTexture(gl.TEXTURE_2D, texture);   // Because images have to be download over the internet   // they might take a moment until they are ready.   // Until then put a single pixel in the texture so we can   // use it immediately. When the image has finished downloading   // we'l...

Matrix math for the web

Matrices can be used to represent transformations of objects in space, and are an important tool to use in visualizations on the Web. This article explores how to create matrices and use them with  CSS3 transforms  and the  matrix3d  transform type. While this article uses CSS3 for the ease of explanations, matrices are a core concept used by many different technologies including WebGL and shaders. This article is also available as an  MDN content kit . The live examples use a collection of  utility functions  availabile under a global object named "MDN". What is a transformation matrix? There are many types of matrices, but the ones we are interested in are the 3D transformation matrices. These matrices consist of a set of 16 values arranged in a 4x4 grid. In JavaScript, it is easy to represent a matrix as an array. The typical starting point is to show the identity matrix. When this matrix is multiplied against another point or matrix then the result...

WebGL: 2D and 3D graphics for the web

WebGL (Web Graphics Library) is a JavaScript API for rendering high-performance interactive 3D and 2D graphics within any compatible web browser without the use of plug-ins. WebGL does so by introducing an API that closely conforms to OpenGL ES 2.0 that can be used in HTML5 <canvas> elements. This conformance makes it possible for the API to take advantage of hardware graphics acceleration provided by the user's device. Support for WebGL is present in Firefox 4+, Google Chrome 9+, Opera 12+, Safari 5.1+, Internet Explorer 11+, and Microsoft Edge build 10240+; however, the user's device must also have hardware that supports these features. The WebGL 2 API introduces support for much of the OpenGL ES 3.0 feature set; it's provided through the WebGL2RenderingContext interface. The <canvas> element is also used by the Canvas API to do 2D graphics on web pages.