Wednesday, March 14, 2012

Anisotropic Filtering in WebGL

On Google+ this morning Ilmari Heikkinen pointed out that support for the EXT_texture_filter_anisotropic WebGL extension landed in Webkit a little over a week ago. That's awesome, as it's one of the features that I've been waiting for essentially since I first started playing with WebGL.

[Update: To give credit where credit is due I've had several people point out that Firefox had this feature first. Guess I need to follow their commits more closely! Also, while some of the appropriate code is in Chrome I guess the feature isn't officially part of the browser yet. Apparently the fact that it works at all is something of a happy fluke. So I guess that for the time being Firefox is the only browser that actually supports this!]

I put together a really simple demo this morning to show how it works, and if you've got a recent Chrome dev build or Firefox nightly you should give it a try!


Yeah, the demo is ugly but it shows off the effect nicely. For those of you not familiar with the concept, Anisotropic Filtering is an extension of standard mip-mapping techniques that improves the quality of textures when viewed at an angle. A good example of this is the floor and ceiling of the demo above. With standard trilinear filtering (gl.LINEAR_MIPMAP_LINEAR) as the floor gets further away from you it becomes blurry pretty quickly:


By using anisotropic filtering, we alter the way that the mipmaps are queried in scenarios like this one, which can give a much crisper, cleaner image:

There is a performance penalty associated with enabling this, and when you do enable it you can specify how many samples are taken for a performance/quality tradeoff. This has become a pretty common setting available for the user to toggle in PC games, and so it's great that we're now able to take advantage of it on the web too!

Implementation

Turning this feature on is pretty simple in a supported browser. As with compressed textures the first thing we do is query the appropriate extension to see if it's available:

var ext = gl.getExtension("MOZ_EXT_texture_filter_anisotropic");

Obviously with Chrome you would query with WEBKIT_ instead of MOZ_, and eventually the prefix should go away entirely. If it returns null the extension is not supported and we move on, doomed to a life of blurry walls. If it is supported, however, it will return an object containing the required enumerations for the extension.

Since this is a filter mode, we enable per-texture just like we do bi/trilinear filtering or texture wrap modes, but with symbols from the newly queried extension:

gl.texParameterf(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY_EXT, 4);

Here we're enabling 4x filtering (the value used by the demo) on the bound texture. Setting it to 1 effectively turns off this filtering, and your graphics card determines how high you can set it. You can query the maximum supported value like so:

var max_anisotropy = gl.getParameter(ext.MAX_TEXTURE_MAX_ANISOTROPY_EXT);

This particular API seems a little bugged right now, as I was only able to get it to return 0, but I expect that will be ironed out soon.

So, like I said, a simple API but a great one for bumping up your rendering quality!

10 comments:

  1. Firefox got it first: https://bugzilla.mozilla.org/show_bug.cgi?id=728354

    Just use MOZ_EXT_texture_filter_anisotropic !

    ReplyDelete
    Replies
    1. I am already testing for MOZ_EXT_texture_filter_anisotropic, and it looks like it's working in the nightlies! Cool! I had tested it earlier this morning but apparently my build was a bit out of date.

      Props to the Firefox team!

      Delete
  2. I haven't finished implementing it yet - it probably shouldn't be working at all in Chrome - I'm surprised :P

    ReplyDelete
    Replies
    1. With the exception of querying MAX_TEXTURE_MAX_ANISOTROPY_EXT (bug), it is definitively working. I even had it turned on in my WebGL Camp Orlando demos.

      Delete
  3. Don't forget to also correct...
    "Obviously once Firefox has this feature"

    You know, since it had it first and all ;)

    ReplyDelete
  4. Post has been updated to rightfully reflect Firefox's "We had it first" status. :)

    ReplyDelete
    Replies
    1. Actually it's a little more complicated than that. I wrote the extension spec for it and got it pushed trough and then Benoit wrote me a ticket in firefox for it, which I implemented as a patch to firefox. We announced it on the mailing list, along with the fact that angle needs an update, which got the interest of some webkit devs obviously.

      It's not so much of a "we had it first" but a "we got it moving at all".

      Delete
    2. Well, regardless of who started what when, you ALL have my thanks for pushing these things forward.

      Delete
  5. This comment has been removed by the author.

    ReplyDelete
  6. Does WebGL support Blend Equation Extensions ?

    I would like to use the WebGL equivalent of the openGL command, glBlendEquationEXT(GL_MAX_EXT)

    Is there any workaround. I would like to have a solution for my problem in the following link.

    http://stackoverflow.com/questions/11839993/how-to-do-maximum-intensity-projection-mip-in-webgl

    ReplyDelete