-
-
Save ROBERT-MCDOWELL/972f737d29d492176e4ba309db90dd9b to your computer and use it in GitHub Desktop.
WebGL initialization
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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