It’s no secret that I like graphics. It’s the main reason why I play video games and it’s the main reason I got into programming. So obviously I was delighted to be invited and to join to the Away3D team last month. Inspired by my earlier Stok3d project (now on the backburner for a bit), I set off to create similar normal mapped pixel shaders, this time in full 3D. After some rough first patches (Stok3d was pretty simple since it only used DisplayObjects, flat planes), things have luckily shaped up, leading up to the first release!
The current state is a dot-release (3.4.2), so the exact implementation might still change while we’re working towards a shiny new 3.5.
So what is the difference with the previous shaders? Using Pixel Bender, the shading is calculated for every pixel in the texture, resulting in much more detailed and realistic lighting or reflections. Each shader requires an object-space normal map, which you can use to add detailed shading information without increasing the polycount of the mesh.
The shaders come in three flavors: environment map shaders, and single- and multi-pass shaders. Single-pass shaders take one PointLight3D and any AmbientLight3D on the scene to calculate the lighting, whereas multi-pass takes any number of lights of any type (AmbientLight3D, DirectionalLight3D, and AmbientLight3D). Important to note, tho, is that every light adds another pass and will be slower. Of course, if you’re only using 1 light, always use single pass.
Check out the following classes in Google Code:
- SphericEnvMapPBMaterial: spheric environment mapping
- Cubic EnvMapPBMaterial: cubic environment mapping
- DiffusePBMaterial: Single-pass, adds diffuse lighting to the texture
- PhongPBMaterial: Single-pass, adds diffuse lighting and specular highlights, with support for specular maps
- SpecularPBMaterial: Single-pass, adds only highlights – can be used in combination with Prefab3D’s prebaked lighting to create view-dependent specular highlights
- DiffuseMultiPassMaterial: Diffuse shading with multiple light sources
- PhongMultiPassMaterial: Phong shading with multiple light sources
Enough explanations, time for some demos! Right-click to view source:
- Cubic environment mapping
- Single pass shading: showing how a detailed normal map and specular map can enrich the shading
- Multi pass shading: using 3 lights (directional moonlight, firefly, and a flickering flame) and ambient
That’s it, enjoy! Feel free to drop by the mailing list for questions or read the official announcement! For now, I need to get some sleep before Flash on the Beach kicks off



Since I started playing around with Pixel Bender in Flash, I’ve been trying out some different approaches here and there and learned a thing or two on performance optimizations (and quirks). As many people use PB specifically for its performance, and not much has been written on the subject, I thought I’d share my experiences and back them up with some benchmarks. Some of the things here are pretty obvious, yet others can be surprising and even frustrating.

When using view-aligned slices, they typically won’t be aligned to the texture’s slices, as illustrated in the image to the right (yes, my graphic skills are EPIC!). The point p is any point on any view-aligned slice. We need to know where it is in the texture’s 3D space. This is simply a change of basis transformation, where both bases are defined to have the same origin. In our specific case, eye space is world space, so all we have to do is multiply p with the inverse of the object’s delta transformation matrix. Since the result will usually lie between 2 slices of the 3D texture (as in the illustration), we sample both texture slices with constant x and y coordinates and interpolate the colour values. This approach is not 100% correct, since the interpolation should also be aligned to the view. However, for this purpose, it’s a good trade-off for some extra performance.



When changing the surface position, scale or rotation, be sure to call the update method and reassign the filter to the target DisplayObject. All this is shown in the 




