Tuesday, May 3, 2011

Bitwise Operators on Low End GPU's

hi
recently i was needed to perform bitwise operators on SM 3, but as you know, SM 3- doesn't support it (only DX10 SM 4.0 and up).
if you try to write this line: (hlsl SM 3 for example):
some_var & 2
you will get error message saying: Bitwise operations not supported on legacy targets.
the technique i present here can be used for few more things (lighting, shading etc), but here i will show how to do bitwise ops with it.
i support: &, |, ^ (AND,OR,XOR) - more complicated operators could be used but these are the base.
the trick is to use a texture to store the results of these operators, and then to sample this texture and get the result.
a code to compute this texture will look like this: (assuming 8 bit range for AND op)
for i=0 to 255
for j=0 to 255
texture[i][j] = i & j
to maximize storage, encode different operators on different channels.
here is a sample texture that encode AND,OR,XOR in different channels:

bitwise operators texture: AND,OR,XOR

the way you use this texture in your shader looks something like this: (hlsl style)
float AND(in float A, in float B)
{
tex2Dlod(BitwiseOpMap, float4(A, B,0,0)).r;
}

NOTE: make sure you use POINT sampling, you don't want to filter the results in the texture, you also don't need mipmaps...

thats it, i hope you find this post useful...
cya until next time ;)

Sunday, May 1, 2011

Post Anti-Aliasing #2

hi
few months ago i'v read an article on intel research group called: Morphological Antialiasing.
this technique designed for cpu but with few tricks and hacks we can use it on gpu as well.
the algorithm consist of 3 main steps:
1. find discontinuities between pixels
2. identify predefined patterns
3. blend pixels in the neighborhood of the patterns in 2
1. simple edge detection on the image, using depth or color differences should do the work, keep in mind that you should encode edge type in you color channels so you could use it in 2, lets say red is horizontal edges, and g is vertical edges.
2. this is tricky, you basically need to identify few shapes: Z, U, L
see image below (grabbed from original intel article):


Reshetov A. 2009. Morphological Antialiasing. In Proceedings of High Performace Graphics

so based on the article, you only need to identify L shapes, as Z, U can be split into L shapes.
for more deep information please refer to the original article that can be found here:
http://visual-computing.intel-research.net/publications/publications.htm#Y2009

to identify L shapes there are few tricks, a simple one is to just follow the edges you mark in 1 and see if you get a match (few loops for each side: left/right/top/bottom and of course branching), if so you compute blend weights for these and continue to the next edges.
at the end, you end up with blend weights texture so you could blend the pixel to get the final image, you can use a the trick described in gpu pro 2, they encode the final weights in textures and sample it.
btw: if you have ATI HD 6850+ you have built in support for that, so no need to worry, for consoles you may want to worry a little ;)

this technique isn't simple to implement as a first shot, i tried few algorithms and techniques before i got this thing working.
after seeing the demo from gpu pro 2, i'v got to say i was impressed by the speed of their implementation so i put some tricks into mine as well to get the missing cycles :)

optimization tip: when doing edge detection pass, use the stencil buffer to mark these pixels, then in the next step, use the stencil apply your "massive" shapes/blend weights shader only on edges pixels, this way you won't waste power on irrelevant pixels

here is a few screenshots of the main steps and result:

Edges Detection with encoded edge type using image colors

Blend Weights

Without MLAA

With MLAA

Without MLAA

With MLAA

as you can see, this technique have very good result.
extra: few other techniques you should check:
* GPAA - show it at humus
* FXAA - nvidia sdk 11 (looks pretty good)

cya until next time...