Testing the Waters with WebGL

Updated browser info as of May 1, 2010

  • Getting a WebGL browser
  • Firefox 4 and Safari partially work but do NOT have advanced vertex features
  • Chrome’s WebGL support is similar, but the features can be enabled:
    • Close all Chrome windows
    • Windows: [UserFolder]AppDataLocalGoogleChromeApplicationchrome.exe --use-gl=desktop
    • Mac: /Applications/Google Chrome.app/Contents/MacOS/Google Chrome --use-gl=desktop
  • Chrome’s and Firefox 4’s default vertex shader compiler has trouble with texture sampling in the vertex shader, so the demo skips that feature for those browsers. As Al mentioned in the comments, the plan to add the capability to the WebGL engine is in place.

After multiple people asked, I decided to give WebGL a try. I’m impressed but also annoyed.
Trying some features out
Check out my modified WebGL moon demo. Some credits are in the source.
screenshot moon
Overall thoughts on WebGL
Pros:

  • The graphics performance is an order of magnitude above any other web technology
  • Again, it’s really fast!
  • It stays fairly true to OpenGL (which is good if you’re familiar with OpenGL)

Cons:

  • The graphics performance is noticeably slower than a desktop app. And forget about using your CPU for anything else.
  • It says fairly true to OpenGL (is that antiquated, procedural, state-machine-based API the best that anyone can do?)
  • No released (non-beta) browser can run it by default.
  • It is OpenGL ES, rather than full OpenGL. Radom functions are just not implemented, but no documentation mentions what’s missing. In some cases whole features just don’t work (e.g. geometry shaders).
  • The crippled GLSL doesn’t have most built-in shader variables like texture coordinates and gl_normal, so you need to make your own “varying” pseudonyms.
  • HTML, javascript, and GLSL… ALL IN ONE FILE! Readability is lost.

Overall compatibility and tools (text completion and debugging those files) are going to be the primary determining factors in WebGL’s success. It’s early, so we’ll have to see what happens.

21 thoughts on “Testing the Waters with WebGL

  1. Steve Haroz Post author

    Hi Giles,

    Thanks, but this texture loader already does that:

    function handleLoadedTexture(texture) {
        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
        gl.bindTexture(gl.TEXTURE_2D, texture);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
        gl.generateMipmap(gl.TEXTURE_2D);
        gl.bindTexture(gl.TEXTURE_2D, null);
    }

    The problem is that the displacement mapping accesses a texture in the vertex shader. Chrome has recently disallowed this feature. It works in Firefox 4 though.

    This version (without displacement mapping) is Chrome friendly – http://steveharoz.com/test/webgl/no_displacement.html

    By the way, thanks for your site! It really helped me get off the ground.

  2. Giles

    Aha, thanks — I saw the error message on Chrome and jumped to the conclusion that it was a spec-change problem. It looks really cool in Minefield! The Chromium version looks great too, though it did crash my browser — an old version, though.

    Glad you found the site useful!

  3. Pingback: WebGL around the net, 9 December 2010 | Learning WebGL

  4. Al

    Chromium should be reporting MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0 to indicate that it does not support texture lookup in vertex shaders. It’s not so much a bug as a disappointment.

    The underlying reason is, by default, Chromium uses Direct3D 9 for rendering and that has pretty limited support for vertex texture lookup. For example, nVidia drivers tend to report that they only support lookup of floating point textures from vertex shaders (not fixed point) and that is not GL ES 2 compliant.

    Possible workarounds: Check MAX_VERTEX_TEXTURE_IMAGE_UNITS at runtime and fallback only if it is too low (or zero). Or launch Chromium with the “–use-gl=desktop” command line switch and it will use OpenGL for rendering and that may or may not support vertex texture lookup depending on the OpenGL driver installed.

    The plan to get this working going forward is here.

    http://code.google.com/p/angleproject/wiki/VTF

  5. Steve Haroz Post author

    Hi Al,

    Thanks for the info.

    In this demo, the function, testBrowserCapability, does check if MAX_VERTEX_TEXTURE_IMAGE_UNITS > 0.

    I initially tried passing a uniform boolean in the shader to conditionally sample via texture2D or use a constant. The problem was that the shader wouldn’t even compile in Chrome (which makes sense if DX9 is used).

    My solution (hack :)) was to create two vertex shaders, shader-vs and shader-vs-chrome. They are identical except for the line with texture2D (the Chrome version uses a constant).

    I’m glad to see that a plan is in place. I’m looking forward to using the feature!

  6. Al

    Steve,

    Looking at the ANGLE code, I see what might be the problem. The relevant source code is here:

    http://code.google.com/p/angleproject/source/browse/trunk/src/compiler/OutputHLSL.cpp?r=511

    I think ANGLE assumes that, since a vertex texture fetch is actually not possible from a vertex shader in ANGLE, it need not at least output a stub function that does nothing. However, I think a call to texture2D or similar is syntactically and semantically valid if it is predicated on a false condition, such as a false uniform. The vertex shader should at least compile even if texture2D returns, for example, a constant.

    If that is true then it is a bug worth reporting. If you report it on the Chromium issue tracker or link a previously filed bug and post the link on your blog, I’ll get the bug to the right person:

    http://crbug.com

    Otherwise, I’ll make sure the right person knows and I’ll give you credit for the find.

    Thanks,

    Al

  7. Al

    Thanks. I commented on it.

    Rather than using a uniform bool to predicate the use of vertex texture fetch, I think using the preprocessor will work.

    vec4 foo;

    #ifdef VTF
    foo = texture2D(sampler, uv);
    #else
    foo = vev4(0, 0, 0, 0);
    #endif

    Then just pass in “#define VTF” if MAX_VERTEX_TEXTURE_IMAGE_UNITS > 0.

    Al

    1. Steve Haroz Post author

      Cool. From what I can discern, the shader compiler has no way of accepting precompiler definitions as arguments, so they have to be manually added to the code.

      I was concerned that when debugging, the line numbers would be different for each condition, so I added #define DUMMY to equalize the lines.

      The function’s below:
      function ApplyVertexTexturesCheck(source) {
        var define = "#define VERTEX_TEXTURES";
        if (gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS) <= 0) {
          define = "#define DUMMY"; // use dummy, so line #s are consistent
          // show warning
        }
        return define + "n" + source;
      }

  8. Al

    As it happens, I’m working on better PIX integration for ANGLE. I have a prototype that does two things.

    First, for profiling and debugging purposes, it groups the D3D calls in terms of the GL ES 2 calls they correspond to. So for a particular set of frames, I can see what GL ES 2 calls were issued, when and what their arguments were. Second it allows source level debugging of GLSL ES shaders rather than the default HLSL. So I can single step through GLSL ES vertex and fragment shaders at the source level and see the contents of variables each step along the way.

    I’ve found it really useful in my work and hope to get it working with Chrome soon. PIX has always been able to do this – I’m just trying to support WebGL and ANGLE’s GL ES 2 implementation better.

    I’d be interested, if you’re willing to share, in understanding your approach to shader debugging. Have you found a way to use a tool like PIX? Are you doing my favorite trick of sticking whatever value you want to visualize into gl_FragColor?

    Your approach of inserting a dummy macro define would not be necessary with my current PIX integration approach. It’s neat though 🙂

    Al

  9. Harshad

    The demo didn’t work in Chrome 15 and nor in Firefox 8, both on WIndows XP.

    Looks like the problem is not solved yet. I am able to run other WebGL demos though.

    1. Steve Haroz Post author

      Hi Harshad,

      I’ve confirmed that the demo works on both Chrome 15 and Firefox 8. It could be your GPU. Try running the benchmark here, and check your value for MAX_VERTEX_TEXTURE_IMAGE_UNITS. If it is less than 2, it’s just a hardware or driver limitation.

  10. Harshad

    Hi Steve,

    Sorry, I made a mistake. Soon after posting I realized that Firefox didn’t have WebGL turned on (because I was using it from a different login than usual). It had to be forced on and then the demo worked, sort of. There were some multi-color lines similar to the screenshot in your post, but not exactly. (Will post my screenshot the next time I boot into Windows).

    Just now I tried the demo in Firefox 8 on Linux and it worked fine albeit slowly. So I guess it is a driver limitation on Windows. I couldn’t complete the benchmark on Linux as it kept popping an “unresponsive script” message every few seconds.

    cheers,
    Harshad

  11. julian

    Hello, I am doing the final project, I must do in WPF, an application has to show an animation in WebGL.
    How could it?
    Thank you.

  12. julian

    I think not, because the application that I want to show in my WPF application is made in WebGL.
    My idea was to embed a web browser that supports WebGL. But if this is possible.

  13. AAA

    How can PIX be used to debug DX Calls which are happening through different exe’s (Both exe’s are of Chrome )for a Application. Pls Reply asap…

Comments are closed.