WebGL - Perspective Correct Textured Cube (modified)

Shows the impact of rectangular vs. non-rectangular geometry on texture mapping fidelity.

by Chrisssie

HTML

<canvas id="canvas"></canvas>
<!-- vertex shader -->
<script  id="vertex-shader-3d" type="x-shader/x-vertex">
attribute vec4 a_position;
attribute vec2 a_texcoord;

uniform mat4 u_matrix;

varying vec2 v_texcoord;

void main() {
  // Multiply the position by the matrix.
  gl_Position = u_matrix * a_position;

  // Pass the texcoord to the fragment shader.
  v_texcoord = a_texcoord;
}
</script>
<!-- fragment shader -->
<script  id="fragment-shader-3d" type="x-shader/x-fragment">
precision mediump float;

// Passed in from the vertex shader.
varying vec2 v_texcoord;

// The texture.
uniform sampler2D u_texture;

void main() {
   gl_FragColor = texture2D(u_texture, v_texcoord);
}
</script><!--
for most samples webgl-utils only provides shader compiling/linking and
canvas resizing because why clutter the examples with code that's the same in every sample.
See https://webglfundamentals.org/webgl/lessons/webgl-boilerplate.html
and https://webglfundamentals.org/webgl/lessons/webgl-resizing-the-canvas.html
for webgl-utils, m3, m4, and webgl-lessons-ui.
-->
<script src="https://webglfundamentals.org/webgl/resources/webgl-utils.js"></script>
<script src="https://webglfundamentals.org/webgl/resources/m4.js"></script>

CSS

@import url("https://webglfundamentals.org/webgl/resources/webgl-tutorials.css");
canvas {
  background: #888;
}

JavaScript

// WebGL - Perspective Correct Textured Cube (the default)
// from https://webglfundamentals.org/webgl/webgl-perspective-correct-cube.html

"use strict";

function main() {
  // Get A WebGL context
  /** @type {HTMLCanvasElement} */
  var canvas = document.querySelector("#canvas");
  var gl = canvas.getContext("webgl");
  if (!gl) {
    return;
  }

  // setup GLSL program
  var program = webglUtils.createProgramFromScripts(gl, ["vertex-shader-3d", "fragment-shader-3d"]);

  // look up where the vertex data needs to go.
  var positionLocation = gl.getAttribLocation(program, "a_position");
  var texcoordLocation = gl.getAttribLocation(program, "a_texcoord");

  // lookup uniforms
  var matrixLocation = gl.getUniformLocation(program, "u_matrix");
  var textureLocation = gl.getUniformLocation(program, "u_texture");

  // Create a buffer for positions
  var positionBuffer = gl.createBuffer();
  // Bind it to ARRAY_BUFFER (think of it as ARRAY_BUFFER = positionBuffer)
  gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
  // Put the positions in the buffer
  setGeometry(gl);

  // provide texture coordinates for the rectangle.
  var texcoordBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
  // Set Texcoords.
  setTexcoords(gl);

  // Create a texture.
  var texture = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, texture);
  // Fill the texture with a 4x4 LUMINANCE pixel.
  const level = 0;
  const format = gl.LUMINANCE;
  const type = gl.UNSIGNED_BYTE;
  const border = 0;
  const width = 8;
  const height = 8;
  const pixels = new Uint8Array([
    255,  64, 255,  64, 255,  64, 255,  64,
     64, 255,  64, 255,  64, 255,  64, 255,
    255,  64, 255,  64, 255,  64, 255,  64,
     64, 255,  64, 255,  64, 255,  64, 255,
    255,  64, 255,  64, 255,  64, 255,  64,
     64, 255,  64, 255,  64, 255,  64, 255,
    255,  64, 255,  64, 255,  64, 255,  64,
     64, 255,  64, 255,  64, 255,  64, 255,
  ]);
  gl.texImage2D(gl.TEXTURE_2D, level,...