Monthly Archives: May 2011

What’s New in Jax – v0.0.0.8

I just pushed Jax v0.0.0.8 to RubyGems, so now I’ll take a moment and elaborate on what’s inside.

In terms of app-breaking stuff, there was only one change that you need to be aware of, and only if you’re using the “classic” Perlin noise functions that ship with Jax. The function “noise()” has been renamed to “cnoise()”. Simplex noise was not affected.

Now on to the good stuff. After pushing the ‘meadow’ demo, which uses vertex texture lookups, I found that vertex texture lookups are not supported on Windows at this time. In the meantime, there’s a GitHub repository that implements all flavors of Perlin noise without relying on texture lookups! And it’s licensed under MIT, to boot. Woot!

I did some quick, unprofessional benchmarks (I watched the recently-implemented framerate on my MacBook Pro) to confirm that the library is, indeed, considerably slower than the texture-lookup version. My framerate dropped from about 100 down to 50-60. Ouch. Since it’s slower, and not just by a few frames, I didn’t want to lose the texture lookups for those who could use them. I did, however, want the demo (and the functions!) to run for those who couldn’t.

The answer was to improve the shader preprocessor a bit, and take advantage of those improvements for Perlin noise. The result is Jax v0.0.0.8, now available. Here it is, in bullet form:

  • Added Jax.Shaders.max_vertex_textures to make accessible the number of vertex textures supported by the client.
  • Exposed a new local variable to the Embedded JavaScript used in shaders (the .ejs files) called shader_type. This is a string equal to either ‘vertex’ or ‘fragment’, and is particularly useful when you’re defining reusable function libraries where you don’t necessarily know which type of shader you’re in.
  • Jax built-in Perlin noise functions now silently fall back to the non-textured version if they are used within a vertex shader and VTL is not supported by the hardware. In all other cases, the texture lookup version is used for the speed benefit.

That’s it. Not a huge release, but a release with huge implications. As far as I know, the noise functions now run properly on all machines that run WebGL itself properly.

The best part about it is that when VTL support makes it to Windows, programs using Jax noise should automatically get a performance increase — just “because”.

(Note: about 20% of clients will continue to not support VTL even after this change goes through; those machines won’t get an automatic performance increase, but they will run Jax noise-based applications without issue. So that’s a pretty cool fringe benefit.)

What’s New in Jax – v0.0.0.7

Since the first version, I’ve been iterating my way through Jax prereleases like there’s no tomorrow! I’ve been going so fast, in fact, that I’ve unfortunately not taken the time to post updates to say what’s actually in them.

So here they are: a list all of the noteworthy updates I’ve made in preparation for the first official release. I won’t bother mentioning all of the bugfixes and minor changes, because that would take up way too much space.

  • Custom shaders. Support for adding your own shaders to an application was added in v0.0.0.2, and they’ve been steadily improving since then. I’ve already covered how to use them in some detail and am currently working on comprehensive documentation.
  • Incremental failoff for shaders. As of v0.0.0.2, Jax is smart enough to detect when a given client is incapable of handling the graphics options you’ve requested, and to make an intelligent decision as to which effects to omit. First it tries to see if there’s anything blatantly impossible to run on the given hardware, and if not (or if it’s already omitted those effects), Jax will remove the last effect in a given effect list until the material itself works. Because the “basic” shader (that is, per-vertex color and nothing else) is guaranteed to run on WebGL-compatible hardware, your app is guaranteed to run on all hardware, even if they don’t have the processing power to run it full-blast.
  • The role of helpers has been solidly defined. Another thing that was added into v0.0.0.2, helpers can be used to make the application at large far DRYer.
  • New generators: the scaffold generator was added in v0.0.0.2, and the material generator was modified to accept the –append option to avoid overwriting existing materials. Both of these generators are extremely helpful.
  • Special handling was added for non-power-of-two (NPoT) textures. WebGL supports these types of textures under very specific circumstances. I wanted Jax to attempt to handle these textures automatically, and instead of simply scaling them up to power-of-two (which technically works, but is kind of flaky across browsers and takes additional processing overhead), I instead altered Jax to assume the specific circumstances that allow NPoT textures to be used natively. This includes switching to GL_LINEAR filters, GL_CLAMP_TO_EDGE wrapping techniques, etc. As long as all the right options are selected (which Jax now assumes automatically), the NPoT texture can be used without issue.
  • Added the Jax license, which is the MIT license. Basically, you can pretty much do anything you want to Jax — including redistribute it, modify it, or even sell it if you think you can find someone who’ll pay for free software.
  • All of the default shaders are now built directly within your application instead of being compiled into the main Jax JavaScript file. This makes the main Jax file smaller, and more importantly, it allows you to override any of them in your application by simply creating a shader with the same name. When you override the shader, it’s totally gone, so the source code for it isn’t cluttering up any of your sources.
  • Jax now checks automatically for version mismatches. One of the unfortunate facts of life is that because Jax spans both Ruby and JavaScript code, both code bases have to be kept in sync. Your Jax applications contain a copy of the Jax JavaScript code, so when you upgrade your Jax RubyGem, your application is in fact still using the old JavaScript base. Beginning in v0.0.0.5, Jax will now warn you whenever your application is loaded with a JavaScript version that doesn’t match the RubyGem version. The warning includes the command you need to run to get them back in sync — which is a pretty simple command:
    $ rake jax:update
  • Jax now sports built-in Perlin noise functions. None of the built-in shaders use it (yet), but you can easily include it into your own shaders:
    //= require "functions/noise"

    Detailed documentation for exactly how to use the noise is still in the works, but it’s not difficult. For now, see the example application for a demonstration.

  • In addition to tons of documentation and bugfixes, v0.0.0.6 included support for “picking”. Picking is a technique that involves you giving Jax an X/Y pixel coordinate. Jax will then render the scene to an off-screen buffer, read back the pixel in question (“pick” it), and then return the object that was rendered at that location (if any). This is exceedingly useful for linking mouse clicks with objects. It’s less accurate than unprojection (it only returns the entire object, not the exact 3D point), but because it’s hardware accelerated, picking is much faster than unprojection, which is done entirely in JavaScript on the CPU.
    • Jax also supports picking an entire region of pixels in the shape of a rectangle; all objects rendered in the region will be returned.
  • Also added in v0.0.0.6 were framerate and update-rate calculations. By default, Jax won’t waste the resources to figure these out, but if you request them, Jax will automatically start calculating them. You can programmatically disable calculating them when you’re finished.
    • The default spec layout was modified to include a hyperlink to activate FPS and UPS calculations. This will affect new applications, but not applications generated prior to v0.0.0.6.
  • Finally, v0.0.0.7 brings us current with a single fairly major bugfix. It turns out that when Jax was packaging files for use in production, it was packaging the helpers in the wrong order, breaking the entire application. I figured this was a major-enough fix to warrant its own, immediate, release. This was the only change between 0.0.0.6 and 0.0.0.7.

…and there you have it. In addition to the mountain of documentation and the plethora of bugfixes, I’ve been able to implement some quite noteworthy feature additions that I believe really bring Jax to the forefront of WebGL application development — again!

I’ll do my best to put out a blog post upon every release going forward so that you’re not left in the dark again. On the other hand, you could always check the changelog — but where’s the fun in that?

Writing Custom Shaders

Shaders are extremely powerful, but that doesn’t help much if you don’t know how to use them. To that end, I’m in the process of writing a comprehensive Guide to Shaders in Jax. Unfortunately, it’s not ready yet.

The fact is, I’m currently running in about a hundred different directions trying to wrap Jax up for its first official release (so far, they’ve all been beta-quality prereleases at best). In addition to the guides, I’m trying desperately to fill in the blanks regarding API documentation. I’ve also got a couple of cool new demos half-written, and tonight I added the last major feature I expect to support with the initial release: picking.

All of these things are worthy of their own posts, and I’ll add posts for them when I have time. For now, I wanted to show you very quickly how you can add your own custom shaders to a Jax project. As with the rest of Jax, it’s really quite easy!

Like most things, it all starts with a generator. Run the following command:

$ jax generate shader custom_shader

This will generate a couple of specs, which will automatically test your shader as you write it to verify that the shader can compile, both standalone and in combination with other shaders. If you add any mandatory options to your shader, you’ll want to modify the test cases to supply those options or else they’ll start failing.

In addition, it generates the shader itself. Most Jax shaders span 5 files, and they are described below:

  • common.ejs — common code which is inserted into the top of both the vertex and fragment shaders. This is so you don’t have to repeat yourself (it keeps your code DRY). You’ll primarily specify uniforms and varyings here, though you could define functions and global variables as well.
  • fragment.ejs — the fragment shader code.
  • vertex.ejs — the vertex shader code.
  • material.js — the material file. This is the interface between Jax materials and your shader; it is responsible for setting values, validating options, etc.
  • manifest.yml — a descriptor for your shader. This is used exclusively by the Jax generators. As an experiment, after generating your shader, run the following command:
    $ jax generate material

    You’ll see your shader listed as one of the effects you can add!

You’ve got almost everything you need, now, to at least get started with your own shaders. There’s one more thing you should be aware of, however:

The Preprocessor

  • As you’ll see by just taking a glance at the files listed above, you can define any uniform, attribute or varying variable as shared. This means that no matter how many shaders and effects are in use by a material, the named variable will be shared across all of them. This makes some of the more complicated combinations of shaders possible, especially on lower end hardware, without exhausing the GPU’s hardware limitations. It’s also an important caveat, though, because if you change one shared value, you’ve changed them all! Be careful, particularly when setting shared varyings.
  • Each shader has its own main function, but when Jax combines shaders to produce interesting effects for complicated materials, these functions are aliased away. They can take 3 optional parameters in the fragment shader: ambient, diffuse and specular color. These are primarily modified by the lighting shaders, and you can produce interesting effects in combination with light sources by modifying these independently. Also experiment with placing your shader before or after the lighting effect.
  • You’ll notice that this architecture produces a lot of repetitive assignments. Luckily, the GLSL compiler is smart enough to optimize all that away so it won’t affect the speed of the program. Just thought I’d mention that so you don’t get worried.
  • Similarly to the rest of Jax, you can use the following style of comment:
    //= require "path/to/file"

    This will cause Jax to search for the specified file relative to the app/shaders directory. This is useful for importing code that you plan to use over many different shaders, such as Perlin noise (although Jax has Perlin noise built-in, now, too. More on that in the guides.)

  • All of the .ejs files are embedded JavaScript templates. That means you can use the <%= … %> syntax to evaluate JavaScript code directly within the shader source! This is most useful for getting constants such as Math.PI out of JavaScript without having to construct a corresponding GLSL constant.

That’s pretty much all I can think of for the moment; it should be enough to get you started, in any case. You can use the shader just like any other: by generating the Material you plan to use it in, and appending the shader to the material file:

$ jax generate material [my-material] [my-shader-name] --append

I’ll add tons more information, including which files you can import directly out of Jax (e.g. Perlin noise, lighting effects, etc.), to the guides just as soon as I have time. I hope this information was coherent; I’m getting pretty tired.

Have fun!

Evolution of a Feature: Helpers

Originally, Jax borrowed its concept of “helpers” from Rails in that they were meant to be supporting libraries of functions used almost exclusively within an application’s views.

As Jax has evolved, it’s become apparent that views don’t change all that often. In fact, they’re so static that most people will probably rarely, if ever, edit the views at all.

So why do we need helpers for the views? The short answer: we don’t.

I was planning to remove the helpers outright, but decided to play with the idea of using them for organizational purposes beyond just views. The result is pretty amazing, and now I’m so confident in their ability to keep an application manageable that I’ve already added how to use them to the Getting Started guide.

Helpers are easy to define and easier to use. First, in the app/helpers directory, create the helper (note that Jax actually generates this step for you, so all you have to do is add the test_method to an existing helper):

var SpiffyHelper = Jax.Helper.create({
  sayHello: function() { alert("Hi there!"); }
});

Once defined, using the helper in any Jax class is a one-liner:

var klass = Jax.Class.create({
  // ...
  helpers: function() { return [ SpiffyHelper ];
});

That’s it! A minor feature to be sure, but one that will have a significant impact on your application as you identify areas where code reuse would be a major plus.

The example I used in the Guides is where you want to handle user input similarly across all controllers; now, instead of copying and pasting (which is a Bad ThingTM), you can just stick the user input code into a helper and apply it to whichever controllers you want!

One additional note is that, if you add methods to the ApplicationHelper, Jax will automatically include this into any Jax class. So you don’t need to explicitly specify a helpers function on your classes in order to include methods that are common to all classes; just put it in the ApplicationHelper and you’re done.

Jax Prerelease Available!

Awesome news: I’ve just pushed Jax v0.0.0.1 to rubygems.com, so Jax can now be installed as simply as:

$ gem install jax

Just make sure you have Ruby on your system first.

Even more awesome, I’ve just published the first draft of the first Jax Guide! I’ve got several more to write and plenty of proofing still ahead of me, but the “Getting Started” guide should be far enough along to do just what its namesake claims and much more. It’s definitely a comprehensive tutorial that, I hope, will make a great introduction to how to use the framework.

Check out the Jax Guides at http://guides.jaxgl.com!

As a minor side note, I’d like to mention that I’ve got the main Jax website, http://jaxgl.com, temporarily redirecting to this blog because I haven’t had time to build the site yet. Too much documentation to write; this blog will have to serve some dual purposes for a time while I try to get as many guides and whatnot online as possible.

If you have any trouble understanding the guides or with Jax itself, don’t hesitate to drop me a line!

Jax Shaders Just Got Even Smarter

So, I’m still writing boat-loads of documentation, and unfortunately, I haven’t yet worked my way around to writing documentation for how to build materials in Jax. That’s kind of sad because Jax’s material management is really impressive. So much so, in fact, that I’m really looking forward to writing that part of the docs. I’m not sure how I’ll organize it yet, as there’s a lot to say, but it definitely promises to be an interesting section of the Wiki.

That said, I probably have to give you a little bit of background so you’ll understand where I’m going with all this. Here’s a sample of an average Jax Material:

# ambient component multiplied with the light source's ambient component
ambient:
  red:   1.0
  green: 1.0
  blue:  1.0
  alpha: 1.0
 
# diffuse component multiplied with the light source's diffuse component
diffuse:
  red:   1.0
  green: 1.0
  blue:  1.0
  alpha: 1.0
 
# specular component multiplied with the light source's specular component
specular:
  red:   1.0
  green: 1.0
  blue:  1.0
  alpha: 1.0
 
shininess: 30
 
layers:
  - type: Texture
    path: "/images/rock.png"
    flip_y: false
    scale: 1
 
  - type: Lighting
 
  - type: NormalMap
    path: "/images/rockNormal.png"
    flip_y: false
    scale: 1
 
  - type: ShadowMap

I love how easy to understand it is. Jax will take the above (hopefully) human-readable content and convert it into a JavaScript resource. Piece of cake.

The “layers” section is the key to this post. They’ve always been impressive; Jax uses some preprocessing magic to turn shaders into pluggable modules, and each type of shader has a corresponding subclass of Material which is responsible for setting its uniforms, attributes and whatnot. (You can even add your own, though I haven’t written a spiffy generator for automating that yet!)

I don’t know if anybody else uses this technique to manage material layers, and I don’t know what anybody else would call the paradigm. I call this a “shader chain”, with each layer acting as a single element in the chain.

I think this is pretty cool, to be honest, because it means that Jax materials can mix and match layers in any order, and each element in a chain could technically be used as its own standalone material, if you so wished. So it’s quite versatile.

And today, it got even more powerful.

I just committed some code to make shader chains smart enough to incrementally back off on individual elements if they appear to be stretching the limits of the client’s graphics processor. So, in the above example, if it is determined that color (which all Materials implicitly support), texture, lighting support, normal maps and shadow maps are just too much for the client to handle, Jax will now automatically back off on layers until it comes up with a result that the GPU can handle. In the above case, it would start with removing the shadow maps. If that’s still not enough, the normal map would be dropped. Failing that, lighting support would be disabled. Finally, if, God forbid, the GPU is just too weak, texturing support would be removed. The only thing left in this worst-case scenario is the core shader, which provides basic per-vertex color support. The core shader is virtually guaranteed to work with all graphics hardware that complies with the WebGL standard, but if for some reason the driver doesn’t follow the standard, and the core shader can’t be used, a fatal error will be raised because there’s no shader left to draw with.

Every time Jax drops an element from the shader chain, a warning is logged to the console. If no console exists, (which is the case in Firefox if you don’t have the Web Console activated), then it is reported in the form of a non-program-halting error (via #setTimeout).

Once an element is dropped from the shader chain, it is dropped permanently unless you programmatically re-add it. Since the determination is made based on the number of uniforms, attributes and varying variables used by the shader vs. how many of each is supported by the GPU, this adaptation phase only has to happen once — because most graphics cards don’t dynamically alter their internal hardware, as far as I know.

Here’s another thing you might want to note: you can easily control which elements will be dropped! As I hopefully implied above, Jax will always drop the last element in the chain. So if you have a scene where you have determined shadow mapping to be more important than normal mapping, simply swap their positions so that normal mapping appears after shadow mapping. That way, if Jax dynamically backs off, it’ll drop normal mapping and hopefully the client will still handle shadow mapping without issue. Job done!

But wait! There’s more! Before popping the last element from the chain, Jax first checks all of the other shaders to see if any of them are simply not going to work. If, for instance, the Lighting shader is using so many uniforms and attributes that the graphics card will never be able to handle it, then Jax simply removes Lighting and tries again. It’ll only pop elements from the end of the array if there are no more obvious candidates for removal.

Realistically, we all hope this is a feature that won’t ever be required (because we’d all prefer our customers to have the best possible experience, no?) — but it’s always there for you, just in case.

WebGL Apps Crashing on Windows 7

So, this is interesting. I got a tweet today saying that, basically, nothing’s working. Rock on. After some research, I narrowed down the failures to Windows 7. Which is a really good thing, actually, because I just got my Windows 7 laptop today. Until now, I’ve done all my work on Jax exclusively between Mac and Ubuntu, with a bit of Windows XP mixed in around the edges. So it was good to finally have a platform on which to reproduce the issue at will.

I quickly determined that the issue was caused by some of the code in my shaders. Which makes sense, since the JavaScript portion is pretty much platform independent except for the occasional browser compatibility layer. I debugged the shaders the same way I always do. Without any way to get particularly useful feedback from the GPU, I’d compile some code and see if it failed. If it failed, I’d remove some of the code I suspected could have caused the error, and try again. Back and forth.

I continued this game of virtual battleship until I was able to narrow the problem down to the lighting functions. I’m pretty sure, now, that this problem exists in all of the lighting functions, but for simplicity’s sake, I’m only debugging one of them, and leaving the rest commented out. The simplest function was the one in charge of attenuation calculations, so that’s what I started with. Check it out:

float calcAttenuation(in vec3 ecPosition3, out vec3 lightDirection) {
  lightDirection = vec3(ivMatrix * vec4(LIGHT.position, 1.0)) - ecPosition3;
  float d = length(lightDirection);
  return 1.0 / (LIGHT.constant_attenuation + LIGHT.linear_attenuation * d + LIGHT.quadratic_attenuation * d * d);
}

The LIGHT variable is actually of type LightSource, a structure I made to hold all my user-defined lighting variables. Those variables, in turn, are specified as uniforms.

And this is the problem. For whatever reason, any reference whatsoever to the LIGHT variable from within a function body is crashing on Windows 7. Even if all I do is immediately return LIGHT.constant_attenuation, the program still refuses to compile. Even if I try to pass the light source in as a const in LightSource argument, it’s no good. I’ve never had a problem with this on Ubuntu or Mac.

As much as I’d love to just say, “Well, that’s why you shouldn’t use Windows…” — I won’t. I’ll grit my teeth and fix the issue, somehow. But don’t assume I’m not thinking it.

As for the fix, I suppose I’ll attempt to pass the uniform variables in directly rather than using a structure for pretty-ness. Failing that, I’ll forgo using functions at all and just in-line all the source code. Ugly, but it should work. Since Jax supports rendering partial templates, I can probably pull off something very similar to my functions without using functions, per se — which might even result in a faster (but larger) shader program. Worst case, I’ll just have a lot of repetitive code until this Windows 7 thing gets fixed.

Regardless, I’ll update this post with a verdict as soon as I have one.

UPDATE: Looks like I can remove the LightSource structure, instead just using each variable explicitly, (e.g. swap LIGHT.constant_attenuation for uniform float LIGHT_ATTENUATION_CONSTANT), and the issue goes away. It’s uglier, but probably the easiest and most painless way to solve this problem. Shouldn’t take long to implement, either.

UPDATE 2: Yeah, that solved it — but woah, shader functions are super-touchy on Win7! Another note is, don’t pass temporary variables as function arguments. In other words, don’t do this:

1
funcall(vec2(0.0, 0.0));

Instead, do it the verbose way:

1
2
vec2 myvec = vec2(0.0, 0.0);
funcall(myvec);

Heads up!

Jax is headed your way. Soon. I’m probably within a few weeks, at most, from the first release. I’m going to spend that time trying to cram a few more features into the framework and fleshing out as much of what’s already in there as possible.

This blog is where I’ll talk about major developments going forward. If something changes, this is where you’ll find out about it. If I’m working on adding a cool new feature, this is where I’ll do my bragging.

This isn’t where you’ll find live demos. At least, not at this time. I’ll post prerecorded videos and whatnot, but if you want the live stuff, you’ll have to head over to the Jax Demos Page.

It’s also not where you’ll find documentation. That’s being hosted over at the Wiki. You should check that out, though. It’s quite a treasure trove of information — or at least, it will be, when Jax is officially released.

So, what are we looking at supporting in the first version of Jax? All of the following is in place today:

  • Support for multiple simultaneous WebGL contexts
  • Flexible, extensible and customizable shaders
  • Lighting support for directional, point and spot lights
  • Shadowing support via shadow maps
  • Flexible 3D model construction
  • Texturing and normal mapping (DOT3 bump mapping) support
  • Automatic cross-browser capturing of keyboard and mouse events — just define a function!
  • WebGL Context initialization in as little as 1 line of JavaScript code
  • MVC architecture segregates rendering, business logic, and scene setup/teardown for better organization and, therefore, code base maintainability
  • Raw data is stored in plain human-readable files and converted to JavaScript automatically
  • Application generator sets up the Jax application skeleton for you
  • Controller and model generators remove the need to copy-and-paste files
  • Unit test files are automatically generated and integrated into the dev environment — just start writing tests!
  • Material generators take the guesswork out of 3D models
  • Light source generators remove the need to programatically build scene lighting
  • Static assets are mirrored in development, so you know your dependencies will work upon deployment
  • Special generators for packaging and bundling your Web app completely automate the task of bow-tying
  • Test server is included, so you can get started with nothing but a text editor
  • “…And so much more!”

As you can see, Jax ain’t your average framework. It’s way more than a simple JavaScript library. It’s an entire suite of development tools designed to get you from zero to production in as rapid a process as possible. It’s been nearly 6 months in the making, (so far), and that’s with yours truly coding into the wee hours of the morning and on most weekends. I’ve put a lot of work into this, and it’s all about to pay off. We’re almost there.