texture-sub-image-cube-maps.html (9416B)
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 texSubImage2Ds cube map 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="256" height="256" style="width: 40px; height: 40px;"></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 uniform mat4 rotation; 23 varying vec3 texCoord; 24 void main() 25 { 26 gl_Position = vPosition; 27 vec4 direction = vec4(vPosition.x * 0.5, vPosition.y * 0.5, 1, 1); 28 texCoord = normalize((rotation * direction).xyz); 29 } 30 </script> 31 32 <script id="fshader" type="x-shader/x-fragment"> 33 precision mediump float; 34 uniform samplerCube tex; 35 varying vec3 texCoord; 36 void main() 37 { 38 gl_FragColor = textureCube(tex, normalize(texCoord)); 39 } 40 </script> 41 <script> 42 "use strict"; 43 var canvas; 44 description("Checks issues with size of cube map textures"); 45 debug(""); 46 47 var wtu = WebGLTestUtils; 48 var canvas = document.getElementById("example"); 49 50 var gl = wtu.create3DContext(canvas); 51 wtu.setupUnitQuad(gl, 0, 1); 52 var program = wtu.setupProgram( 53 gl, 54 ['vshader', 'fshader'], 55 ['vPosition', 'texCoord0'], [0, 1]); 56 var rotLoc = gl.getUniformLocation(program, "rotation"); 57 58 var size = 16; 59 60 var colors = [ 61 {name: 'red', color: [255, 0, 0, 255]}, 62 {name: 'green', color: [ 0, 255, 0, 255]}, 63 {name: 'blue', color: [ 0, 0, 255, 255]}, 64 {name: 'yellow', color: [255, 255, 0, 255]}, 65 {name: 'cyan', color: [ 0, 255, 255, 255]}, 66 {name: 'magenta', color: [255, 0, 255, 255]} 67 ]; 68 69 var targets = [ 70 gl.TEXTURE_CUBE_MAP_POSITIVE_X, 71 gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 72 gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 73 gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 74 gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 75 gl.TEXTURE_CUBE_MAP_NEGATIVE_Z]; 76 77 var rotations = [ 78 {axis: [0, 1, 0], angle: Math.PI / 2}, 79 {axis: [0, 1, 0], angle: -Math.PI / 2}, 80 {axis: [1, 0, 0], angle: -Math.PI / 2}, 81 {axis: [1, 0, 0], angle: Math.PI / 2}, 82 {axis: [0, 1, 0], angle: 0}, 83 {axis: [0, 1, 0], angle: Math.PI}, 84 ]; 85 86 var halfRotations = [ 87 {colors: [3, 4], rotations: [{axis: [1, 0, 0], angle: Math.PI / 4}]}, 88 {colors: [4, 2], rotations: [{axis: [1, 0, 0], angle: -Math.PI / 4}]}, 89 {colors: [5, 3], rotations: [{axis: [1, 0, 0], angle: Math.PI / 4 * 3}]}, 90 {colors: [2, 5], rotations: [{axis: [1, 0, 0], angle: -Math.PI / 4 * 3}]}, 91 {colors: [3, 0], rotations: [{axis: [0, 1, 0], angle: Math.PI / 2}, 92 {axis: [1, 0, 0], angle: Math.PI / 4}]}, 93 {colors: [0, 2], rotations: [{axis: [0, 1, 0], angle: Math.PI / 2}, 94 {axis: [1, 0, 0], angle: -Math.PI / 4}]}, 95 ]; 96 97 var count = 0; 98 testSize(size); 99 100 function testSize(size) { 101 debug(""); 102 debug("testing size: " + size); 103 var canvasSize = Math.max(size / 4, 2); 104 canvas.width = canvasSize; 105 canvas.height = canvasSize; 106 gl.viewport(0, 0, canvasSize, canvasSize); 107 var tex = gl.createTexture(); 108 gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex); 109 110 // Seems like I should be using LINEAR here with some other math 111 // to make sure I get more mip coverage but that's easier said 112 // than done. 113 114 gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 115 gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 116 117 for (var jj = 0; jj < 2; ++jj) { 118 for (var tt = 0; tt < targets.length; ++tt) { 119 var color = colors[(tt + count) % colors.length]; 120 fillLevel(targets[tt], 0, size, color.color); 121 } 122 if (jj == 1) { 123 debug("use mipmap"); 124 gl.texParameteri( 125 gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, 126 gl.NEAREST_MIPMAP_NEAREST); 127 gl.generateMipmap(gl.TEXTURE_CUBE_MAP); 128 } 129 130 var err = gl.getError(); 131 if (err == gl.OUT_OF_MEMORY) { 132 debug("out of memory"); 133 return false; 134 } 135 if (err != gl.NO_ERROR) { 136 testFailed("unexpected gl error: " + wtu.glEnumToString(gl, err)); 137 } 138 139 140 for (var rr = 0; rr < rotations.length; ++rr) { 141 var rot = rotations[rr]; 142 var color = colors[(rr + count) % colors.length]; 143 var rotMat = axisRotation(rot.axis, rot.angle); 144 gl.uniformMatrix4fv(rotLoc, false, rotMat); 145 wtu.clearAndDrawUnitQuad(gl); 146 wtu.checkCanvas( 147 gl, color.color, 148 wtu.glEnumToString(gl, targets[rr]) + " should be " + color.name); 149 } 150 151 for (var rr = 0; rr < halfRotations.length; ++rr) { 152 var h = halfRotations[rr]; 153 var rots = h.rotations; 154 var rotMat = axisRotation(rots[0].axis, rots[0].angle); 155 for (var ii = 1; ii < rots.length; ++ii) { 156 var tmpMat = axisRotation(rots[ii].axis, rots[ii].angle); 157 var rotMat = mulMatrix(tmpMat, rotMat); 158 } 159 gl.uniformMatrix4fv(rotLoc, false, rotMat); 160 wtu.clearAndDrawUnitQuad(gl); 161 162 for (var ii = 0; ii < 2; ++ii) { 163 checkRect( 164 0, 165 canvasSize / 2 * ii, 166 canvasSize, 167 canvasSize / 2, 168 colors[(h.colors[ii] + count) % colors.length]); 169 } 170 } 171 ++count; 172 } 173 174 gl.deleteTexture(tex); 175 return true; 176 } 177 178 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors."); 179 180 function checkRect(x, y, width, height, color) { 181 wtu.checkCanvasRect( 182 gl, 183 x, 184 y, 185 width, 186 height, 187 color.color, 188 "" + x + ", " + y + ", " + width + ", " + height + 189 " should be " + color.name); 190 } 191 192 function fillLevel(target, level, size, color) { 193 var numPixels = size * size; 194 var halfPixelRow = new Uint8Array(size * 2); 195 for (var jj = 0; jj < size; ++jj) { 196 var off = jj * 4; 197 halfPixelRow[off + 0] = color[0]; 198 halfPixelRow[off + 1] = color[1]; 199 halfPixelRow[off + 2] = color[2]; 200 halfPixelRow[off + 3] = color[3]; 201 } 202 gl.texImage2D( 203 target, level, gl.RGBA, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, 204 null); 205 for (var jj = 0; jj < size; ++jj) { 206 gl.texSubImage2D( 207 target, level, 0, jj, size / 2, 1, gl.RGBA, gl.UNSIGNED_BYTE, halfPixelRow); 208 gl.texSubImage2D( 209 target, level, size / 2, jj, size / 2, 1, gl.RGBA, gl.UNSIGNED_BYTE, halfPixelRow); 210 } 211 } 212 213 function printMat(mat) { 214 debug("" + mat[0] + ", " + mat[1] + ", " + mat[2] + ", " + mat[3] + ", "); 215 debug("" + mat[4] + ", " + mat[5] + ", " + mat[6] + ", " + mat[7] + ", "); 216 debug("" + mat[8] + ", " + mat[9] + ", " + mat[10] + ", " + mat[11] + ", "); 217 debug("" + mat[12] + ", " + mat[13] + ", " + mat[14] + ", " + mat[15] + ", "); 218 } 219 220 function axisRotation(axis, angle) { 221 var dst = new Float32Array(16); 222 var x = axis[0]; 223 var y = axis[1]; 224 var z = axis[2]; 225 var n = Math.sqrt(x * x + y * y + z * z); 226 x /= n; 227 y /= n; 228 z /= n; 229 var xx = x * x; 230 var yy = y * y; 231 var zz = z * z; 232 var c = Math.cos(angle); 233 var s = Math.sin(angle); 234 var oneMinusCosine = 1 - c; 235 236 dst[ 0] = xx + (1 - xx) * c; 237 dst[ 1] = x * y * oneMinusCosine + z * s; 238 dst[ 2] = x * z * oneMinusCosine - y * s; 239 dst[ 3] = 0; 240 dst[ 4] = x * y * oneMinusCosine - z * s; 241 dst[ 5] = yy + (1 - yy) * c; 242 dst[ 6] = y * z * oneMinusCosine + x * s; 243 dst[ 7] = 0; 244 dst[ 8] = x * z * oneMinusCosine + y * s; 245 dst[ 9] = y * z * oneMinusCosine - x * s; 246 dst[10] = zz + (1 - zz) * c; 247 dst[11] = 0; 248 dst[12] = 0; 249 dst[13] = 0; 250 dst[14] = 0; 251 dst[15] = 1; 252 253 return dst; 254 }; 255 256 function mulMatrix(a, b) { 257 var dst = new Float32Array(16); 258 var a00 = a[0]; 259 var a01 = a[1]; 260 var a02 = a[2]; 261 var a03 = a[3]; 262 var a10 = a[ 4 + 0]; 263 var a11 = a[ 4 + 1]; 264 var a12 = a[ 4 + 2]; 265 var a13 = a[ 4 + 3]; 266 var a20 = a[ 8 + 0]; 267 var a21 = a[ 8 + 1]; 268 var a22 = a[ 8 + 2]; 269 var a23 = a[ 8 + 3]; 270 var a30 = a[12 + 0]; 271 var a31 = a[12 + 1]; 272 var a32 = a[12 + 2]; 273 var a33 = a[12 + 3]; 274 var b00 = b[0]; 275 var b01 = b[1]; 276 var b02 = b[2]; 277 var b03 = b[3]; 278 var b10 = b[ 4 + 0]; 279 var b11 = b[ 4 + 1]; 280 var b12 = b[ 4 + 2]; 281 var b13 = b[ 4 + 3]; 282 var b20 = b[ 8 + 0]; 283 var b21 = b[ 8 + 1]; 284 var b22 = b[ 8 + 2]; 285 var b23 = b[ 8 + 3]; 286 var b30 = b[12 + 0]; 287 var b31 = b[12 + 1]; 288 var b32 = b[12 + 2]; 289 var b33 = b[12 + 3]; 290 dst[ 0] = a00 * b00 + a01 * b10 + a02 * b20 + a03 * b30; 291 dst[ 1] = a00 * b01 + a01 * b11 + a02 * b21 + a03 * b31; 292 dst[ 2] = a00 * b02 + a01 * b12 + a02 * b22 + a03 * b32; 293 dst[ 3] = a00 * b03 + a01 * b13 + a02 * b23 + a03 * b33; 294 dst[ 4] = a10 * b00 + a11 * b10 + a12 * b20 + a13 * b30; 295 dst[ 5] = a10 * b01 + a11 * b11 + a12 * b21 + a13 * b31; 296 dst[ 6] = a10 * b02 + a11 * b12 + a12 * b22 + a13 * b32; 297 dst[ 7] = a10 * b03 + a11 * b13 + a12 * b23 + a13 * b33; 298 dst[ 8] = a20 * b00 + a21 * b10 + a22 * b20 + a23 * b30; 299 dst[ 9] = a20 * b01 + a21 * b11 + a22 * b21 + a23 * b31; 300 dst[10] = a20 * b02 + a21 * b12 + a22 * b22 + a23 * b32; 301 dst[11] = a20 * b03 + a21 * b13 + a22 * b23 + a23 * b33; 302 dst[12] = a30 * b00 + a31 * b10 + a32 * b20 + a33 * b30; 303 dst[13] = a30 * b01 + a31 * b11 + a32 * b21 + a33 * b31; 304 dst[14] = a30 * b02 + a31 * b12 + a32 * b22 + a33 * b32; 305 dst[15] = a30 * b03 + a31 * b13 + a32 * b23 + a33 * b33; 306 return dst; 307 }; 308 309 var successfullyParsed = true; 310 </script> 311 <script src="../../../js/js-test-post.js"></script> 312 313 </body> 314 </html>