FAQ

From WebGL Public Wiki
Revision as of 22:02, 10 July 2012 by HulkHolden (talk | contribs)
Jump to navigation Jump to search

Programming

What is the recommended way to initialize WebGL?

It is recommended that you check for success or failure to initialize. If WebGL fails to initialize it is recommended you distinguish between failure because the browser doesn't support WebGL and failure because for some other reason. If the browser does not support WebGL then present the user with a link to "http://get.webgl.org". If WebGL failed for some other reason present the user with a link to "http://get.webgl.org/troubleshooting/"

You can determine if the browser supports WebGL by checking for the existence of WebGLRenderingContext.

if (window.WebGLRenderingContext) {
  // browser supports WebGL
}

If the browser supports WebGL and canvas.getContext("webgl") returns null then WebGL failed for some reason other than user's browser (no GPU, out of memory, etc...)

  if (!window.WebGLRenderingContext) {
    // the browser doesn't even know what WebGL is
    window.location = "http://get.webgl.org";
  } else {
    var canvas = document.getElementById("myCanvas");
    var ctx = canvas.getContext("webgl");
    if (!ctx) {
      // browser supports WebGL but initialization failed.
      window.location = "http://get.webgl.org/troubleshooting";
    }
  }

Note: You MUST check that the browser supports WebGL to know that getting null from canvas.getContext() means

There is a wrapper that will do all of this for you here.

Example using the wrapper

<html>
<body>
<script type="text/javascript" src="localpath/webgl-utils.js"></script>
<script>
  function init() {
    canvas = document.getElementById("c");
    gl = WebGLUtils.setupWebGL(canvas);
    if (!gl) {
      return;
    }
    ...
  }

  window.onload = init;
</script>
<canvas id="c"></canvas>
</body>
</html>

What is the recommended way to implement a rendering loop?

It is HIGHLY recommended you use requestAnimationFrame if it is available. There is a small cross browser implementationr available here.

Example using the wrapper.

<html>
<body>
<script type="text/javascript" src="localpath/webgl-utils.js"></script>
<script>
  window.onload = init;

  function init() {
    canvas = document.getElementById("c");
    ...
    // render the first frame.
    render();
  }

  function render() {
    // request render to be called for the next frame.
    window.requestAnimFrame(render, canvas);

    ...
    // render scene
    ...
  }
</script>
<canvas id="c"></canvas>
</body>
</html>

What is the recommended way to handle lost context?

See Handling Context Lost.

Why don't textures work in my vertex shader on browser/machine/os XXX?

WebGL conforms to the OpenGL ES 2.0 spec in this regard. Implementations advertise how many textures can be accessed in a vertex shader with

var numTexturesAvailableInVertexShader = gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS)

That value is allowed to be 0. In which case your code must take appropriate action.

Why don't my textures render?

WebGL conforms to the OpenGL ES 2.0 spec in this regard. Textures that are non-power-of-two (NPOT) do not render unless texture filtering is set so it does not require mips and texture wrapping is set to CLAMP_TO_EDGE. The default parameters of a texture require mips and are set to wrap so you must set the texture parameters appropriately.

gl.bindTexture(gl.TEXTURE_2D, someNPOTTexture);

// Turn off the need for mips.
gl.texParameter(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);

// Set wrapping to CLAMP_TO_EDGE
gl.texParamater(gl.TEXTURE_2D, gl.WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParamater(gl.TEXTURE_2D, gl.WRAP_T, gl.CLAMP_TO_EDGE);

Why do I get an error with gl.framebufferTexture2D on certain machines/browsers?

There is a bug in many NVidia drivers that requires that textures passed to framebufferTexture2D be renderable. In other words, they either must have all required mips or else must set filtering to not require mips. Since the texture is not renderable without those settings, set the texture parameters before calling framebufferTexture2D

var fbo = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);

var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.RGBA, null);

// Turn off the need for mips.
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);

// Set wrapping to CLAMP_TO_EDGE
gl.texParameteri(gl.TEXTURE_2D, gl.WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.WRAP_T, gl.CLAMP_TO_EDGE);

gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);