MENU
Alpha Blending
For a surface, WebGL allows you to mix its color(the source color) with the color of the surface behind it(the destination color). Alpha blending means using the alpha values to achieve blending effects such as transparency.
To use blending:
Step 1: Enable the blending function:
gl.enable(gl.BLEND);
Step 2: Specify the blending function:
gl.blendFunc(src_factor, dst_factor);
where <color> = <source color> * src_factor + <destination color> * dst_factor
Factor Constant | Factor for R | Factor for G | Factor for B |
ZERO | 0.0 | 0.0 | 0.0 |
ONE | 1.0 | 1.0 | 1.0 |
SRC_COLOR | Rs | Gs | Bs |
ONE_MINUS_SRC_COLOR | (1-Rs) | (1-Gs) | (1-Bs) |
DST_COLOR | Rd | Gd | Bd |
ONE_MINUS_DST_COLOR | (1-Rd) | (1-Gd) | (1-Bd) |
SRC_ALPHA | As | As | As |
ONE_MINUS_SRC_ALPHA | (1-As) | (1-As) | (1-As) |
DST_ALPHA | Ad | Ad | Ad |
ONE_MINUS_DST_ALPHA | (1-Ad) | (1-Ad) | (1-Ad) |
SRC_ALPHA_SATURATE | min (As,Ad) |
min (As,Ad) |
min (As,Ad) |
RESETRUNFULL
<!DOCTYPE html><html>
<head>
<script src="/shared/webgl-library.js"></script>
<script id="shader-fs" type="x-shader/x-fragment">
#ifdef GL_ES
precision mediump float;
#endif
varying vec4 v_Color;
void main() {
gl_FragColor = v_Color;
}
</script>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec4 a_Position;
attribute vec4 a_Color;
uniform mat4 u_ViewMatrix;
uniform mat4 u_ProjMatrix;
varying vec4 v_Color;
void main() {
gl_Position = u_ProjMatrix * u_ViewMatrix * a_Position;
v_Color = a_Color;
}
</script>
<script type="text/javascript">
function WebGLStart() {
var canvas = document.getElementById('cv');
var gl = canvas.getContext("webgl");
initShaders(gl, "shader-vs", "shader-fs");
var n = initVertexBuffers(gl);
gl.clearColor(0, 0, 0, 1);
gl.enable (gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
var u_ViewMatrix = gl.getUniformLocation(gl.program, 'u_ViewMatrix');
var u_ProjMatrix = gl.getUniformLocation(gl.program, 'u_ProjMatrix');
var viewMatrix = new Matrix4();
window.onkeydown = function(ev){
keydown(ev, gl, n, u_ViewMatrix, viewMatrix);
};
var projMatrix = new Matrix4();
projMatrix.orthographic(-1, 1, -1, 1, 0, 2);
gl.uniformMatrix4fv(u_ProjMatrix, false, projMatrix.entries);
draw(gl, n, u_ViewMatrix, viewMatrix);
}
function initVertexBuffers(gl) {
var verticesColors = new Float32Array([ // Vertex coordinates and color(RGBA)
0.0, 0.5, -0.4, 0.4, 1.0, 0.4, 0.4, // The green front
-0.5, -0.5, -0.4, 0.4, 1.0, 0.4, 0.4,
0.5, -0.5, -0.4, 1.0, 0.4, 0.4, 0.4,
0.5, 0.4, -0.2, 1.0, 0.4, 0.4, 0.4, // The yellow middle
-0.5, 0.4, -0.2, 1.0, 1.0, 0.4, 0.4,
0.0, -0.6, -0.2, 1.0, 1.0, 0.4, 0.4,
0.0, 0.5, 0.0, 0.4, 0.4, 1.0, 0.4, // The blue back
-0.5, -0.5, 0.0, 0.4, 0.4, 1.0, 0.4,
0.5, -0.5, 0.0, 1.0, 0.4, 0.4, 0.4,
]);
var n = 9;
var vertexColorbuffer = gl.createBuffer();
if (!vertexColorbuffer) {
console.log('Failed to create the buffer object');
return -1;
}
gl.bindBuffer(gl.ARRAY_BUFFER, vertexColorbuffer);
gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);
var FSIZE = verticesColors.BYTES_PER_ELEMENT;
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
gl.vertexAttribPointer(a_Position, 3, gl.FLOAT,false,FSIZE*7,0);
gl.enableVertexAttribArray(a_Position);
var a_Color = gl.getAttribLocation(gl.program, 'a_Color');
gl.vertexAttribPointer(a_Color, 4, gl.FLOAT,false, FSIZE*7, FSIZE * 3);
gl.enableVertexAttribArray(a_Color);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
return n;}function keydown(ev, gl, n, u_ViewMatrix, viewMatrix) {
if(ev.keyCode == 39) { // The right arrow key was pressed
g_EyeX += 0.01;
} else if (ev.keyCode == 37) { // The left arrow key was pressed
g_EyeX -= 0.01;
} else return;
draw(gl, n, u_ViewMatrix, viewMatrix);
}
var g_EyeX = 0.20, g_EyeY = 0.25, g_EyeZ = 0.25;
function draw(gl, n, u_ViewMatrix, viewMatrix) {
viewMatrix.lookAt(g_EyeX, g_EyeY, g_EyeZ, 0, 0, 0, 0,1,0);
gl.uniformMatrix4fv(u_ViewMatrix, false, viewMatrix.entries);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, n);
}
</script>
</head>
<body onload="WebGLStart();">
<canvas id="cv" style="border: none;" width="500" height="500"></canvas>
</body>
</html>
With hidden surface removal enabled, objects at the back may not be drawn. This may cause alpha blending to behave unexpectedly. To counter this problem, follow these steps:
Step 1: Enable hidden surface removal
gl.enable(gl.DEPTH_TEST);
Step 2: Draw all opaque objects (alpha values=1.0)
Step 3: Make the depth buffer read-only
gl.depthMask(false);
Step 4: Draw all the transparent objects back to front.
Step 5: Make the depth buffer readable and writable
gl.depthMask(true);