"use strict";
const img = new Image();
img.onload = main;
img.crossOrigin = "";
img.src = "https://webglfundamentals.org/webgl/resources/noodles.jpg";
const vs = `#version 300 es
uniform mat4 u_worldViewProjection;
in vec4 a_position;
in vec2 a_texcoord;
in uint a_faceId;
out vec4 v_position;
out vec2 v_texCoord;
flat out uint v_faceId;
void main() {
v_faceId = a_faceId;
v_texCoord = a_texcoord;
gl_Position = u_worldViewProjection * a_position;
}
`;
const fs = `#version 300 es
precision mediump float;
in vec4 v_position;
in vec2 v_texCoord;
flat in uint v_faceId;
uniform mediump sampler2DArray u_diffuse;
uniform uint u_faceIndex[6];
out vec4 outColor;
void main() {
outColor = texture(u_diffuse, vec3(v_texCoord, u_faceIndex[v_faceId]));
}
`;
function main() {
twgl.setDefaults({attribPrefix: "a_"});
var m4 = twgl.m4;
var gl = document.querySelector("canvas").getContext("webgl2");
if (!gl) {
alert("Sorry, this example requires WebGL 2.0"); // eslint-disable-line
return;
}
var programInfo = twgl.createProgramInfo(gl, [vs, fs]);
var arrays = {
position: [1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1],
normal: [1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1],
texcoord: [1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1],
faceId: { numComponents: 1, data: new Uint8Array([0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6]), },
indices: [0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23],
};
var bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D_ARRAY, tex);
const levels = 7;
const width = 128;
const height = 128;
const depth = 8;
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, levels, gl.RGBA8, width, height, depth);
// Tell WebGL the size of one row
gl.pixelStorei(gl.UNPACK_ROW_LENGTH, img.width);
for (let d = 0; d < depth; ++d) {
const xoff = d % 4 * width;
const yoff = (d / 4 | 0) * height;
// Tell WebGL where to start copying from
gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, xoff);
gl.pixelStorei(gl.UNPACK_SKIP_ROWS, yoff);
const level = 0;
gl.texSubImage3D(gl.TEXTURE_2D_ARRAY, level, 0, 0, d, width, height, 1, gl.RGBA, gl.UNSIGNED_BYTE, img);
}
gl.generateMipmap(gl.TEXTURE_2D_ARRAY);
var uniforms = {
u_diffuse: tex,
u_faceIndex: [0, 1, 2, 3, 4, 5],
};
var oldTime = 0;
function render(time) {
time *= 0.001;
twgl.resizeCanvasToDisplaySize(gl.canvas);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
oldTime = time;
gl.enable(gl.DEPTH_TEST);
gl.enable(gl.CULL_FACE);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
var projection = m4.perspective(30 * Math.PI / 180, gl.canvas.clientWidth / gl.canvas.clientHeight, 0.5, 10);
var eye = [1, 4, -6];
var target = [0, 0, 0];
var up = [0, 1, 0];
var camera = m4.lookAt(eye, target, up);
var view = m4.inverse(camera);
var viewProjection = m4.multiply(projection, view);
var world = m4.rotationY(time);
uniforms.u_worldViewProjection = m4.multiply(viewProjection, world);
gl.useProgram(programInfo.program);
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
twgl.setUniforms(programInfo, uniforms);
twgl.drawBufferInfo(gl, bufferInfo);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
body {
margin: 0;
}
canvas {
display: block;
width: 100vw;
height: 100vh;
}
<canvas></canvas>
<script src="https://twgljs.org/dist/3.x/twgl-full.min.js"></script>
ImageBitmap
andArrayBufferView
which has an offer. Not sure how to get one of these from an image though and reliably get an offset etc. \$\endgroup\$