tex-srgb-mipmap.html (7302B)
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>WebGL texture mipmap conformance test.</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 <canvas id="example" width="4" height="4" style="width: 16px; height: 16px;"></canvas> 18 <div id="description"></div> 19 <div id="console"></div> 20 <script id="vshader" type="x-shader/x-vertex"> 21 attribute vec4 vPosition; 22 attribute vec2 texCoord0; 23 varying vec2 texCoord; 24 void main() 25 { 26 gl_Position = vPosition; 27 texCoord = texCoord0; 28 } 29 </script> 30 31 <script id="fshader" type="x-shader/x-fragment"> 32 precision mediump float; 33 uniform sampler2D tex; 34 varying vec2 texCoord; 35 void main() 36 { 37 gl_FragColor = texture2D(tex, texCoord); 38 } 39 </script> 40 <script> 41 "use strict"; 42 var wtu = WebGLTestUtils; 43 var canvas = document.getElementById("example"); 44 var gl = wtu.create3DContext(canvas, undefined, 2); 45 46 description("Test srgb emulation for generateMipmap."); 47 function generateMipmap() 48 { 49 debug("Generate mipmaps for sRGB texture"); 50 51 wtu.setupUnitQuad(gl, 0, 1); 52 var program = wtu.setupProgram( 53 gl, ['vshader', 'fshader'], ['vPosition', 'texCoord0'], [0, 1]); 54 55 gl.disable(gl.DEPTH_TEST); 56 gl.disable(gl.BLEND); 57 58 var colors = { 59 blank: [0, 0, 0, 0], 60 srgba: [0, 63, 127, 255], 61 }; 62 63 var texLoc = gl.getUniformLocation(program, "tex"); 64 gl.uniform1i(texLoc, 0); 65 66 var width = 128; 67 var height = 128; 68 canvas.width = width; 69 canvas.height = height; 70 gl.viewport(0, 0, width, height); 71 72 var srgbTex = gl.createTexture(); 73 gl.bindTexture(gl.TEXTURE_2D, srgbTex); 74 // Set full texture as srgba color first. 75 wtu.fillTexture(gl, srgbTex, width, height, colors['srgba'], 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.SRGB8_ALPHA8); 76 // Set up-left region of the texture as red color. 77 // In order to make sure bi-linear interpolation operates on different colors, red region 78 // is 1 pixel smaller than a quarter of the full texture on each side. 79 var redWidth = width / 2 - 1; 80 var redHeight = height / 2 - 1; 81 var buf = new Uint8Array(redWidth * redHeight * 4); 82 for (var i = 0; i < redWidth * redHeight; i++) { 83 buf[4 * i + 0] = 255; 84 buf[4 * i + 1] = 0; 85 buf[4 * i + 2] = 0; 86 buf[4 * i + 3] = 255; 87 } 88 gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, redWidth, redHeight, gl.RGBA, gl.UNSIGNED_BYTE, buf); 89 gl.generateMipmap(gl.TEXTURE_2D); 90 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST); 91 92 // Decode the srgba texture to a linear texture which will be used as reference. 93 var linearTex = gl.createTexture(); 94 gl.bindTexture(gl.TEXTURE_2D, linearTex); 95 wtu.fillTexture(gl, linearTex, width, height, wtu.sRGBToLinear(colors['srgba']), 0, gl.RGBA, gl.UNSIGNED_BYTE); 96 // Set up-left region of the texture as red color. 97 // In order to make sure bi-linear interpolation operates on different colors, red region 98 // is 1 pixel smaller than a quarter of the full texture on each side. 99 for (var i = 0; i < redWidth * redHeight; i++) { 100 buf[4 * i + 0] = 255; 101 buf[4 * i + 1] = 0; 102 buf[4 * i + 2] = 0; 103 buf[4 * i + 3] = 255; 104 } 105 gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, redWidth, redHeight, gl.RGBA, gl.UNSIGNED_BYTE, buf); 106 gl.generateMipmap(gl.TEXTURE_2D); 107 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST); 108 109 // Change canvas to a small size. 110 width = 64; 111 height = 64; 112 canvas.width = width; 113 canvas.height = height; 114 gl.viewport(0, 0, width, height); 115 116 // Draw with srgb texture and linear texture respectively. 117 gl.bindTexture(gl.TEXTURE_2D, srgbTex); 118 wtu.clearAndDrawUnitQuad(gl); 119 var result = new Uint8Array(width * height * 4); 120 gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, result); 121 gl.bindTexture(gl.TEXTURE_2D, linearTex); 122 wtu.clearAndDrawUnitQuad(gl); 123 var reference = new Uint8Array(width * height * 4); 124 gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, reference); 125 126 gl.deleteTexture(srgbTex); 127 gl.deleteTexture(linearTex); 128 129 var tolerance = 7; 130 var diff = new Uint8Array(width * height * 4); 131 var failed = wtu.comparePixels(result, reference, tolerance, diff); 132 if (failed) { 133 testFailed("Generate wrong mipmaps for sRGB texture."); 134 wtu.displayImageDiff(result, reference, diff, width, height); 135 } else { 136 testPassed("Generate correct mipmaps for sRGB texture."); 137 } 138 } 139 140 function generateMipmap_immutableTexture() 141 { 142 debug("Generate mipmaps for immutable texture."); 143 var tex = gl.createTexture(); 144 gl.bindTexture(gl.TEXTURE_2D, tex); 145 gl.texStorage2D(gl.TEXTURE_2D, Math.log2(canvas.width), gl.SRGB8_ALPHA8, canvas.width, canvas.height); 146 gl.generateMipmap(gl.TEXTURE_2D); 147 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "GenerateMipmap should succeed."); 148 149 gl.deleteTexture(tex); 150 } 151 152 function generateMipmap_widthHeightNotEqual() 153 { 154 debug("Generate mipmaps when width and height are not equal."); 155 var tex = gl.createTexture(); 156 gl.bindTexture(gl.TEXTURE_2D, tex); 157 gl.texImage2D(gl.TEXTURE_2D, 0, gl.SRGB8_ALPHA8, 64, 32, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 158 gl.generateMipmap(gl.TEXTURE_2D); 159 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "GenerateMipmap should succeed."); 160 161 gl.deleteTexture(tex); 162 } 163 164 function generateMipmap_maxLevelLessThanFullMipmapLevel() 165 { 166 debug("Generate mipmaps when maxLevel is less than full mipmap level."); 167 168 wtu.setupUnitQuad(gl, 0, 1); 169 var program = wtu.setupProgram( 170 gl, ['vshader', 'fshader'], ['vPosition', 'texCoord0'], [0, 1]); 171 172 var colors = [0, 63, 127, 255]; 173 174 var texLoc = gl.getUniformLocation(program, "tex"); 175 gl.uniform1i(texLoc, 0); 176 177 var width = 16; 178 var height = 16; 179 canvas.width = width; 180 canvas.height = height; 181 gl.viewport(0, 0, width, height); 182 183 var srgbTex = gl.createTexture(); 184 gl.bindTexture(gl.TEXTURE_2D, srgbTex); 185 wtu.fillTexture(gl, srgbTex, width, height, colors, 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.SRGB8_ALPHA8); 186 187 // Set max level, check if the max level mipmap is generated. 188 var max_level = 3; 189 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAX_LEVEL, max_level); 190 gl.generateMipmap(gl.TEXTURE_2D); 191 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST); 192 193 width >>= max_level; 194 height >>= max_level; 195 canvas.width = width; 196 canvas.height = height; 197 gl.viewport(0, 0, width, height); 198 199 gl.bindTexture(gl.TEXTURE_2D, srgbTex); 200 wtu.clearAndDrawUnitQuad(gl); 201 202 var reference = wtu.sRGBToLinear(colors); 203 var msg; 204 wtu.checkCanvasRect(gl, 0, 0, width, height, reference, msg, [1,1,1,1]); 205 206 gl.deleteTexture(srgbTex); 207 } 208 209 generateMipmap(); 210 generateMipmap_immutableTexture(); 211 generateMipmap_widthHeightNotEqual(); 212 generateMipmap_maxLevelLessThanFullMipmapLevel(); 213 214 var successfullyParsed = true; 215 </script> 216 <script src="../../../js/js-test-post.js"></script> 217 218 </body> 219 </html>