Skip to content

Instantly share code, notes, and snippets.

@x-labz
Last active December 16, 2023 12:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save x-labz/c834b6211dc90450b081e1cfa906b3bf to your computer and use it in GitHub Desktop.
Save x-labz/c834b6211dc90450b081e1cfa906b3bf to your computer and use it in GitHub Desktop.
WebGL initialization
var glRef = {};
function loadImage(src) {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => {
resolve(img);
};
img.src = src;
});
}
// The required resolution is passed as parameters
const initWebGL = async ({ width, height }) => {
const backgroundImage = await loadImage("./seaside.png");
const canvas =
document.querySelector("#canvas") || document.createElement("canvas");
canvas.width = width;
canvas.height = height;
const gl = canvas.getContext("webgl2");
if (!gl) {
return;
}
glRef.gl = gl;
// setup GLSL program, for simplicity they are stored in HTML script tags
// use webglUtils from https://webgl2fundamentals.org/
const program = webglUtils.createProgramFromScripts(gl, [
"vertex-shader",
"fragment-shader",
]);
gl.useProgram(program);
const positionLocation = gl.getAttribLocation(program, "a_position");
const texcoordLocation = gl.getAttribLocation(program, "a_texCoord");
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
// Set a rectangle the same size as the image.
const x1 = 0;
const x2 = 0 + width;
const y1 = 0;
const y2 = 0 + height;
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array([x1, y1, x2, y1, x1, y2, x1, y2, x2, y1, x2, y2]),
gl.STATIC_DRAW
);
// provide texture coordinates for the rectangle.
const texcoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array([
0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0,
]),
gl.STATIC_DRAW
);
const textures = [];
// Create a texture for the background image
{
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
// Set the parameters so we can render any size image.
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
// Upload the image into the texture.
gl.texImage2D(
gl.TEXTURE_2D,
0,
gl.RGBA,
gl.RGBA,
gl.UNSIGNED_BYTE,
backgroundImage
);
textures[0] = texture;
}
// create texture for the video frame
{
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
// Set the parameters so we can render any size image.
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
const pixelData = new Uint8Array(1.5 * width * height);
// Upload the image into the texture.
gl.texImage2D(
gl.TEXTURE_2D,
0,
gl.LUMINANCE, // <-- monochrome texture, not RGBA!!!
width,
height * 1.5,
0,
gl.LUMINANCE,
gl.UNSIGNED_BYTE,
pixelData,
0
);
textures[1] = texture;
}
const u_image = gl.getUniformLocation(program, "u_image");
const u_image_frame = gl.getUniformLocation(program, "u_image_frame");
// set which texture units to render with.
gl.uniform1i(u_image, 0); // texture unit 0
gl.uniform1i(u_image_frame, 1); // texture unit 1
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, textures[0]);
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, textures[1]);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.clearColor(0, 0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
// Turn on the position attribute
gl.enableVertexAttribArray(positionLocation);
// Bind the position buffer.
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
// Tell the position attribute how to get data out of positionBuffer (ARRAY_BUFFER)
{
const size = 2;
const type = gl.FLOAT;
const normalize = false;
const stride = 0;
const offset = 0;
gl.vertexAttribPointer(
positionLocation,
size,
type,
normalize,
stride,
offset
);
}
// Turn on the texcoord attribute
gl.enableVertexAttribArray(texcoordLocation);
// bind the texcoord buffer.
gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
// Tell the texcoord attribute how to get data out of texcoordBuffer (ARRAY_BUFFER)
{
const size = 2;
const type = gl.FLOAT;
const normalize = false;
const stride = 0;
const offset = 0;
gl.vertexAttribPointer(
texcoordLocation,
size,
type,
normalize,
stride,
offset
);
}
// lookup uniforms
const resolutionLocation = gl.getUniformLocation(program, "u_resolution");
// set the resolution
gl.uniform2f(resolutionLocation, gl.canvas.width, gl.canvas.height);
// Draw the rectangle.
gl.drawArrays(gl.TRIANGLES, 0, 6);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment