| <!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> |