//app.js
(async function () {
const canvas = document.getElementById("webgl-canvas");
const gl = canvas.getContext("webgl");
// Check for WebGL context
if (!gl) {
alert("WebGL not supported on this browser.");
throw new Error("WebGL not supported");
}
// Load shaders using await inside async function
const vertexShaderSource = await fetch("shaders/vertex.glsl").then((res) =>
res.text()
);
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
const fragmentShaderSource = await fetch("shaders/fragment.glsl").then(
(res) => res.text()
);
const fragmentShader = createShader(
gl,
gl.FRAGMENT_SHADER,
fragmentShaderSource
);
// Create the shader program
const program = createProgram(gl, vertexShader, fragmentShader);
gl.useProgram(program);
// Set up the geometry (a simple square)
const positions = new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]);
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
const positionAttributeLocation = gl.getAttribLocation(program, "a_position");
gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);
// Texture coordinates for the square
const texCoords = new Float32Array([0, 0, 1, 0, 0, 1, 1, 1]);
const texCoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, texCoords, gl.STATIC_DRAW);
const texCoordLocation = gl.getAttribLocation(program, "a_texCoord");
gl.enableVertexAttribArray(texCoordLocation);
gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0);
// Generate a checkerboard texture programmatically
createCheckerboardTexture(gl);
function createShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error(gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}
return shader;
}
function createProgram(gl, vertexShader, fragmentShader) {
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.error(gl.getProgramInfoLog(program));
gl.deleteProgram(program);
return null;
}
return program;
}
function createCheckerboardTexture(gl) {
const size = 64;
const data = new Uint8Array(size * size * 4);
// Generate checkerboard pattern
for (let y = 0; y < size; ++y) {
for (let x = 0; x < size; ++x) {
const offset = (y * size + x) * 4;
const color = (x & 8) ^ (y & 8) ? 255 : 0;
data[offset] = color; // Red
data[offset + 1] = color; // Green
data[offset + 2] = color; // Blue
data[offset + 3] = 255; // Alpha
}
}
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(
gl.TEXTURE_2D,
0,
gl.RGBA,
size,
size,
0,
gl.RGBA,
gl.UNSIGNED_BYTE,
data
);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
// Set the texture uniform
const textureLocation = gl.getUniformLocation(program, "u_texture");
gl.uniform1i(textureLocation, 0); // Texture unit 0
requestAnimationFrame(drawScene);
}
function drawScene() {
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
// Draw the square with the texture
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
}
})();