Encoding floats to RGBA, again
Hey, it looks like the quest for encoding floats to RGBA textures (part 1, part 2) did not end yet.
Here’s the “best available” code that I have now:
inline float4 EncodeFloatRGBA( float v ) {
return frac( float4(1.0, 255.0, 65025.0, 160581375.0) * v ) + bias;
}
inline float DecodeFloatRGBA( float4 rgba ) {
return dot( rgba, float4(1.0, 1/255.0, 1/65025.0, 1/160581375.0) );
}
Before I thought that bias should be +0.5/255.0 normally, except it had to be around -0.55/255.0 on Radeon cards (older than Radeon HD series). Well, turns out I was wrong, the bias mostly has to be around -0.5/255.0.
Here’s the list (same bias on Windows/D3D9 and OS X/OpenGL, so it seems to be hardware dependent, and not something in API/drivers):
- Radeon 9500 to X850: -0.61/255
- Radeon X1300 to X1900: -0.66/255
- Radeon HD 2xxx/3xxx: -0.49/255
- GeForce FX, 6, 7, 8: -0.48/255
- Intel 915, 945, 965: -0.5/255
Those are the best bias values I could find. Still, every once in a while (rarely) encoding the value to RGBA texture and reading it back would produce something where one channel is half a bit off. Not a problem if you were encoding numbers were originally 0..1 range, but for example if you were encoding something that spans over whole range of the camera, then 0..1 range gets expanded into 0..FarPlane…
And all of a sudden there are huge precision errors, up to the point of being unusable. I just tried doing a quick’n'dirty depth of field and soft particles implementation using depth encoded this way… not good.
Oh well. Has anyone successfully used encoding of high precision number into RGBA channels before?
This looks like it’s related to the internal float representation of the card. I’m pulling numbers out of air, but I would guess that the early Radeons used FP16, x13-x19 used FP24, and HD series finally went to FP32. That would explain the large discrepancies between the early Radeons and the HD/GeForce/Intel cards.
Hmm, come to think of it, I don’t think you could get enough texture addressing with FP16, so scratch that theory.
Hi, I had a go at this problem in my own special way. I’d be very interested in your opinions and results with the following (my post):
http://www.gamedev.net/community/forums/topic.asp?topic_id=485186
It’s certainly less elegant than the frac encode!
@Pat: I think the difference is caused by the texture sampler differences. Even if GPUs do have floating point precision internally, regular 8 bit/channel textures are still sampled (and filtered!) at 8 bit precision, I guess for backwards compatibility reasons. Now, if there’s a very slight change in how the sampling and filtering works, then differences like we have here might surface. That’s my theory at least :)
@Alex: not sure, I haven’t actually tried that approach.
Use these two :)
inline float4 FloatToRGBA(float value)
{
float4 packedValue = frac(value * float4(16777216, 65536, 256, 1));
return packedValue – packedValue.xxyz * float4(0, 1.0 / 256, 1.0 / 256, 1.0 / 256);
}
inline float RGBAToFloat(float4 packedValue)
{
return dot(packedValue, float4( 1.0 / 16777216, 1.0 / 65536, 1.0 / 256, 1.0));
}
This works quite well for all values from 0.0 (included) to 1.0 (excluded).
If you need to store value 1.0 too, you can simply divide the input of FloatToRGBA and multiply the output of RGBAToFloat by 0.9999991 loosing only a small amount of precision.
It seems to work quite well also with bilinear interpolation of textures.
[...] right there on my previous blog post [...]
Be convinced of it or not, 7 commuter vehicles are not newfangled inventions. In actuality, they time retreat from to the 1920s when there were vehicles called depot hacks that were euphemistic pre-owned to report people and their luggage to and from train stations. In the 1940s, Jeep truly introduced a 7 rider conduit called the Jeep Wagon.
There possess also been numerous 7 rider vehicles at an end the years that were called status wagons. Some of these were uninterrupted effective of room 9 people. However, appoint wagons be dressed evolved into SUVs and minivans and today it is tough to purchase something called a place wagon.
Today’s 7 Rider Vehicles
Location wagons began losing acceptance in the 1970s suitable mostly to the 1973 unguent crisis. It created a slightly ill of turning instant against the model American rank wagon with its vinyl bench seats and sluggish V8 engine. Some people referred to these as “lumbering landmarks.” The last American-made, full-size models were the Chevrolet Caprice and the Buick Roadmaster. Both were discontinued in 1996.
As mentioned greater than, two types of 7 voyager vehicles pull someone’s leg replaced caste wagons. The first of these is the minivan as mentioned above. Chrysler Corporation introduced it in 1984. Minivans quickly became predominating because they would adapt 7 passengers (or 4 people with a straws of consignment) and because they offered so much more national space than the to some degree low-slung position wagons.
The second category of conveyance that helped kill touched in the head the spot wagon is the 7 rider SUV. There are now varied of these vehicles elbow in a wide range of prices. This includes high-priced, luxuriousness vehicles such as the Cadillac Escalade, the Lincoln Seaman, the Mercedes-Benz GL 450 and the Lexus LX 570, all of which can tariff up to $70,000. Lower-priced 7 rider SUVs list the Toyota Highlander, the Ford Explorer and the Honda Pilot. However, it is important to be conversant with that “lower-priced” means vehicles that cost from $25,000-$35,000. In laconic, they are lower-priced alone when compared to the opulence models.
google lidafuck