format-r11f-g11f-b10f.html (9168B)
1 <!-- 2 Copyright (c) 2019 The Khronos Group Inc. 3 Use of this source code is governed by an MIT-style license that can be 4 found in the LICENSE.txt file. 5 --> 6 7 <!DOCTYPE html> 8 <html> 9 <head> 10 <meta charset="utf-8"> 11 <title>Test Format R11F_G11F_B10F</title> 12 <link rel="stylesheet" href="../../resources/js-test-style.css"/> 13 <script src="../../js/js-test-pre.js"></script> 14 <script src="../../js/webgl-test-utils.js"></script> 15 </head> 16 <body> 17 <div id="description"></div> 18 <div id="console"></div> 19 <canvas id="canvas" width="20" height="20"> </canvas> 20 <script id="vshader" type="x-shader/x-vertex"> 21 attribute vec2 pos; 22 attribute vec2 texCoord0; 23 varying vec2 texCoord; 24 25 void main() { 26 gl_Position = vec4(pos, 0.0, 1.0); 27 texCoord = texCoord0; 28 } 29 </script> 30 31 <script id="fshader" type="x-shader/x-fragment"> 32 precision mediump float; 33 uniform vec3 u_color; 34 uniform vec3 u_tol; 35 uniform sampler2D u_tex; 36 varying vec2 texCoord; 37 38 void main() { 39 vec4 sample = texture2D(u_tex, texCoord); 40 vec3 rgb = sample.xyz; 41 if (abs(rgb[0] - u_color[0]) > u_tol[0] || 42 abs(rgb[1] - u_color[1]) > u_tol[1] || 43 abs(rgb[2] - u_color[2]) > u_tol[2]) { 44 gl_FragColor = vec4(1, 0, 0, 1); 45 } else { 46 gl_FragColor = vec4(0, 1, 0, 1); 47 } 48 } 49 </script> 50 <script> 51 "use strict"; 52 description("This tests format R11F_G11F_B10F works as expected"); 53 debug("MacOSX driver bug. See https://github.com/KhronosGroup/WebGL/issues/1832"); 54 55 var wtu = WebGLTestUtils; 56 var canvas = document.getElementById("canvas"); 57 var gl = wtu.create3DContext(canvas, undefined, 2); 58 59 var testValues = [100, 1000, 2047, 2500, 4095, 5000, 60 8191, 8192, 10000, 16383, 16384]; 61 62 if (!gl) { 63 testFailed("context does not exist"); 64 } else { 65 testPassed("context exists"); 66 if (gl.getExtension("EXT_color_buffer_float")) { 67 testPassed("Extension EXT_color_buffer_float is available"); 68 69 testRenderbufferReadback(4, 4); 70 testTextureReadback(4, 4); 71 testTextureSampling(4, 4); 72 } else { 73 testPassed("Extension EXT_color_buffer_float is unavailable - this is legal"); 74 } 75 } 76 77 function setupColor(testR, testG, testB, value) { 78 var data = new Float32Array(4); 79 data[0] = testR ? value : 0; 80 data[1] = testG ? value : 0; 81 data[2] = testB ? value : 0; 82 data[3] = 1; // Doesn't really matter for RGB formats. 83 return data; 84 } 85 86 // The definition of <Unsinged 11-Bit Floating-Point Number> in GLES 3.0.4: 87 // https://www.khronos.org/registry/gles/specs/3.0/es_spec_3.0.4.pdf#nameddest=section-2.1.3 88 // The definition of <Unsinged 10-Bit Floating-Point Number> in GLES 3.0.4: 89 // https://www.khronos.org/registry/gles/specs/3.0/es_spec_3.0.4.pdf#nameddest=section-2.1.4 90 function setTolerance (testR, testG, testB, value) { 91 var tol = new Float32Array(3); 92 var exponent; 93 if (value < Math.pow(2, -14)) { 94 exponent = -14; 95 } else { 96 exponent = Math.floor(Math.log(value) / Math.LN2); 97 } 98 var tol11F = Math.pow(2, exponent) / 64; 99 var tol10F = Math.pow(2, exponent) / 32; 100 tol[0] = testR ? tol11F : 0; 101 tol[1] = testG ? tol11F : 0; 102 tol[2] = testB ? tol10F : 0; 103 return tol; 104 } 105 106 function clearAndVerifyColor(width, height, testR, testG, testB, value) { 107 var data = setupColor(testR, testG, testB, value); 108 var tol = setTolerance(testR, testG, testB, value); 109 gl.clearBufferfv(gl.COLOR, 0, data); 110 var buffer = new Float32Array(width * height * 4); 111 gl.readPixels(0, 0, width, height, gl.RGBA, gl.FLOAT, buffer); 112 for (var ii = 0; ii < width * height; ++ii) { 113 var pixel = [buffer[ii * 4], buffer[ii * 4 + 1], buffer[ii * 4 + 2], buffer[ii * 4 + 3]]; 114 if (isNaN(pixel[0]) || isNaN(pixel[1]) || isNaN(pixel[2]) || 115 Math.abs(pixel[0] - data[0]) > tol[0] || 116 Math.abs(pixel[1] - data[1]) > tol[1] || 117 Math.abs(pixel[2] - data[2]) > tol[2]) { 118 testFailed("ReadPixels " + ii + " : got [" + pixel + "], expected [" + data + "], tol [" + tol + "]"); 119 return; 120 } 121 } 122 testPassed("ReadPixels success : [" + data + "]"); 123 } 124 125 function clearDrawAndVerifyColor(fbo, program, testR, testG, testB, value) { 126 var data = setupColor(testR, testG, testB, value); 127 var tol = setTolerance(testR, testG, testB, value); 128 debug("Testing : [" + data + "] with tolerance = [" + tol + "]"); 129 130 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); 131 gl.clearBufferfv(gl.COLOR, 0, data); 132 133 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 134 gl.clearColor(0, 0, 0,1); 135 gl.clear(gl.COLOR_BUFFER_BIT); 136 137 gl.uniform3fv(program.colorPos, data.slice(0, 3)); 138 gl.uniform3fv(program.tolPos, tol); 139 140 wtu.drawUnitQuad(gl); 141 wtu.checkCanvas(gl, [0, 255, 0, 255], "Should pass (green color instead of red)"); 142 } 143 144 145 function testReadPixelsFromColorChannelsWithVariousValues(width, height) { 146 debug("Testing R channel"); 147 for (var ii = 0; ii < testValues.length; ++ii) { 148 clearAndVerifyColor(width, height, true, false, false, testValues[ii]); 149 } 150 debug("Testing G channel"); 151 for (var ii = 0; ii < testValues.length; ++ii) { 152 clearAndVerifyColor(width, height, false, true, false, testValues[ii]); 153 } 154 debug("Testing B channel"); 155 for (var ii = 0; ii < testValues.length; ++ii) { 156 clearAndVerifyColor(width, height, false, false, true, testValues[ii]); 157 } 158 } 159 160 function testSampleTextureFromColorChannelsWithVariousValues(fbo, program) { 161 debug("Testing R channel"); 162 for (var ii = 0; ii < testValues.length; ++ii) { 163 clearDrawAndVerifyColor(fbo, program, true, false, false, testValues[ii]); 164 } 165 debug("Testing G channel"); 166 for (var ii = 0; ii < testValues.length; ++ii) { 167 clearDrawAndVerifyColor(fbo, program, false, true, false, testValues[ii]); 168 } 169 debug("Testing B channel"); 170 for (var ii = 0; ii < testValues.length; ++ii) { 171 clearDrawAndVerifyColor(fbo, program, false, false, true, testValues[ii]); 172 } 173 } 174 175 function testRenderbufferReadback(width, height) { 176 debug(""); 177 debug("Checking clearing and readback of a color image of renderbuffer with R11F_G11F_B10F format."); 178 179 var fbo = gl.createFramebuffer(); 180 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); 181 var renderbuffer = gl.createRenderbuffer(); 182 gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer); 183 gl.renderbufferStorage(gl.RENDERBUFFER, gl.R11F_G11F_B10F, width, height); 184 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, renderbuffer); 185 shouldBe("gl.FRAMEBUFFER_COMPLETE", "gl.checkFramebufferStatus(gl.FRAMEBUFFER)"); 186 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setup framebuffer with renderbuffer should succeed."); 187 188 testReadPixelsFromColorChannelsWithVariousValues(width, height); 189 190 gl.deleteFramebuffer(fbo); 191 gl.deleteRenderbuffer(renderbuffer); 192 } 193 194 function testTextureReadback(width, height) { 195 debug(""); 196 debug("Checking clearing and readback of a color image of texture with R11F_G11F_B10F format."); 197 198 var fbo = gl.createFramebuffer(); 199 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); 200 var tex = gl.createTexture(); 201 gl.bindTexture(gl.TEXTURE_2D, tex); 202 gl.texImage2D(gl.TEXTURE_2D, 0, gl.R11F_G11F_B10F, width, height, 0, gl.RGB, gl.FLOAT, null); 203 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0); 204 shouldBe("gl.FRAMEBUFFER_COMPLETE", "gl.checkFramebufferStatus(gl.FRAMEBUFFER)"); 205 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setup framebuffer with texture should succeed."); 206 207 testReadPixelsFromColorChannelsWithVariousValues(width, height); 208 209 gl.deleteFramebuffer(fbo); 210 gl.deleteTexture(tex); 211 } 212 213 function setupProgram() { 214 var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["pos", "texCoord0"]); 215 if (!program) 216 return null; 217 program.colorPos = gl.getUniformLocation(program, "u_color"); 218 program.tolPos = gl.getUniformLocation(program, "u_tol"); 219 var texPos = gl.getUniformLocation(program, "u_tex"); 220 program.buffers = wtu.setupUnitQuad(gl, 0, 1); 221 if (!program.colorPos || !program.tolPos || !texPos || program.buffers.length == 0) { 222 gl.deleteProgram(program); 223 return null; 224 } 225 gl.useProgram(program); 226 gl.uniform1i(texPos, 0); 227 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setup program should succeed."); 228 return program; 229 } 230 231 function testTextureSampling(width, height) { 232 debug(""); 233 debug("Checking sampling of a texture with R11_G11F_B10F format"); 234 235 var program = setupProgram(); 236 if (!program) { 237 testFailed("Failed to setup program"); 238 return; 239 } 240 241 var fbo = gl.createFramebuffer(); 242 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); 243 var tex = gl.createTexture(); 244 gl.bindTexture(gl.TEXTURE_2D, tex); 245 gl.texImage2D(gl.TEXTURE_2D, 0, gl.R11F_G11F_B10F, width, height, 0, gl.RGB, gl.FLOAT, null); 246 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); 247 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0); 248 shouldBe("gl.FRAMEBUFFER_COMPLETE", "gl.checkFramebufferStatus(gl.FRAMEBUFFER)"); 249 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setup framebuffer with texture should succeed."); 250 251 testSampleTextureFromColorChannelsWithVariousValues(fbo, program); 252 253 gl.deleteTexture(tex); 254 gl.deleteFramebuffer(fbo); 255 gl.deleteProgram(program); 256 } 257 258 debug(""); 259 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No GL error from tests."); 260 var successfullyParsed = true; 261 262 </script> 263 <script src="../../js/js-test-post.js"></script> 264 265 </body> 266 </html>