Wednesday, April 13, 2011

WebGL Starter Package

[Edit: Now with 100% less jQuery dependency!]

I've had some sudden urges to jump back into WebGL land again lately, and while gearing up for another project it struck me how much time I was wasting trying to copy one of my older projects, strip out all the project-specific stuff, and get down to a really basic starting point.

Realistically, that starting point is one of the hardest hurdles to jump for any graphically-based program, doubly so for 3D programs. There's just so very many silly little things that might go wrong!

  • Is the context and viewport set up properly?
  • Is your shader compiling?
  • Are your vertices right?
  • Are your indicies right?
  • Are your matrices right?
  • Did you give the right strides and sizes to your vertex layout? 
  • Is your geometry rendering in front of the "camera"?
  • Is it rendering in a color other than the background color?
  • Are you certifiably insane yet?
I decided to save myself some greif and put together a quick and dirty WebGL page that I can use as a jumping-off point for future projects. The goals here were to start with something that was putting geometry on the screen and allowed me to move around the scene, nothing more. This was the result:


Like I said, very simple. Just enough geometry on screen to know that you're rendering properly and to give you a sense of space. This is certainly not meant to be the foundation of a complex demo, but it sure beats starting out with a blank page! Of course, while I built this for my own use I certainly hope that some other aspiring WebGL developer out there finds it useful, and to that end I've packaged it up in a convenient downloadable bundle:


A couple of quick notes, for those that end up using this: Most of the formats I work with are designed with Z as the "up" axis, so Y is the one that actually points "out" of the screen. I'm using requestAnimationFrame (with fallbacks to setTimeout) for the core animation loop, so hopefully that doesn't cause any issues. I'm also not setting anything like blend modes or geometry culling states, you're on your own there. The page relies on my glMatrix library (included) and also makes use of webgl-debug.js, though you can easily turn that one off.

If anyone finds this useful or uses it as the basis for their own projects I would love to hear about it! Also, if you have any suggestions on how to improve it send them my way! Happy coding!

7 comments:

  1. Hi brandon,

    I just wanted to say I'm very thankful for all the brilliant web-gl stuff you've been doing. Working with ID tech is not easy but you make it a breeze. You're a very very talented and very smart developer and people like me learn a lot from someone like you. I hope you keep up the brilliant work.

    ReplyDelete
  2. I've made some simple updates to this today: It now also has very simple texturing, since that's a pretty common part of WebGL projects. :) I also fixed the updating on the FPS counter and made the movement time based. Hopefully that helps this demo prove to be a bit more useful for people using it as a starting point.

    ReplyDelete
  3. Hi Brandon,
    Using your demo as a starting point, I try to display a pyramid, but this far I've only been able to see one of its four faces. If I use gl.LINES instead of gl.TRIANGLES, then I see only one triangle (i.e. on face).
    I'm also a bit confused by the way you mix texture coordinates into the vertArray. Can you explain how these coordinates get sorted out in the shader?

    ReplyDelete
  4. Jon,

    That's an interesting subject, and not too many people talk about it online, so I'll see if I can whip up a blog post about it. May not actually get anything posted until tomorrow though.

    ReplyDelete
  5. Very useful piece of code. One question, though.

    You appear to have two distinct onFrame()'s. Within animateWebGLSandbox(), onFrame is the third passed parameter, which in the calling location is drawFrame. So here onFrame() is effectively a synonym for drawFrame(), which does all the heavy webGL-y stuff. Inside requestAnimation(), however, there is a local function called onFrame() which does FPS-related stuff.

    Is there a reason for this name being used twice? I found it very confusing. Also, use of the name "onFrame" even once seems to me to be less than ideal, because searching for it does find it but also brings up requestAnimationFrame etcetera.

    Apart from that, though, it's all great stuff. I'll definitely be making use of it as a starting point for something. Thanks for that!

    ReplyDelete
  6. Yeah, I agree that it's a bit confusing. I've been reworking it slowly as I've been using this framework for newer projects and I think I've changed it up enough that I may release a Version 2 of my sandbox pretty soon. The code should be a bit cleaner when I do.

    ReplyDelete
  7. OK, I've just spotted one other thing that you may want to fix for version 2. You've probably spotted it yourself already, but anyway the gl.vertexAttribPointer()'s in drawFrame() are something that only need to be done the once, rather than repeatedly, so the natural place for them is in initScene() somewhere after the bindBuffer() for vertBuffer.

    I hope that helps.

    ReplyDelete