I’ve tried to adapt the example and also asked some help from GPT-4, though I’m not getting any tangible results. I’m not versed in lower level WebGL so I’m a bit lost, I’d really appreciate anyone who could point me in the right direction. 
Here’s my current code:
const canvas = this.app.graphicsDevice.canvas;
const bindingContext = canvas.getContext("webgl2");
this.glBinding = new XRWebGLBinding(this.app.xr.session, bindingContext);
const gl = document.getElementById('debugCanvas').getContext('webgl');
this.app.xr.on ('update', (frame) => {
if (!this.app.takeScreenshot) return;
this.app.takeScreenshot = false;
if (!xrRefSpace) {
console.log ('no ref space');
return;
}
let pose = frame.getViewerPose(xrRefSpace);
for (const view of pose.views) {
if (view.camera) {
let camera = view.camera,
webXRTexture = this.glBinding.getCameraImage(camera);
// 2. Create a framebuffer
const framebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
// 3. Create a new destination texture
const destinationTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, destinationTexture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, canvas.width, canvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
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.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
// 4. Attach the destination texture to the framebuffer
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, destinationTexture, 0);
// 5. Set up the viewport
gl.viewport(0, 0, canvas.width, canvas.height);
// 6. Create a vertex buffer and an index buffer
const quadVertices = [
-1, -1, 0, 0,
1, -1, 1, 0,
1, 1, 1, 1,
-1, 1, 0, 1
];
const quadIndices = [
0, 1, 2,
0, 2, 3
];
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(quadVertices), gl.STATIC_DRAW);
const indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(quadIndices), gl.STATIC_DRAW);
// 7. Create a shader program
const vertexShaderSource = `
attribute vec2 aPosition;
attribute vec2 aTexCoord;
varying vec2 vTexCoord;
void main() {
gl_Position = vec4(aPosition, 0.0, 1.0);
vTexCoord = aTexCoord;
}
`;
const fragmentShaderSource = `
precision mediump float;
uniform sampler2D uTexture;
varying vec2 vTexCoord;
void main() {
gl_FragColor = texture2D(uTexture, vTexCoord);
}
`;
function createShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
throw new Error(`An error occurred compiling the shader: ${gl.getShaderInfoLog(shader)}`);
}
return shader;
}
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
throw new Error(`Unable to initialize the shader program: ${gl.getProgramInfoLog(shaderProgram)}`);
}
// 8. Bind the buffers, texture, and shader program
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.useProgram(shaderProgram);
const positionAttribute = gl.getAttribLocation(shaderProgram, 'aPosition');
gl.enableVertexAttribArray(positionAttribute);
gl.vertexAttribPointer(positionAttribute, 2, gl.FLOAT, false, 16, 0);
const texCoordAttribute = gl.getAttribLocation(shaderProgram, 'aTexCoord');
gl.enableVertexAttribArray(texCoordAttribute);
gl.vertexAttribPointer(texCoordAttribute, 2, gl.FLOAT, false, 16, 8);
const textureUniformLocation = gl.getUniformLocation(shaderProgram, 'uTexture');
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, webXRTexture); // Use webXRTexture as the source texture
gl.uniform1i(textureUniformLocation, 0);
// 9. Draw the textured quad
gl.clearColor(0, 0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawElements(gl.TRIANGLES, quadIndices.length, gl.UNSIGNED_SHORT, 0);
// 10. Unbind the framebuffer and display the result
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
// 11. Draw the destination texture on the canvas
gl.bindTexture(gl.TEXTURE_2D, destinationTexture);
gl.clearColor(0, 0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawElements(gl.TRIANGLES, quadIndices.length, gl.UNSIGNED_SHORT, 0);
}
}
});