We can safely pack normals and tangents to a uint32 each.
Also, I mainly use the second UV set with unique mappings / lightmaps, so it is ensured that the coords always lie within [0,1] - this allows to use D3DDECLTYPE_SHORT2N (the unnormalized SHORT2 type is not supported on my trusty old ATi x700 mobility..). To convert your float UVs you just multiply them with 32767.0f
As a result we get a nice vertexformat like this:
// size = 32 bytes
struct Vertex {
FVec3 pos;
VecU32 nrm;
FVec2 uv;
short uv2[2];
VecU32 tan;
};
D3DVERTEXELEMENT9 declExt[] = {
// stream, offset, type, method, usage, usageIndex
{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
{ 0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 },
// 2d uv
{ 0, 16, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
{ 0, 24, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 },
// tangent
{ 0, 28, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2 },
D3DDECL_END()
};
In your shader just use:
struct VertexInput {
float4 position : POSITION;
float4 norm : NORMAL; // compressed uint32
float2 uv : TEXCOORD0;
float2 uv2 : TEXCOORD1;
float4 tangent : TEXCOORD2; // compressed uint32
};
VertexOutput main(VertexInput IN) {
...
// decompress normal & tangent
float3 N = 2.0f*IN.norm/255.0f-1.0f;
float4 T = 2.0f*IN.tangent/255.0f-1.0f;
...
}
Here is some C++ code to de-/compress your normals:
class VecU32 {
public:
union {
u8 dir[4];
u32 vec32;
};
inline void compress(const FVec3& nrm) {
dir[0] = (u8)((nrm.x * 0.5f + 0.5f) * 255.0f);
dir[1] = (u8)((nrm.y * 0.5f + 0.5f) * 255.0f);
dir[2] = (u8)((nrm.z * 0.5f + 0.5f) * 255.0f);
dir[3] = 255;
}
inline void compress(const FVec4& nrm) {
dir[0] = (u8)((nrm.x * 0.5f + 0.5f) * 255.0f);
dir[1] = (u8)((nrm.y * 0.5f + 0.5f) * 255.0f);
dir[2] = (u8)((nrm.z * 0.5f + 0.5f) * 255.0f);
dir[3] = (u8)((nrm.w * 0.5f + 0.5f) * 255.0f);
}
inline FVec4 decompress() {
return FVec4(
2.0f*dir[0]/255.0f-1.0f,
2.0f*dir[1]/255.0f-1.0f,
2.0f*dir[2]/255.0f-1.0f,
2.0f*dir[3]/255.0f-1.0f
);
}
};
Zeux also has a very nice article about the topic recently:
ReplyDeletehttp://zeuxcg.org/2010/12/14/mesh-optimization-quantizing-floats/