Retrospective changes to the lessons for the spec update

I’ve updated my tutorials to reflect the WebGL spec changes; they should now run just fine on the most recent versions of WebKit, Chromium, and Minefield, with shader validation switched on. I’ll be updating the lesson text later on this evening.[UPDATE the lessons are all now updated.]

If you’ve still to update your own WebGL pages to match the spec, here are the precise changes I made — they might make things easier for you.

At the start of every fragment shader, I put this:

  #ifdef GL_ES
  precision highp float;
  #endif

This is because all fragment shaders now need a qualifier to say what kind of floating-point precision they use; precision highp float gives you (as you’d expect) the highest precision. The #ifdef around it is a bit of guard code to stop this bit of code being executed in older browsers that don’t support this bit of the spec yet.

[UPDATE: this was changed on 1 December 2011 to be simply

  precision mediump float;

-- that is, medium precision floating point (because mobile devices, which are now beginning to support WebGL, often don't support high precision) and without the #ifdefs, because this is no longer required.]

The other change I had to make was to update the way I called texImage2D. I used to do this:

    gl.texImage2D(gl.TEXTURE_2D, 0, texture.image, true);

This created a texture using the HTML image element bound to texture.image, with a mip level of 0. It also flipped the image around the X axis, which I find useful because it allows me to have texture coordinates that have Y axes that increase as you go up the screen, but to use texture images in formats like GIF, whose Y coordinates increase as you go down the image. This now requires two steps: firstly, I call gl.pixelStorei with appropriate parameters to say that all textures I use should be flipped around the X axis:

    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);

Then, when I want to create a texture, I call this:

    gl.texImage2D(
        gl.TEXTURE_2D, 0,
        gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE,
        texture.image
    );

The first two parameters are the same as before, and the last parameter is the same image as before. In the middle, we have a constant to tell WebGL that the image that we’re loading has red, green, blue and alpha components, another to say that we want to store it in the same way [UPDATE: in the comments, Benoit Jacob from the Mozilla team explains that these two must be the same value, and actually specify how the image is stored on the graphics card; so long as you're loading the image from an HTML element, WebGL knows already what format it's on], and a final one to say that each component is stored as an unsigned byte.

Those changes were all that were necessary to get everything working for me; let me know if you have any problems!

You can leave a response, or trackback from your own site.

11 Responses to “Retrospective changes to the lessons for the spec update”

  1. Benoit Jacob says:

    - when you say “flipped around the X axis” do you mean the Y axis ?
    - the format and internalformat parameters are always required to be equal; however, if your original image is a HTMLElement or a ImageData so that JavaScript already knows its format, you are free to specify a different format to texImage2D(). The behavior will then be that the WebGL implementation converts your image from its original format to the format your specified. For example, you could have a 32 bpp image that you want to upload as 16 bpp to save texture memory.

    Disclaimers:
    – i’m no expert so if anything I said sounds strange, you probably know better than me.
    – the conversions between all 16bpp and 32bpp formats are not implemented yet in Minefield although that is coming soon (looking at reusing WebKit code there).

  2. giles says:

    Re: flipping — it’s a vertical flip but that means it’s about the X axis, no? Flipping around the Y axis would move stuff from the left to the right and vice versa.

    Re: the formats — thanks, that clarifies things!

  3. Benoit Jacob says:

    Re: flipping — woops, you’re right! I got confused :-)

  4. giles says:

    Hi Benoit — no problem!

  5. Jerry says:

    Hi giles
    Also I encountered the problem about “no precision specified for (float)” that I found this post.
    It’s great but it also didn’t show the Object as I modify as the instruction.

    My object is to modify the code that the sample “Basic native WebGL example” can show up on Chrome(6.0.495.0) which is on http://code.google.com/p/blender-webgl-exporter/.

    I did two things:
    1. Add
    #ifdef GL_ES
    precision highp float;
    #endif
    in the top of each tag:

    2. Modify as
    gl.texImage2D(gl.TEXTURE_2D, 0, texture.image, true);
    as
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);

    gl.texImage2D(
    gl.TEXTURE_2D, 0,
    gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE,
    texture.image
    );

    But error occurred, I try can the code and it listed in function:initBuffers():
    gl.bufferData(gl.ARRAY_BUFFER, new WebGLFloatArray(vertices), gl.STATIC_DRAW);
    error message is:
    ReferenceError: WebGlFloatArray is not defined

    WebGlFloatArray is not available now? and what shall I do to run this sample?
    Thanks

    Jerry

  6. Jerry says:

    Somethind didnot displayed:
    I did two things:

    1. Add
    #ifdef GL_ES
    precision highp float;
    #endif
    in the top of each tag:

    《script id=”shader-fs” type=”x-shader/x-fragment”》

    《/script》

  7. giles says:

    Hi Jerry — yup, they dropped WebGLXXXArray too — details in this post.

  8. Stephen Larson says:

    Thanks for the pointers here. I updated the “Basic native webGL example’ that was mentioned in this thread based on these pointers and some additional updates from the new Typed Array specification. You can find my modified index.html attached here:

    http://code.google.com/p/blender-webgl-exporter/issues/detail?id=11

  9. giles says:

    Thanks, Stephen — one of the many things on my to-do list is to revisit that exporter and stop it from gathering dust — I suspect a lot of people will find it useful it we just update it!

  10. KILE says:

    Hi!
    I don’t know if it’s possible, but I have a buffer of greyscale/16 bits per pixel image and I would like to load it.
    It’s there any way to load it?

    Something like:
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, gl.LUMINANCE, gl.UNSIGNED_SHORT, image);

    And instead of reading the image using image.src, I guess I should use createImage data, fill the buffer and use after it right?

    Thank you very much in advance

  11. giles says:

    Hi Kile — that’s not something I’ve tried to do, so I don’t know offhand. Perhaps someone on the WebGL forums could help?

Leave a Reply

Subscribe to RSS Feed Follow Learning WebGL on Twitter