Search code examples
three.jstextureswebglrendering

WebGL crashes when generating a texture - OutOfMemory


I currently use Three.js in a bigger web project. Everything works fine and there is no issue with rendering and so on. The only problem I am running into is kind of specific.

In a part of my project, the user is able to position an image on a 3D-Model through a canvas, which is used as texture. Sometimes, when the user is really fast changing the position via clicks, WebGL stops working.

In Chrome :

Rats! WebGL hit a Snag - alert

So the user has to reload the page.

Is this actually a performance issue?
If it is, is the only way to reduce the speed of transformations per second? Or is there something like a try/catch thing so it will just perform the transformation, if it will not lead to block WebGL?

I really want to keep this live positioning of the Image on the 3D-Model.

Also I could hide other objects in the scene, so only the object on which the image is positioned will be shown, would that help?

Thank you for your time and answers!

This is the actual error in the console :

GL_INVALID_OPERATION : glGenSyncTokenCHROMIUM:
fence sync must be flushed before generating sync token

filename.html:1 WebGL: CONTEXT_LOST_WEBGL: loseContext: context lost

The code executed for each click is :

context = canvas.getContext("2d");
canvas.width = 1024;
canvas.height = 1024;
canvas.style.width = canvas.width + "px";
canvas.style.height = canvas.height + "px";
context.clearRect(0, 0, canvas.width, canvas.height);

context.save();
context.setTransform(1, 0, 0, 1, x + width / 2, y + height / 2);
context.rotate(angle * TO_RADIANS);
var imgT = new Image();
imgT.src = fotoprintPath + this.id;
context.drawImage(imgT, -width / 2, -height / 2, width, height);
context.restore();

matTexture.map = new THREE.Texture(canvas);
matTexture.map.needsUpdate = true;

Does it have something to do with asynchrone function calls, like WebGL has not finished the previous task and so crashes?

In Firefox the browser just crashes. I hope somebody can help with this, or tell me how to avoid it.

**Update When I restrict the clicks per second is not a satisfying solution. The problem by this solution is, either I have to allow only 1 click per second (which makes positioning very slow) or I use the clicks per second my PC can handle but this causes users of tablets and slow PC's to still recieve the error.

What I really need is a function like this

function canPerformTextureTransformation(){
   if(availableMemory >= neededMemory)
       return true;
   else
       return false;
 }

But how can I check for the memory that will be needed and the available memory?


Solution

  • I found a solution, which seems to completly solve the problem.

    I just reduced the size of the applied texture from 1024x1024 to 256x256

    canvas.width = 1024; --> canvas.width = 256;
    canvas.height = 1024; --> canvas.height = 256;
    canvas.style.width = canvas.width + "px";
    canvas.style.height = canvas.height + "px";
    

    This is not what I searched, but there is no real visible change in the result, so it is an workaround which I will use. By changing this, all operations are much faster.