# Pack spherical normal + specular I & E into ARGB32

## Recommended Posts

skytiger    294
I am thinking about packing a view space normal and specular I & E into ARGB32

12 bits spherical phi(azimuth)
10 bits signed Z
5 bits specular I
5 bits specular E

(I don't need to filter the resulting texture)

because I have run out of MRTs and want to increase the precision of my normals
(currently stored as float4(phi, z, i, e))

also thinking about mapping only the range of Z that is possible
in view space to increase precision of Z

for example: mapping [-0.2, 1.0] --> [0,1]

before I start: has anybody found a good way to do this, or is this a bad idea?

(edit) yes I meant phi

[Edited by - skytiger on December 2, 2010 2:41:11 PM]

##### Share on other sites
Out of curiosity, how to you reconstruct the your normal from the azimuth (I think this is typically labeled phi not theta right?) and z value?

x = sin(theta)*cos(phi)
y = sin(theta)*sin(phi)

I guess sin(theta) = sqrt(1 - z^2)?

##### Share on other sites
skytiger    294
yep, with phi calculated from xz so singularity is when N.y in (-1, 1)
(as vertical fov is less than horizontal)

float2 NormalToSpherical(in float3 N) {	float phi = atan2(N.x, N.z) * OneOverPi;	return float2(phi, N.y);}//functionfloat3 SphericalToNormal(in float2 S) {	float3 N;	sincos(S.x * Pi, N.x, N.z);	float L = sqrt(1.0 - S.y * S.y);	N.xz *= L;	N.y = S.y;	return N;}//function

##### Share on other sites
What about using RGBA1010102 instead, with normal x and y stored in the first two components, your 5+5 specular values in the third, and the sign of the normal stored in the leftover 2 bits? Are you more concerned about whether your proposed layout has enough precision for the normal, or too little for the specular values?

edit: I would speculate that 5 bits for specular intensity and exponent could be a problem actually. If the source of these was a grayscale map you're probably throwing away a lot of detail. You might try finding a specular map somewhere and down-sampling it to 5-bits and see what the result looks like.

[Edited by - doesnotcompute on December 2, 2010 4:55:15 PM]

##### Share on other sites
skytiger    294
great idea, thanks

I was experimenting with RGB10A2 for linear color just yesterday
should have thought of that myself :-)

I could store the sign of phi in A2 also ...

I was going to hack this up for 12,10,5,5:

float4 UnitToColor(in float unit) {    const float4 factor = float4(1, 255, 65280, 16711680);    const float mask = 1.0 / 256.0;    float4 color = frac(unit * factor);    color.rgb -= color.gba * mask;    return color;}//functionfloat ColorToUnit(in float4 color) {    const float4 factor = 1.0 / float4(1, 255, 65280, 16711680);    return dot(color, factor);}//function

##### Share on other sites
skytiger    294
Had some success with this packing:

http://pastebin.com/k5jC1U8F

Because there is only a limited range of view space normals with negative Z that are visible
I can increase normal precision by mapping phi to the visible range ...

Also I think a bit of gamma on the specular intensity would also improve things