<!DOCTYPE html>
<html>
<!--
Creates 4 WebGL canvases with the cross-product of anti-aliasing and
premultiplied alpha. Uses drawingBufferStorage to ensure these canvases are
floating-point. Draws and reads back the color #800080, with slight
perturbations to ensure that greater than 8-bit precision is preserved in
the round-trip.
-->
<head>
<style type="text/css">
.nomargin {
margin: 0;
}
</style>
<script>
function sendResult(status) {
if (window.domAutomationController) {
window.domAutomationController.send(status);
} else {
console.log(status);
}
}
var g_swapsBeforeAck = 15;
function waitForFinish() {
if (g_swapsBeforeAck == 0) {
sendResult("SUCCESS");
} else {
g_swapsBeforeAck--;
window.requestAnimationFrame(waitForFinish);
}
}
function drawQuad(gl, color) {
let ext = gl.getExtension('EXT_color_buffer_half_float');
if (!ext) {
sendResult("FAILURE", "EXT_color_buffer_half_float not supported");
return;
}
gl.drawingBufferStorage(gl.RGBA16F, gl.drawingBufferWidth, gl.drawingBufferHeight);
// Create the program to draw a point sprite.
let program = null;
{
let compileShader = function(gl, vertCode, fragCode) {
let vertShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertShader, vertCode);
gl.compileShader(vertShader);
if (!gl.getShaderParameter(vertShader, gl.COMPILE_STATUS))
throw new Error(gl.getShaderInfoLog(vertShader));
let fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragShader, fragCode);
gl.compileShader(fragShader);
if (!gl.getShaderParameter(fragShader, gl.COMPILE_STATUS))
throw new Error(gl.getShaderInfoLog(fragShader));
let shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertShader);
gl.attachShader(shaderProgram, fragShader);
gl.linkProgram(shaderProgram);
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS))
throw new Error(gl.getProgramInfoLog(program));
return shaderProgram;
}
let vs = `attribute vec2 position;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
}`;
let fs = `precision mediump float;
uniform vec4 color;
void main() {
gl_FragColor = color;
}`;
program = compileShader(gl, vs, fs);
}
gl.useProgram(program);
// Draw using that program.
{
let vertices = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertices);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1,-1, 1,-1, 1,1, -1,1]), gl.STATIC_DRAW);
let indices = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indices);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0,1,2, 0,2,3]), gl.STATIC_DRAW);
let positionLocation = gl.getAttribLocation(program, 'position');
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(positionLocation);
gl.uniform4fv(gl.getUniformLocation(program, 'color'), color);
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
}
// Ensure that we can read the values back as FLOAT, and that the output
// matches the input with higher precision than we can achieve with 8 bits.
let pixels = new Float32Array(4);
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.FLOAT, pixels);
for (let c = 0; c < 4; ++c) {
const epsilon = (1/255) / 8;
if (Math.abs(pixels[c] - color[c]) > epsilon)
throw new Error('Error reading back pixels as floats');
}
}
async function main() {
let color = new Float32Array(4);
color[0] = 1.0;
color[1] = 0.0;
color[2] = (128 + 1/4) / 255;
color[3] = 1.0;
{
let element = document.getElementById('canvas-noaa-premul');
let gl = element.getContext('webgl2', {premultipliedAlpha: true, antialias:false});
drawQuad(gl, color);
}
{
let element = document.getElementById('canvas-aa-premul');
let gl = element.getContext('webgl2', {premultipliedAlpha: true, antialias:true});
drawQuad(gl, color);
}
{
let element = document.getElementById('canvas-noaa-unpremul');
let gl = element.getContext('webgl2', {premultipliedAlpha: false, antialias:false});
drawQuad(gl, color);
}
{
let element = document.getElementById('canvas-aa-unpremul');
let gl = element.getContext('webgl2', {premultipliedAlpha: false, antialias:true});
drawQuad(gl, color);
}
waitForFinish();
}
</script>
</head>
<body onload='main()'>
<p>
<canvas id='canvas-aa-premul' width='32' height='32'></canvas>
<canvas id='canvas-aa-unpremul' width='32' height='32'></canvas>
<canvas id='canvas-noaa-premul' width='32' height='32'></canvas>
<canvas id='canvas-noaa-unpremul' width='32' height='32'></canvas>
</p>
</body>
</html>