|
-
Senior Member
Wow, you know I never heard that 1/20 pixel thing. That might help piece things together a bit, thank you for the clue. The bitmapFill and drawTriangle routines hide this 1/20 unit scaling from the user, I wonder why gradientFill works differently?
I skimmed that Z-buffer thread (although I am not the least bit conversant in russian, there are code samples+babelfish to piece together the gist). It appears that they're working on a different aspect of the problem - the test/comparison step. You'd like to just use a bitmapData.compare, but this will not do 24-bit subtraction w/ borrowing from channels with higher significance. They appear to be working around that limitation with paletteMaps and some channel swaps.
But I feel a bigger problem is filling the z-buffer in the first place. IMO, the only quick way to do this is with gradientFill and instead writing the whole thing as a 1/z buffer (because that will be linear in screenspace, and you can use the built-in linear interpolation of gradientFill instead of doing a costly rasterization step yourself). With gradient fill, it's a nobrainer to get 8bits (just interpolate colors from black to white ... 0x000000, 0x010101, 0x020202, ... 0xFFFFFF). Getting this fill to work with more significant bits is troublesome, I figured out two separate ways to make it work up to 11bits but I don't know how to go any higher (yet). They both involve some clever fiddling of the colors argument.
The naive extension is to do combine separate sweeps across each channel:
sweep0 : 0x000000 to 0x0000FF ( ratio=0 to 85 )
sweep1 : 0x0000FF to 0x00FFFF ( ratio=85 to 170 )
sweep2 : 0x00FFFF to 0xFFFFFF ( ratio=170 to 255 )
This gives you 256*3 unique colors, which increase monotonically, and effectively a log2(768) = 9.6 bit z-buffer. Not much improvement.
The next idea I had was based on gray codes, it did 8 sweeps of 256 colors each, arranged as:
sweep0: 0x000000 to 0x0000FF (ratio=0 to 31)
sweep1: 0x0000FF to 0x00FFFF (ratio 31 to 63)
sweep2: 0x00FFFF to 0x00FF00 (ratio 63 to 95)
sweep3: 0x00FF00 to 0xFFFF00 (ratio 63 to 95)
sweep4: 0xFFFF00 to 0xFFFFFF ...
sweep5: 0xFFFFFF to 0xFF00FF
sweep6: 0xFF00FF to 0xFF0000
sweep7: 0xFF0000 to 0x010000 (ratio 223 to 255)
This uses 8 entries in the colors[] and ratios[] arguments of gradientFill
This gives you 2048 unique colors, for 11 bits of precision. It's still a nice smooth gradient at all spots, so linear interpolation with gradientFill will always work. The catch is that it's not monotonic increasing or decreasing - so just because the buffer value at one spot is > or < than the buffer value at another spot, that doesn't necessarily mean that the z's are greater or less. That is, the buffer doesn't really store 1/z, it stores some function f(1/z), where f is piecewise smooth, 1:1 and invertible, but not monotonic. You need a more sophisticated comparision function (it has to invert f and then compare) that gets applied per-pixel during composition. This is what is making me think pixelbender/hydra will be needed.
There's a third option I played around with - sweeps of blue with a regular stepping of green:
0x000000 to 0x0000FF (ratio = 0 to ratio = 31)
0x002000 to 0x0020FF (ratio = 32 to ratio = 63)
0x004000 to 0x0040FF (ratio = 64 to ratio = 95)
... so on
or in code:
Code:
var K : int = 32;
for (var i : int = 0; i < 256/K; i++)
{
grad_alphas.push(1);
grad_alphas.push(1);
grad_colors.push(i*K*256+0);
grad_colors.push(i*K*256+0xFF);
grad_ratios.push(i*K);
grad_ratios.push( (i+1)*K-1 );
}
This requires all 16 entries of gradientFills colors[] argument (why oh why is this capped?). If you do the math, it's 2048 unique colors, so were back at 11 bits (that the resolution is the same is just coincidence, they each arrive at a cap of 11 bits for totally different reasons). This could be corrected to higher resolution if the colors[] argument could be longer.
This sequence is monotonic and can be compared directly, but not smooth (ya just can't have it all!). There are jump discontinuities from one color to another (0x00FF and 0x0100 are adjacent in binary arithmetic, but in RGB color space they are miles away). I expect this will lead to noticeable errors in the image, if the gradientFill ends up sampling at ratio=31.5 you'll interpolate between those two colors and end up with a bad 1/z value. You might be able to use a ratios array with no gaps, like: [0 32 32 64 64 96...], I don't know if that's considered valid or not. But it still won't get you beyond 11 bits, because you're capped to 16 colors[] arguments.
Anyway, got a little sidetracked there. The bottom line is that it's the fill step that I am more worried about making fast, the comparison step is manageable with either F9 or F10 tech. And it's the fill step (ie gradientFill) that is limiting you to 11 bits, not the compare. Unless there's a clever and fast way to fill a 24 bit z-buffer that I don't know of, which is entirely possible. If you permit yourself to do multiple gradient z-fills per polygon, a lot of these problems will probably vanish.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|