Sunday, December 2, 2012

I will not be playing your game today

I've always considered myself to be a gamer. I've been fascinated with video games since I was very young and the NES was hot stuff. I would never think to describe myself as a "casual" gamer: I can still headshot you from half way across the map in Team Fortress 2 with ease. I've beaten multiple Final Fantasies, and will fervently argue that VI is the best in the series. I still chuckle if I ever hear someone say "Would you kindly...". I've always wanted to build games, which is why I started teaching myself graphics development in Junior High. Gaming has long been an important part of my life, and is a big part of why I'm in the career I am today. In every sense of the word I am a Gamer with a capitol 'G'!

Except, um... I've been playing a lot more Angry Birds and Cut the Rope lately than Dishonored or Borderlands. Actually, that's pretty much all I've been playing. I feel vaguely guilty about that: it's hard to claim that you're a "hardcore" gamer with a straight face when most of your gaming time is spent slicing fruit instead of shooting aliens. But, at least I've a good excuse! His name is James:


Yes, I've added "Daddy" to my resume. And, for those of you who have kids I don't need to explain that, especially at this age (2 Months) it's a full-time job.

Tuesday, October 2, 2012

OES_vertex_array_object extension

(Update: Demo should work on Windows now too with the latest Canary builds)

So believe it or not, since joining Google I've been doing more than just lounging around and enjoying the free food. This week my first feature landed in the Chrome source, which means it should be coming to a canary build near you soon! And it just so happens that the feature is question is, surprise surprise, a WebGL extension! OES_vertex_array_object, to be exact.

(Giving credit where it's due: Ben Vanik did the work to expose the extension to WebKit a while back, my contribution was wiring it up to Chrome's GPU pipeline.)

As is tradition we'll start off with a demo. If you're reading this near the posting date you'll have to have a Chrome Canary or Chromium build to see this in action:


Not exactly the most graphically impressive thing in the world, is it?

Thursday, September 13, 2012

Nexus 7 impressions

I picked up a Nexus 7 last weekend, partially because I am on the Chrome team now and want to contribute to the Android version, and partially because I really wanted an Android device to play with again. :) I've been using it pretty consistently over the last week and felt like it would be a good time to share my first impressions.

Sunday, September 2, 2012

New job and glMatrix 2.0

A bit of a life update here, for those that don't follow my Twitter feed there's a couple of things worth bringing up:

First up, I've left Motorola after the project I was working on was shut down. I'm sad to be leaving a truly great team, but when one door closes another blah blah... So now I'm a Google employee! I've joined the Chrome GPU team, and will working on the WebGL implementation! I officially started on August 27th, so this was my first week. Yes, that makes me a Noogler. :)

Thus far my experience has been that Google is a ridiculously awesome and just a tad bit overwhelming at first. There is a LOT to learn, both in terms of culture and code. Did you know that the Chrome code base is (to use a technical term) frikin' huge? It also take a long time to check out and a really long time to build.  That's going to take some getting used to after all my dallying in insta-refresh web development land.

Speaking of web development, with my new job what's going to happen with my WebGL hobby code? Hopefully not much, although I'll admit that it'll probably slow down a bit while I focus getting up to speed at the job that actually pays me. :) In any case, I will still be doing personal code, but "Building the Game" is taking another break. (Not that I was being terribly speedy with my updates anyway...)

There is at least one project that I'm actively working on, however: I've started on glMatrix 2.0. It's primarily an application of all the bits of feedback that have been given about the original library, along with an effort to clean up and standardize the API based on real-world use patterns that I've seen. It's still a work in progress at the moment, so anyone is welcome to chime in on the code that's been written thus far. I'm not sure when it'll be officially released, but I'm hoping sometime in the next couple of months.

So that's my little catch-up post! Till next time!
 

Friday, August 10, 2012

More GPU Tile map demos (Zelda)

I published these on Twitter and Google+ a little over a week ago, but felt they were worth posting on the blog as well!

So if you recall from my previous post I mentioned that the tile map technique allowed for really REALLY big maps. How big, exactly?

How about big enough to store the entire NES Legend of Zelda overworld...
and all of the dungeons...
and the second quest overworld...
and all of it's dungeons...
all in a single massive map!


Monday, July 30, 2012

Sprite tile maps on the GPU

I had a fun idea yesterday while playing (what else) Spelunky and decided I'd give it a go. The result is this demo, which I'm reasonably proud of despite it's simplicity.

I know it doesn't look all that impressive, after all the SNES was doing that kind of stuff a long way back and they didn't need any fancy WebGL to do it. Heck, even a rudimentary HTML Canvas renderer can get similar results, so what makes this so special?

Well, what if I told you the entire thing was done on the GPU by drawing a full-screen quad? Interest piqued?

Friday, July 27, 2012

The WebGL Guide to reading OpenGL shaders, Part 1

When discussing graphical techniques in WebGL, it's not uncommon to hear people say "Here's some shader code from an OpenGL desktop app! Use that!" And for the most part that's an entirely reasonable thing to say. Typically it's only when you start looking at OpenGL 3+ (DirectX 10+) level hardware and applications do we run into things that are simply out of reach of WebGL as it stands today.

There are, however, some oddities from the desktop relm that have (wisely) been excised from OpenGL ES 2.0, OpenGL 3.1+, and WebGL. These can make a simple "Oh just use this legacy shader" recommendation an exercise in frustration for someone who isn't intimately familiar with OpenGL 2.0 development on the desktop. If that sounds like you, then this is your guide!

Sunday, July 8, 2012

Using WEBGL_depth_texture

Gregg Tavares mentioned on the WebGL mailing list recently that the WEBGL_depth_texture extension was available in Chrome Canary, but I've yet to see anyone talking about how to use it so I figured I'd throw together a quick demo via one of the most popular uses for depth textures: Shadow mapping!

Saturday, June 30, 2012

WebGL Quake 3: 2 years later

Got a great question in the comments on my Quake 3 Tech Talk post today from Daniel P.
It's been almost 2 years since you did this. My question is: how much could you improve the rendering with your knowledge today?
Indeed, both WebGL and myself have improved since I initially did the Quake 3 demo, so it's interesting to look back and see what could be done better today given more expertise with WebGL and the evolution of the API.

Thursday, June 28, 2012

Building the Game: Part 6 - Isosurface Landscapes

See the code for this post, or all posts in this series.
See the live editor demo.

Well, it's been a long time coming, but I'm finally back with another official installment in the Building the Game Series! As mentioned previously I'm want to take the series in a different direction now, and as such this post represents a bit of backtracking from the previous one but I'm hoping that it will be a more productive direction in the end.

Wednesday, June 13, 2012

Building the Game: Part 5.5 - Two steps forward, one step back

So this isn't really one of the "main" posts in the Building the Game series, but I feel it's important to bridge the gap between the last post and the upcoming one, since there's been a significant gap between them and the project's direction is going to change in some important ways. I've already hinted at some of the reasons why the series stalled out, but I want to go into some more detail about it now to give context to some of the decisions I've made.

The big issue that I ran into when trying to build on the last post was visibility culling. As you may have noticed, the live demo of the previous post wasn't exactly speedy, and that's because it was trying to render every piece of a very large scene every frame. The obvious next step is to introduce a visibility testing system that can quickly inform you of what meshes are potentially visible from a given point in the world. This isn't a new concept, and it's one that I've worked with before. Quake 3 and the Source engine both use a pretty straightforward PVS (potentially visible set) system, and I was expecting that Unity would expose similar information through it's APIs.

Unfortunately, it doesn't.

Sunday, April 29, 2012

WebGL Texture Utils and Building Require.js libs

Two things to go over today:

One, I've got a new library out. WebGL Texture Utils. It's, as you might imagine, a collection of utilities to assist with loading WebGL textures of several different forms. Actually the repo for it has been available for a little bit now, but it's only today that I feel things have actually gotten to the point where it's really useful.

Thursday, April 5, 2012

If I built a physics engine...

So let's be clear about something right from the very start: I'm not a physics guy. I love me a good physics engine, but I will likely never build one because that's just not where my expertise lies. Far be it from me to criticize the algorithms used by your broadphase collision pass, because I only have the most high level of ideas what that actually is. I'm a graphics guy through and through and that's where I'm happy to stay.

However, I do know a thing or two about writing fast Javascript code, which is something that will become fairly important to the new breed of browser-oriented physics engines that are starting to crop up, like Ammo.js, Cannon.js, and the various Box2D ports. Unfortunately, however, I've seen a few common threads within these engines that I think will limit their effectiveness in real-world use, and I wanted to get some of it off my chest while the development of these libraries is still in the early days. Some of these trends are inherited from the underlying C++ libs these libraries wrap (like Ammo.js, which is built from Bullet with Emscripten), but others appear to be self imposed. That's the group I'm talking to.

Friday, March 23, 2012

Javascript memory optimization and texture loading

Over the past couple of weeks I've seen a few great resources about optimizing your javascript. One is a wonderful GCD presentation by Lilli Thompson about best practices when writing code for V8 (Chrome's Javascript engine.) Although the presentation uses Chrome for it's concrete examples, much of the information is very practical for any browser.

GDC 2012: From Console to Chrome

It's a long presentation, but well worth the time. If you simply can't bring yourself to sit and listen for a bit, though, at the very least take a look through her slide deck.

The second resource is a great blog post by Ashley Gullen of Scirra about reducing the amount of time your app spends in that dreaded garbage collecting coma.

How to write low garbage real-time Javascript

I highly encourage you to go through both of those if you are a web developer. Even as an expert dev with years of experience, I'm sure you'll learn something!

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!

Friday, February 17, 2012

The Gamepad API and the case of the shifting buttons

Took the opportunity to look at the Gamepad API for the first time yesterday while at the Mozilla Games Work Week. It's a simple API at it's core, and one that should be very straightforward to use. I gave a stab at it by sneaking gamepad controls into my Quake 3 demo (Have you noticed that tends to be the testbed for all my API fiddlings?) and am semi-pleased with the result. If you plug in most controllers (Xbox, PS3, etc) you should get at least be able to move with one stick and look with the other, though depending on the OS/gamepad/browser some things may not work quite as expected.

And that brings me to my grip with the Gamepad API as it exists now. It IS OS/gamepad/browser specific. My current code looks roughly like this:

for (var i = 0; i < navigator.gamepads.length; ++i) {
    var pad = navigator.gamepads[i];
    if(pad) {
        walk(pad.axes[0], pad.axes[1]);
        look(pad.axes[2], pad.axes[3]);
            
        if(pad.buttons[0]) { playerMover.jump(); }
    }
}

The basic idea here is that we loop over all the available gamepads and when we find one pull from axis 0 and 1 (hopefully left stick on your basic 360/PS3 style pad) for movement, axis 2 and 3 (right stick?) for looking around, and button 0 (???) to jump.

That's the theory, anyway. Here's what actually happens: In Chrome on my Mac the DirectInput gamepad I have returns the sticks as axis 0/1 for the left stick and 2/5 for the right. This means that looking up and down is broken. With my Gamepad-enabled Firefox build, though, the axes are actually 0/1 and 2/3. If you use the PS3 controller, the axes match up to what you would expect on both browsers, so that's nice, but the button mapping is COMPLETELY different between browsers. Firefox considers the "X" button to be button 0, while Chrome things button 0 is D-Pad up. (Firefox thinks the D-Pad is an axis, actually.) So if you're going to use gamepads on your page, um... you're kinda screwed. It's like if typing a "W" on one browser gave you a "W" and on another it gave you a "U". Madness!

There are projects out there already that try to normalize this situation. Gamepad.js and input.js are the big ones right now. Both do some checking against the browser/os/gamepad model and map them into a more sensible gamepad structure that looks a lot like XInput. (That's a good thing, by the way!) The biggest problem with these libraries is that if the library author hasn't gotten their hands on your exact controller you're out of luck. Also if you have a controller that happens to not look at home on a modern console, like an actual joystick, these libraries will do nothing for you.

I'm not trying to be down on the gamepad abstraction libs, because I actually think they're great and would encourage people to use them. What I feel is problematic is that the browsers aren't returning consistent data for the same device. If we could remove the question of OS and Browser from the equation and just focus on the device that's connected developers would be able to cope with the vast array of input devices out there with the minimal amount of pain required by dealing with such a varied field. If things stay the way they are now, we can still get everything to work, eventually, but we'll be working three times as hard for it.

So please, browser peoples, get everyone together on a conference call and all agree that you'll poll the hardware the same way. It will make our lives as developers much easier!

Thursday, February 9, 2012

...in which I give updates on everything

Also known as: Why I've been so lazy lately.

So I know that theres more than a couple of you out there that have been very patiently awaiting the next post in my Building the Game series for the last couple of months. It's probably been a little frustrating to have the first 6 posts come out fairly quickly and then just abruptly cut off. For that I apologize.

The reality is that I've been buys with plenty of other, non-blog-related things lately and simply haven't been able to spend the time working on it. During the holidays I made a conscious decision to focus on family rather than code, and immediately after that I've been pretty swamped with a project from work (you know, the guys that actually pay me!) that has left me with little desire to do even more code when I get home. On top of that, I quickly realized that the where I wanted to take the bog series next would require some research into areas that I've never really poked into before (generating visible sets and such) and it's been difficult to find the time and resources to really dig into it.

In other words, I've been feeling a little burnt out. I think all programmers go through this from time to time, and I'm simply allowing myself to recover and gain back some of that all important enthusiasm.

Don't fret, this isn't my "well that was a failed experiment" post where I leave things forever unfinished. I'm going to continue the series soon, but I think I'll be back tracking a little bit and hitting some other aspects of it first before getting back into the whole level loading thing. Better animation management and player input feels like a good place to hit next, along with some retrospective tweaks to the model formats. I don't think I can give dates on when we'll see the next post, but rest assured it will be sooner than later.

Beyond the blog, however, there's been a couple of other developments worth mentioning lately. Since the contract is now signed I think it's safe to announce that I'm currently co-authoring a WebGL book! I was asked to help Diego Cantor complete a WebGL Beginners Guide for Packt Publishing, which has proven to be no small feat. I don't know anything really about potential release dates or anything like that, but rest assured that I'll be tweeting and blogging about it once I know more.

Also, I've been invited to attend Mozilla's HTML5 Games Work Week this February. Essentially, Mozilla is reaching out to people who have been active in game-related HTML5 tech (like WebGL) and is bringing them together for a week to ask "How can we make the web an awesome game platform?" This is a goal I think we can all support!

For my part, I want to try and address several concerns from the development community that I've run into either through this blog, via email, or that I've seen talked about on various other online resources. These include:
  • Synchronizing game logic and rendering
  • Considerations for reducing power consumption of games on mobile devices
  • Content protection
  • Content delivery
  • Robust input handling
  • High-performance audio
But I'd also love to hear what the rest of the HTML5 game dev community is concerned about! I can't promise that everything that I hear about will be addressed but if I'm hearing similar concerns from multiple people you can be sure I'll do my best to bring it up.

That's about it for now. There's a couple of conferences on the horizon that I may have a chance to speak at but nothing is confirmed right now. I'll let you know if things solidify. There's also some exciting new and upcoming bits of web tech that I'm itching to play with and do some little demos for, so expect to see some quickie proof-of-concept stuff in the coming months as well. In the meantime, I'm always available for questions by email, on twitter, or through this blog, and I've made a habit of trolling StackOverflow for WebGL questions

WebGL JS1K entry

As a sort of follow up to last years Itty Bitty WebGL post I decided to take a crack at actually entering the js1k competition this time around. Since the theme of the competition is "Love" I thought it would be fitting to do a minimalistic version of this awesome little "beating heart" shader.

You can see my under 1k version here.

And the not-quite-so-compressed-but-still-really-hard-to-read source code here:

c=document.getElementById('c');
c.height=300;
g=c.getContext('experimental-webgl');

b=g.createBuffer();
a=34962;
g.bindBuffer(a,b); 
g.bufferData(a,new Float32Array([0,0,2,0,0,2,0,2,2,0,2,2]),35044); 
g.vertexAttribPointer(0,2,5126,false,0,0);

p=g.createProgram();
function l(x,y){
    s=g.createShader(35633-x);
    g.shaderSource(s,y.replace(/#/g,'float ').replace(/\^/g,'vec'));
    g.compileShader(s);
    g.attachShader(p,s);
}

// See the uncompressed shader code at http://glsl.heroku.com/e#1599.2

l(0,'attribute ^2 p;void main(){gl_Position=^4(p.x-1.0,p.y-1.0,1,1);}');
l(1,'precision highp #; uniform #t;^2 r=^2(300,300);^3 h(#x,#y){#s=mod(t,1.0);s=1.0+(1.0-exp(-5.0*s)*sin(9.0*s));x*=s;y*=s;#h=abs(atan(x,y)/3.14);#d=(13.0*h-22.0*h*h+10.0*h*h*h)/(6.0-5.0*h);return mix(vec3(1.0,0,0),vec3(1.0),smoothstep(d-0.05,d,sqrt(x*x+y*y)));}void main(){^2 p=^2(-1.0+2.0*gl_FragCoord.xy/r);gl_FragColor=^4(h(p.x,p.y),1.0);}');

g.linkProgram(p);
g.useProgram(p);
g.enableVertexAttribArray(0);

u=0;
setInterval(function(){
    g.uniform1f(g.getUniformLocation(p,'t'),u+=0.02);
    g.drawArrays(4,0,6);
},16);

To be perfectly honest, I really don't care to explain the details of what's going on here. The basic setup is the same as my previous post on the subject, with the core difference being that we're now rendering a fullscreen quad. (That effectively makes this a tiny version of mr doobs GLSL Sandbox) The shader code is really just a minimal implementation of the original shader, and the only really interesting trick there is that I'm doing a string replace to simplify commonly repeated symbols like "float" and "vec".

I'm not certain that this even qualifies for the contest (since WebGL isn't enabled by default on some of the required browsers) but I had fun doing it and it was a good break from everything else going on in my life right now. (I'll be posting more on THAT shortly.)

OVERNIGHT UPDATE: So apparently I missed the line on the rules page that actually excludes WebGL from the competition (Second to last bullet under "Other things you should know"). That's a shame, but hopefully WebGL will be allowed for the next round! Doesn't matter much to me, I was just doing it for kicks anyway.

In other news, @p01 managed to cull 303 bytes out of my demo while I was sleeping which I think is deserving of a "I'm not worthy!" bow. There's some seriously clever little tricks in his version that I'm most certainly going to have to utilize the next time I try one of these! :)