torstai 29. maaliskuuta 2012

Gaussian blur for gles2.0

For box2dlights I needed soft shadows and initial guess was blur is the key. Problem was that Gaussian blur can be really heavy especially on mobile devices where GPU memory bandwith can be really low.
I tried many different tricks but it was just too slow. Thankfully I didn't sleep at signal processing lectures and I didn't wasted my time any of those brute force implemenations but instead used separated exis kernel from start. But for getting enough blur I needed at least 9x9 kernel which mean 18 samples and that was still too many. Then I found this efficient-gaussian-blur-with-linear-sampling and method was almoust fast enough but on some devices it just hit against brick wall(namely powerVR gpu's)
Then I realized that I need to calculate texture coordinates on vertex shader and pass those at varyings to prevent "dependant" texture reads on this problematic gpu's.
Full source of shader is here http://pastebin.com/QSbR5Z8T
Using it is really easy just pass fbo sizes as uniform and which pass is nex as another uniform. shader.setUniformf("dir", 1f, 0f); correspond a horizontal pass. This way you can use one shader for both pass and any fbo size without touching there shader code.
Gaussian blur is one basic post proces effect that is used everywhere I have used this shader with good results for basic blurring, bloom, SSAO, VSM,  2d water rendering.. etc. So it's really important have quality and performant shader for this.

tiistai 27. maaliskuuta 2012

Box2dLights

Some how light and light behavior is always fascinated me. Long time ago I noticed that I can do some 2d lights with textures and blendfuncs. Basic model was something like this.
Render scene.
Clear alpha channel.
Render lights to alpha channel with glBlendFunc(GL_SRC_ALPHA, GL_ONE)
Render fullscreen quad with glBlendFunc(GL_ONE, GL_DST_ALPHA)
This give lights and shadows that blend together nicely. But this way you can't get dynamic shadows.

When I coded Boxtrix I did get idea that was too crazy to work. Everyone said that it's not gonna work but I still wanted to test it. Plan was to simulate lights rays using box2d raycasting. After couple hours first prototype was working and looked really ugly but tech seemed to work great.

After Boxtrix was finished I noticed that raycasting lights have really great api and usage is simple. User can add just lights and then one line of code to render lights. That was amazing allready but there was tons of features at wishlist. Softshadows, gles2.0 support, way to query if something is in shadows/lights, lights filters etc. Biggest problem was that usually you don't have alpha channel at render target when you are coding against android. Luckily gl es2.0 solved almoust every problem.
Rendering pipeline goes in box2dLights with gl es 2.0 pretty much like this.

Render scene.
Construct light volumes using crazy amount of raycasts.
Render light volumes to small fbo.
Blur fbo. Using really fast two pass shader that use separate convolution and hardware bilinear filtering tricks. 10samples for 9x9 kernel.
Render lightmap over scene using custom shader that render shadows and lights in one pass.

Box2dLights is complex and powerfull beast but using it is still really simple. Least half dozed published games  is using it and more to come. It's opensource and license is compatible with LibGDX license so it can be used for commercial projects. http://code.google.com/p/box2dlights/

Performance is better than any full gpu solution that I have tested and most of mobile games is fragment shader limited anyway so it's good to use CPU to share some heavy lifting. More info at google code page.