0

I'm trying to do some behind the scenes rendering work with WebGL and then copy the canvas data to an image.

I'm able to accomplish this successfully with a physical canvas element on the page, however, once I try to replace my

const canvas = document.getElementById("glcanvas") with either
const cavnas = document.createElement("canvas") or
const canvas = new OffscreenCanvas(640, 480)

My render doesn't seem to work anymore.

Interestingly I still see my WebGL clear color so I know it's rendering something. If I go back to the getElemeentById method with a physical canvas in the DOM, everything works fine, any ideas?

code (I pretty much just followed the Mozilla tutorial for WebGL, some code is omitted because it is not important):

function main() {
    // Initialize the GL context
    const canvas = new OffscreenCanvas(640, 480)
    const gl = canvas.getContext("webgl2")
    
    // Only continue if WebGL is available and working
    if (gl === null) {
        alert("Unable to initialize WebGL. Your browser or machine may not support it.")
        return
    }
        
    // Set clear color to black, fully opaque
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    // Clear the color buffer with specified clear color
    gl.clear(gl.COLOR_BUFFER_BIT);

    // Initialize a shader program; this is where all the lighting
    // for the vertices and so forth is established.
    const shaderProgram = initShaderProgram(gl, vsSource, fsSource);

    // Collect all the info needed to use the shader program.
    // Look up which attributes our shader program is using
    // for aVertexPosition, aVertexColor and also
    // look up uniform locations.
    const programInfo = {
        program: shaderProgram,
        attribLocations: {
            vertexPosition: gl.getAttribLocation(shaderProgram, "aVertexPosition"),
            vertexColor: gl.getAttribLocation(shaderProgram, "aVertexColor"),
        },
        uniformLocations: {
            projectionMatrix: gl.getUniformLocation(
                shaderProgram,
                "uProjectionMatrix"
            ),
            modelViewMatrix: gl.getUniformLocation(shaderProgram, "uModelViewMatrix"),
        },
    };
    
    const objects = [
        initCuboid(
            gl,
            {x: 0, y: 0, z: 0},
            {x: 1, y: 1, z: 1},
            {pitch: 0, yaw: 0, roll: 0} 
        ),
        initCuboid(
            gl,
            {x: 0, y: 2, z: 0},
            {x: .5, y: .5, z: .5},
            {pitch: 0, yaw: 0, roll: 0} 
        ),

    ]

    function render() {
        drawScene(gl, programInfo, objects);
        canvas.convertToBlob().then((res) => {
            document.getElementById("glimg").src = URL.createObjectURL(res)
        })
        requestAnimationFrame(render)
    }

    requestAnimationFrame(render)
}
Benjamin Kosten
  • 361
  • 2
  • 12
  • 1
    Which browser? Also, while this should work, know that your code is very inneficient, and you should refrain from doing something like that. To render the canvas result, just append the (placeholder) canvas in the page, don't create a new image file +load it a every frame. – Kaiido Dec 28 '22 at 15:09
  • tested on both chrome + firefox (latest version). I agree this is inefficient, my actual code just calls `drawScene` once and then calls `convertToBlob` is there some sort of way to know when WebGL is done drawing the scene? Maybe I'm rendering the scene as an image before I get a chance to actually render the full scene. – Benjamin Kosten Dec 28 '22 at 15:42

0 Answers0