Der Schmale – David Lenaerts’s blog

Flash Platform Experiments

Marching Cubes using Pixel Bender: Metaballs / LoFi 4D Julia Set

Tags: , , , , , , , , , ,

juliasetAs promised in my previous post, I would elaborate on some of the things done for the demo. So I’m taking a quick break from work to get this post done :)

Marching Cubes

One thing I did was implement a marching cubes algorithm using Pixel Bender, which is a way to triangulate an isosurface in a scalar field. I had started to write up a whole explanation, but realized it was kinda pointless, as it has been covered plenty of times :) If you’re interested, you’re better off reading up about the subject starting here and here.

Pixel Bender

I know there’s plenty of marching cube implementations in ActionScript out there, but I haven’t seen one using Pixel Bender, so I thought I’d give it a try. I’m using it to calculate the values in the scalar field (at least on the marching cube’s grid corners), and to build the pattern ids needed for triangulation. The benefit of using Pixel Bender is that you can put in any kind of calculation that outputs scalar values, some of which you wouldn’t dare to put ActionScript through. The drawback is that it seems to have some precision problems while doing comparisons (or so it seems), so there’s some missing triangles on occasion.

No transforms, no sorting

Something I’ve realized that’s pretty neat about this algorithm is that you don’t actually need sorting. As long as you make sure the grid is aligned to the “camera” at all times, the triangulation occurs back to front and will already be correctly sorted. This of course means you can’t do any rotations on the triangles, but that’s no big deal. You can simply perform the transformation on the grid coordinates, and let the correct values be calculated for those points. Added bonus, you can do any scaling and translations together with the projection matrix in one call to Utils3D.projectVectors, annihilating the need for any calls to Matrix3D.transformVectors. Result: some extra fps.

Metaballsmetaballs

Metaballs are probably the most iconic example of isosurfaces out there (bar MRI and CT imagery). It was actually my test data for the MC system, but it ended up making a sneaky appearance in the demo (which I still consider a tribute to the undisputed king of ActionScript sticky substances ).

> Metaball demo (click to change textures)

Quaternion Julia Set

Another example I did was to triangulate a quaternion Julia set, which seems pretty popular lately ;) It definitely looks better raytraced, but I couldn’t resist! I’m using the distance estimator function to produce the grid values (see here), and an epsilon distance as the surface’s isovalue. Since things always look less crap with music, I added some for a change.

> Quaternion Julia Set Demo (might take a while to load the mp3)

Source

The marching cubes thingy, as well as the metaballs example source is up for grabs at Google Code . Enjoy! If you make any surfaces with it, I’d love to see them :)

Leave a comment (6 comments)

Assembly 2010: EvoFlash FTW!

Tags: , , , , ,

spiralOutA few months ago, Simo Santavirta (aka simppa.fi, aka jac) from EvoFlash invited me to do some effects for a demo they were planning to release at Assembly 2010. I hadn’t actually done anything for the demoscene before, but how could I say no; it’s Assembly, home of Second Reality! (and I do believe there was beer involved at some point). The category was “Real Wild”, which basically means “demos for any platform that can run real-time graphics”, including Flash. And… We ended first! Champagne for all!

Linkage

Demo building for the creatively challenged

Before I start yapping too much, first things first: Simo did >90% of the demo, just need to clarify that!

Okay, to continue… I did get confronted with some facts of life in that I am not an artistic person! With code as a starting point, it’s hard for me to come up with something that looks good. Feels like a wall in my brain that’s preventing me to go that way. Typically, I work the other way around and try to turn “looks” into code (like references from real life). With the abstract beauty of many demos, it had me cursing plenty of times. Luckily, Simo was able to adapt my pieces and make them look good, so I’m very proud of the end result! ;)

From the technical side of things, here’s what I did: normal mapping on dynamic models (procedural of course), projection+shadow mapping, and marching cubes (metaballs and, I dunno, some weird tunnely thing). The metaballs are slightly tongue in cheek, and I consider them an homage to the “metaball guy”. I’ll probably get back to some of the effects in future blog posts, so I won’t delve into any detail right now. Most of them were done using Away3D Lite, preferring it over the main engine because it’s so lightweight/fast and darn easy to hack and extend. For me, it makes an excellent playground!

The demo itself was built upon the evoTinyEngine demo framework, which made it very easy to collaborate, sync, and hook effects into the main demo.

In closing

Obviously, many thanks to Simo for giving me the opportunity to join in! Too bad I couldn’t be there in person, but there were some other things I was up to during the weekend. Time to recover ;)

Enjoy the demo!

Leave a comment (3 comments)

More Fresnel fun in Away3D: through the looking glass

Tags: , , , , , , , , , ,

glassBallAs a continuation of an earlier post, here’s a variation of the Fresnel Pixel Bender material. Still obviously inspired by Bartek’s Unity3D shader, it became a glass material with support for chromatic aberration (what causes the rainbow effect in refracted light). The result could come in handy in some situations, so I thought I’d share and commit it to the Away3D trunk as the GlassMaterial.

The material uses the same environment map to do (fake) refractions and reflections, so it’s not actually refracting the real scene around it. However, if you make a sphere map rendering of your scene, the effect can be convincing enough.

The demo shows a couple of default primitives and several settings of the material (such as glass colour and reflection strength), and also uses a new primitive called TorusKnot (which is a (p,q) torus knot). Consider that a tribute to a demo shown by Ralph during his presentation at FITC Amsterdam ;) . Click to cycle through the different settings, and check the source to see how it all works.

Update: As Makc pointed out in the comments (and rightly so), the refraction looked rather icky, so I updated it that it uses linear sampling. It’s a bit slower but looks much better.

Leave a comment (3 comments)

Fresnel reflective shading with Away3D

Tags: , , , , , , , , ,

fresnel-awayFinally, something new! But no, it’s not any of the bigger things I’ve been hinting at before. However, I’ve been hard at work at those (and other) projects for months, and ended up with tunnel vision and an annoying rut. I really needed to do something smaller again for some immediate visual fun. When Bartek showed me something on Twitter, I decided to take a step back from all the work, dig up some half-year old code and finish it asap. And so I did: that is a Fresnel Pixel Bender shader for Away3D, presented in the FresnelPBMaterial!

I’ve explained it before, but I’ll give a more general explanation this time around. Fresnel shading mimics the way light reflects off of (often translucent) surfaces such as water or glass. Looking head-on, you can see its proper surface (or see through it with refraction). However, if seen from a shallow angle, it reflects light (just imagine looking over a large body of water, or the mirage effect on the road on hot summer days).

Demos

I’ve thrown together some rather random demos to illustrate the point. There’s source for both. (A word of warning: apparently, on some FP10.1 betas, Pixel Bender causes it to throw an invalid input exception, which seems to be bogus.)

  • Glass and marble head: Yes, the head appears to be floating in the middle of a cathedral of some blurry sort. Click to cycle through different property settings: glass, alien marble (I’m sure that’s a thing), and plain marble.
  • Water surface: Using an animated normal map to illustrate how water could be rendered while using the fake refraction. It also shows the WaterMap util.

Another word of warning: slight implementation details might change in the next few days/weeks, but it should be nothing too dramatic!

I’ll probably be doing something more with this when I have the time, but nothing that would likely make it to the repository :-)

Leave a comment (8 comments)

All new normal map shaders in Away3D with Pixel Bender!

Tags: , , , , , , , , , , , , , ,

pixelshadingIt’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.

The new shaders

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.

headshader

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:

  • 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

Demosplaneshader

Enough explanations, time for some demos! Right-click to view source:

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 :)

Leave a comment (10 comments)

September! Speaking at Adobe User Group BE meeting

Tags: , , , ,

augbeThe summer holidays aren’t even over yet and September already seems like it’s going to be a great month! Apart from the fact that I’m going to Flash on the Beach, there’s also something for us Belgians that’s a bit closer to home: the annual Adobe User Group meeting & barbeque on September 12th! And as it happens, I’ll be speaking there alongside much more impressive names as Seb Lee-Delisle and Niqui Merret :)

What to expect? Here’s my session description:

“In his session, David will walk through some of the experiments and projects he has done over the past year while elaborating on the concepts behind them. Without getting too technical, he will explain his motives, his love affair with Pixel Bender and the big looming question: “Mmkay, but what’s the use?”. Using experimentation as the main thread, he will try to show how going off the beaten path can take you to sweet little places you didn’t expect, and finally, offer a sneak-peak at some of the more useful projects he ended up doing as a result.”

In short, since it’s my first public session, I figured I would give a bird’s view of my philosophy concerning after-work development, and show some cool things I have in the pipeline at the moment (so even if you follow this blog, there’ll be something new to look at ;) ).

Don’t forget to register here if you want to come (and gloat) – and if you do, I’ll see you there!

Leave a comment (1 comment)

Some Flash Pixel Bender performance tips + benchmarks

Tags: , , , , ,

flashpbSince 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.

Remember that this concerns Shaders in Flash Player, not Photoshop or After Effects, and that results could change in future versions. All benchmarks were performed on my crummy pc (AMD Athlon 64 X2 Dual, 2.21Ghz, 2GB Ram, Win XP), using 500×500 data with 4 channels, each performing 10 consecutive kernel executions. The kernel itself is just a read, a multiplication, a division, and a sqrt. ShaderJobs are performed synchronously.

Let’s get the obvious out of the way first (I won’t go into common sense optimalizations too much).

Well, duh!

  • Use 4 channels only if necessary. No transparency? Ditch it.
  • Precalculate recurring constant calculations in Flash and pass them as parameters (such as width*height). Sure, it makes the “interface” of your Kernel potentially harder to read, but since Flash doesn’t support dependents (I hope it will some day), this should be a no-brainer if performance is really important.
  • If only a part of a BitmapData needs to be processed, isolate it into a new BitmapData using copyPixels. Even when using applyFilter, sourceRect is buggy.

Told you it was obvious :p Now, some better ones.

Use ShaderJob, not ApplyFilter

  • ShaderJob (on BitmapData) benchmark: 92-99ms
  • ApplyFilter benchmark: 104-109ms
  • ShaderJob ~ 10% faster

BitmapData is faster than ByteArray is faster than Vector.<Number> !

I’ve seen (and been guilty of) a lot of copying BitmapData into a Vector to harness “the power of Vector”. But look at this:

  • ShaderJob on BitmapData: 92-99ms
  • ShaderJob on ByteArray: 147-172ms
  • ShaderJob on Vector.<Number>: 167-192ms
  • BitmapData is ~40% faster than ByteArray
  • BitmapData is ~47% faster than Vector.<Number>!!

Use BitmapData unless you have no other choice, or if complete floating point precision is important.

Conditionals are expensive!

This one annoys me quite a bit. Imagine you’re doing some calculations that you don’t need to do when alpha == 0 (which, as it happens, is usually the case). It can be a good idea to do them anyway in favour of dropping the alpha == 0 check. For the benchmark, I used values that had alpha set to 0 for about half of the data! Compare results to the previous benchmark.

  • BitmapData: 134-192ms – ~47% speed loss!!!
  • ByteArray: 147-172ms – ~22% speed loss
  • Vector: 192-213ms – ~27% speed loss

In practice, test a version with and one without conditional. The results vary heavily depending on how many times calculations are omitted, and how many calculations are otherwise performed. Still, with half the (although slightly trivial) calculations omitted in this case, it’s stupefying that there’s so much increase in execution speed.

Do not use the input as the output

When using a ShaderJob or ApplyFilter, don’t use the same BitmapData/ByteArray/Vector instance that functions as the source. If you need iteration, you’re better of swapping two buffers. What happens is that Flash Player will need to make a temporary copy of the source, which slows things down.

Edit: The results here were compared to the normal ShaderJob test, while they’re using the alpha test. Percentages have been updated

  • BitmapData: 207-218ms – ~30% speed loss
  • ByteArray: 256-271ms – ~65% speed loss
  • Vector: 276-293ms – ~40% speed loss

Update: Asynchronous ShaderJob

I just tested it, and the results indicate that asynchronous calls (waitForCompletion=false) are slower than synchronous calls. I suppose that’s mainly because of the event handling flow. Another thing I tested was to run 2 asynchronous calls with data of half the size, but it seems only 1 asynchronous ShaderJob can be started at the same time.

That’s it, see for yourself!

In closing, I’ll mention something I usually do but doesn’t seem to have any effect (it’s actually a habit from ActionScript). When reading from the same coordinate multiple times, I often store outCoord() in a variable and use that in the sample function. Well, I tested it, and it doesn’t have any impact at all :)

That’s it, at least for now, I hope it’s helpful! Check the benchmark and its source (the source is in fact pretty ugly, but does the trick). I’d be happy to know what kind of results other hardware yields.

Leave a comment (15 comments)

Slice-based volume rendering using Pixel Bender

Tags: , , , , , ,

volumerendering

After a futile exploration of sparse voxel octree ray casting using Alchemy (which was fun but hopeless), I turned towards another technique for volume rendering, using view-aligned slices. The approach is not much different from the rendering of this older experiment, in which the slices were aligned to the object itself. Again, we’re using the same technique to create and read from the 3D texture (which is static in this case): ie. a set of cross sections placed next to eachother. CT scans are wonderful for this:

cross-section

Not that the image above is just a crop-out, we need a lot more to make it look decent (I used 32 cross sections).

Rendering the slices

slicesWhen 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.

As this needs to be done for every pixel on every slice, we’re doing these calculations through Pixel Bender. And that’s how it works in general lines. There’s some translations and scaling going on as well to ensure a uniform and properly centered transformation. If you’re still interested, you can check the source for that. Important to note is that half the slices in the back are actually culled for a worthwhile performance boost. They don’t really contribute all that much to the final image after all.

Demos

Click and drag to rotate the pitbull skull in all demos:

Leave a comment (8 comments)

Render Bender v0.1: optimizing my Flash+Pixel Bender workflow

Tags: , , , , ,

renderbenderOften, when I’m writing Pixel Bender content targeted for Flash Player, the original toolkit leaves something to be desired. Luckily, Joa Ebert created his PBDT plugin for Eclipse which was already a great step to streamline my workflow. Still, the lack of previewing would require switching back to the PB toolkit. And more often than not, that preview didn’t tell me much, as many of my PB projects consist of multiple filters that are dependent on eachother’s output.

Render Bender

So yesterday, I created Render Bender v0.1 (yes, that is some juvenile wordplay) strictly to suit my own needs, but it might just be useful for people out there with the same problem. It is designed to tackle the following issues:

  • Eliminate the need of writing much AS3 code for PB code that might not even work. Instead generating an easy “proof of concept” method.
  • Real Flash-based rendering (instead of simulated rendering of the toolkit, which does not expose runtime bugs)
  • Running a sequence of consecutive Shaders, which may be dependent of a previous Shader or a previous run of an iterative sequence
  • Easy integration with Eclipse and PBDT, without the need of switching applications.
  • Have an easy way of demoing pixel bender effects in development

Essentially, it’s just a Flex App/Component that you need to add to a project, which contains nothing else except for perhaps some interactivity handling necessary for your effect. This way, you can then add your kernels to this project and have them compiled with PBDT. All you need to do is to set up an xml file (once) defining the assets and the kernel sequence. After that, it’s simply a matter of running the project after editing a kernel.

The documentation is a bit sparse at this point, but along with the Demo.mxml source file, it should be pretty clear.

Get it!

In closing…

It’s in early stages, but it works for me :)  I’ll be glad to hear questions, suggestions or bugs. I’m not sure how much time I can invest at this point, but I do have some ideas for future development. At this point, it uses the default Flex skin (3 or 4, depends on your sdk) to minimize compile time. If someone wants to create a minimal fast skin, feel free! :)

Leave a comment (5 comments)

More Stok3d: Parallax mapping & Water shading

Tags: , , , , , , , , ,

waterToday’s update on Stok3d is perhaps not as useful as the previous post, but I certainly had fun working on it. Or as we say in Dutch with a word blatantly stolen from German: it’s “spielerei”.

Demos:

I’m going to post the demos first this time. Saves you some scrolling effort, because the explanations below are rather boring ;)

  • Parallax Mapping : Move and turn towards the edges of the screen to see the extrusion of the texture best. A PhongFilter is added as a second filter, making it slower but the effect becomes more obvious.
  • Water Shading 1 – Ocean : Reflects or refracts light depending on the view angle and the surface relief. It animates a perlin noise filter to generate a water heightmap.
  • Water Shading 2 – Ripples : Same thing, but with a simple drawn ripple effect. The difference between refracted and reflected light is more obvious here.

Edit: Even if you have Flash Player 10, you still might get an update request. That is because these demos require the version of 10.0.22 concerning recent Pixel Bender bugfixes.

The source code for these demos can also be found on Google Code.

Useful updates

Some updates I did involved some bugfixes and performance-related updates. I also added a NormalMapUtil class, which provides a basic API to generate and manipulate normal maps. The main features are the generateFromHeightmap and drawFromHeightmap methods. Since height maps (or bump maps) are generally easier to come by (and to make), these methods generate a normal map for you. generateFromHeightMap creates a new BitmapData, drawFromHeightMap uses an existing BitmapData that you provide (useful if you need to generate one on every frame). The NormalMapUtil class furthermore allows you to invert the components of the normals, in case a normal map reflects the light in the wrong directions.

Water Shading

A new shader filter that was added is the WaterShadingFilter. If you remember your high school physics, depending on the view angle, the surface either reflects the light or lets it pass through and refracts it (which is called the fresnel effect).  To put it simply, when looking at water at a shallow angle, it seems like a very reflective surface, but when looking straight down into it, you can see through it but it’s a distorted view. The reflection uses a combination of environment mapping and phong shading, while the refraction is a simple displacement mapping technique. The DisplayObject to which the filter is applied is used as what’s underneath the surface, ie: the refracted light. The ripples seen in the demo are not made by the filter, but are custom written to manipulate the normal map.

Parallax Mapping

Another new filter is the ParallaxFilter, which performs (you guessed it) parallax mapping. It’s a technique like bump and normal mapping, in the sense that it tries to give more depth to a 2D texture. It does so by displacing texture coordinates based on a height map and view direction to the coordinate that it would normally have in 3D space. This causes the texture to look extruded and more detailed. For more (and better) information, check the article on wikipedia. Stok3d implements an iterative variation. It’s a bit slower but takes care of overlap issues and can handle sharp edges.

That’s it! For now, it’s back to Farbe, and… some other things :)

Leave a comment (15 comments)

© 2009 Der Schmale – David Lenaerts’s blog. All Rights Reserved.

This blog is powered by Wordpress and Magatheme by Bryan Helmig.