How does blending work with GLSL ES fragment shaders in WebGL?

Sean Seefried picture Sean Seefried · May 28, 2011 · Viewed 8.2k times · Source

I'm trying to get a simple effect to display using WebGL. Naturally, this means I'm using the fragment shader language defined in the GLSL ES 1.0 specification.

The code I am working with is largely copied from other sources. It sets up a square and uses the fragment and vertex shaders to determine the pixel colors. The following code will just display a white square.

gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);

However, if I change the alpha component to 1.0 then it will show a black square instead.

gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); // displays a black square

I'm assuming that the color that is output by the fragment shader must be combined with some previous color. How do I make sure that only the last color (regardless of its alpha value) is what is actually chosen as the color to be displayed?

Or perhaps I've got the order the wrong way around. Perhaps there is a later phase that is combining with the color from the fragment shader to produce the white color. In any case, I know that some kind of blending is going on because when I change the alpha value to 0.5 I get a grey square. I just want to know, where is the white color coming from? And how do I get rid of it?

As far as I can tell the problem is not to do with the blending function. The code is on GitHub here. Try it out in Google Chrome or Firefox.

Answer

Sean Seefried picture Sean Seefried · May 31, 2011

The white color is not coming from any WebGL blending operations. It happens because canvas DOM elements are composited with the web page they reside in. Setting the background color of the canvas DOM element to black fixes the problem. This phenomenon has been written about here. However, the most definitive answer comes from the WebGL specification. The behaviour of compositing can be defined by setting various attributes of the WebGLContextAttributes object. Quoting from the specification:

The optional WebGLContextAttributes object may be used to change whether or not the buffers are defined. It can also be used to define whether the color buffer will include an alpha channel. If defined, the alpha channel is used by the HTML compositor to combine the color buffer with the rest of the page.

Thus, an alternative solution, that does not involve setting the background of the canvas to black, is to ask for the WebGL context with the following Javascript code

gl = canvas.getContext("experimental-webgl", { alpha: false } );