Added vertex pack/unpack support.

This commit is contained in:
bkaradzic 2012-12-31 18:48:52 -08:00
parent d4cd0ea4fa
commit 446686b48f
11 changed files with 351 additions and 192 deletions

View file

@ -42,21 +42,6 @@ uint32_t packUint32(uint8_t _x, uint8_t _y, uint8_t _z, uint8_t _w)
return un.ui32; return un.ui32;
} }
void unpackUint32(uint8_t _result[4], uint32_t _packed)
{
union
{
uint32_t ui32;
uint8_t arr[4];
} un;
un.ui32 = _packed;
_result[0] = un.arr[0];
_result[1] = un.arr[1];
_result[2] = un.arr[2];
_result[3] = un.arr[3];
}
uint32_t packF4u(float _x, float _y = 0.0f, float _z = 0.0f, float _w = 0.0f) uint32_t packF4u(float _x, float _y = 0.0f, float _z = 0.0f, float _w = 0.0f)
{ {
const uint8_t xx = uint8_t(_x*127.0f + 128.0f); const uint8_t xx = uint8_t(_x*127.0f + 128.0f);
@ -66,16 +51,6 @@ uint32_t packF4u(float _x, float _y = 0.0f, float _z = 0.0f, float _w = 0.0f)
return packUint32(xx, yy, zz, ww); return packUint32(xx, yy, zz, ww);
} }
void unpackF4u(float _result[4], uint32_t _packed)
{
uint8_t unpacked[4];
unpackUint32(unpacked, _packed);
_result[0] = (float(unpacked[0]) - 128.0f)/127.0f;
_result[1] = (float(unpacked[1]) - 128.0f)/127.0f;
_result[2] = (float(unpacked[2]) - 128.0f)/127.0f;
_result[3] = (float(unpacked[3]) - 128.0f)/127.0f;
}
static PosNormalTangentTexcoordVertex s_cubeVertices[24] = static PosNormalTangentTexcoordVertex s_cubeVertices[24] =
{ {
{-1.0f, 1.0f, 1.0f, packF4u( 0.0f, 0.0f, 1.0f), 0, 0.0f, 0.0f }, {-1.0f, 1.0f, 1.0f, packF4u( 0.0f, 0.0f, 1.0f), 0, 0.0f, 0.0f },
@ -172,18 +147,42 @@ static const bgfx::Memory* loadTexture(const char* _name)
return load(filePath); return load(filePath);
} }
template<typename Ty> void calcTangents(void* _vertices, uint16_t _numVertices, bgfx::VertexDecl _decl, const uint16_t* _indices, uint32_t _numIndices)
void calcTangents(const uint16_t* _indices, uint32_t _numIndices, Ty* _vertices, uint16_t _numVertices)
{ {
struct PosTexcoord
{
float m_x;
float m_y;
float m_z;
float m_pad0;
float m_u;
float m_v;
float m_pad1;
float m_pad2;
};
float* tangents = new float[6*_numVertices]; float* tangents = new float[6*_numVertices];
memset(tangents, 0, 6*_numVertices*sizeof(float) ); memset(tangents, 0, 6*_numVertices*sizeof(float) );
PosTexcoord v0;
PosTexcoord v1;
PosTexcoord v2;
for (uint32_t ii = 0, num = _numIndices/3; ii < num; ++ii) for (uint32_t ii = 0, num = _numIndices/3; ii < num; ++ii)
{ {
const uint16_t* indices = &_indices[ii*3]; const uint16_t* indices = &_indices[ii*3];
const Ty& v0 = _vertices[indices[0] ]; uint32_t i0 = indices[0];
const Ty& v1 = _vertices[indices[1] ]; uint32_t i1 = indices[1];
const Ty& v2 = _vertices[indices[2] ]; uint32_t i2 = indices[2];
bgfx::vertexUnpack(&v0.m_x, bgfx::Attrib::Position, _decl, _vertices, i0);
bgfx::vertexUnpack(&v0.m_u, bgfx::Attrib::TexCoord0, _decl, _vertices, i0);
bgfx::vertexUnpack(&v1.m_x, bgfx::Attrib::Position, _decl, _vertices, i1);
bgfx::vertexUnpack(&v1.m_u, bgfx::Attrib::TexCoord0, _decl, _vertices, i1);
bgfx::vertexUnpack(&v2.m_x, bgfx::Attrib::Position, _decl, _vertices, i2);
bgfx::vertexUnpack(&v2.m_u, bgfx::Attrib::TexCoord0, _decl, _vertices, i2);
const float bax = v1.m_x - v0.m_x; const float bax = v1.m_x - v0.m_x;
const float bay = v1.m_y - v0.m_y; const float bay = v1.m_y - v0.m_y;
@ -224,12 +223,11 @@ void calcTangents(const uint16_t* _indices, uint32_t _numIndices, Ty* _vertices,
for (uint32_t ii = 0; ii < _numVertices; ++ii) for (uint32_t ii = 0; ii < _numVertices; ++ii)
{ {
Ty& v0 = _vertices[ii];
const float* tanu = &tangents[ii*6]; const float* tanu = &tangents[ii*6];
const float* tanv = &tangents[ii*6 + 3]; const float* tanv = &tangents[ii*6 + 3];
float normal[4]; float normal[4];
unpackF4u(normal, v0.m_normal); bgfx::vertexUnpack(normal, bgfx::Attrib::Normal, _decl, _vertices, ii);
float ndt = vec3Dot(normal, tanu); float ndt = vec3Dot(normal, tanu);
float nxt[3]; float nxt[3];
@ -240,13 +238,13 @@ void calcTangents(const uint16_t* _indices, uint32_t _numIndices, Ty* _vertices,
tmp[1] = tanu[1] - normal[1] * ndt; tmp[1] = tanu[1] - normal[1] * ndt;
tmp[2] = tanu[2] - normal[2] * ndt; tmp[2] = tanu[2] - normal[2] * ndt;
float tangent[3]; float tangent[4];
vec3Norm(tangent, tmp); vec3Norm(tangent, tmp);
float tw = vec3Dot(nxt, tanv) < 0.0f ? -1.0f : 1.0f; tangent[3] = vec3Dot(nxt, tanv) < 0.0f ? -1.0f : 1.0f;
v0.m_tangent = packF4u(tangent[0], tangent[1], tangent[2], tw); bgfx::vertexPack(tangent, true, bgfx::Attrib::Tangent, _decl, _vertices, ii);
} }
} }
int _main_(int _argc, char** _argv) int _main_(int _argc, char** _argv)
{ {
@ -293,14 +291,14 @@ int _main_(int _argc, char** _argv)
// Create vertex stream declaration. // Create vertex stream declaration.
s_PosNormalTangentTexcoordDecl.begin(); s_PosNormalTangentTexcoordDecl.begin();
s_PosNormalTangentTexcoordDecl.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float); s_PosNormalTangentTexcoordDecl.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float);
s_PosNormalTangentTexcoordDecl.add(bgfx::Attrib::Normal, 4, bgfx::AttribType::Uint8, true); s_PosNormalTangentTexcoordDecl.add(bgfx::Attrib::Normal, 4, bgfx::AttribType::Uint8, true, true);
s_PosNormalTangentTexcoordDecl.add(bgfx::Attrib::Tangent, 4, bgfx::AttribType::Uint8, true); s_PosNormalTangentTexcoordDecl.add(bgfx::Attrib::Tangent, 4, bgfx::AttribType::Uint8, true, true);
s_PosNormalTangentTexcoordDecl.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float); s_PosNormalTangentTexcoordDecl.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float);
s_PosNormalTangentTexcoordDecl.end(); s_PosNormalTangentTexcoordDecl.end();
const bgfx::Memory* mem; const bgfx::Memory* mem;
calcTangents(s_cubeIndices, countof(s_cubeIndices), s_cubeVertices, countof(s_cubeVertices) ); calcTangents(s_cubeVertices, countof(s_cubeVertices), s_PosNormalTangentTexcoordDecl, s_cubeIndices, countof(s_cubeIndices) );
// Create static vertex buffer. // Create static vertex buffer.
mem = bgfx::makeRef(s_cubeVertices, sizeof(s_cubeVertices) ); mem = bgfx::makeRef(s_cubeVertices, sizeof(s_cubeVertices) );

View file

@ -329,7 +329,10 @@ struct BgfxCallback : public bgfx::CallbackI
virtual void fatal(bgfx::Fatal::Enum _code, const char* _str) BX_OVERRIDE virtual void fatal(bgfx::Fatal::Enum _code, const char* _str) BX_OVERRIDE
{ {
// Something unexpected happened, inform user and bail out.
dbgPrintf("Fatal error: 0x%08x: %s", _code, _str); dbgPrintf("Fatal error: 0x%08x: %s", _code, _str);
// Must terminate, continuing will cause crash anyway.
abort(); abort();
} }
@ -337,14 +340,18 @@ struct BgfxCallback : public bgfx::CallbackI
{ {
char filePath[256]; char filePath[256];
bx::snprintf(filePath, sizeof(filePath), "%016" PRIx64, _id); bx::snprintf(filePath, sizeof(filePath), "%016" PRIx64, _id);
// Use cache id as filename.
FILE* file = fopen(filePath, "rb"); FILE* file = fopen(filePath, "rb");
if (NULL != file) if (NULL != file)
{ {
uint32_t size = fsize(file); uint32_t size = fsize(file);
fclose(file); fclose(file);
// Return size of shader file.
return size; return size;
} }
// Return 0 if shader is not found.
return 0; return 0;
} }
@ -352,14 +359,20 @@ struct BgfxCallback : public bgfx::CallbackI
{ {
char filePath[256]; char filePath[256];
bx::snprintf(filePath, sizeof(filePath), "%016" PRIx64, _id); bx::snprintf(filePath, sizeof(filePath), "%016" PRIx64, _id);
// Use cache id as filename.
FILE* file = fopen(filePath, "rb"); FILE* file = fopen(filePath, "rb");
if (NULL != file) if (NULL != file)
{ {
// Read shader.
size_t result = fread(_data, 1, _size, file); size_t result = fread(_data, 1, _size, file);
fclose(file); fclose(file);
// Make sure that read size matches requested size.
return result == _size; return result == _size;
} }
// Shader is not found in cache, needs to be rebuilt.
return false; return false;
} }
@ -368,9 +381,11 @@ struct BgfxCallback : public bgfx::CallbackI
char filePath[256]; char filePath[256];
bx::snprintf(filePath, sizeof(filePath), "%016" PRIx64, _id); bx::snprintf(filePath, sizeof(filePath), "%016" PRIx64, _id);
// Use cache id as filename.
FILE* file = fopen(filePath, "wb"); FILE* file = fopen(filePath, "wb");
if (NULL != file) if (NULL != file)
{ {
// Write shader to cache location.
fwrite(_data, 1, _size, file); fwrite(_data, 1, _size, file);
fclose(file); fclose(file);
} }
@ -378,6 +393,7 @@ struct BgfxCallback : public bgfx::CallbackI
virtual void screenShot(const char* _filePath, uint32_t _width, uint32_t _height, uint32_t _pitch, const void* _data, uint32_t /*_size*/, bool _yflip) BX_OVERRIDE virtual void screenShot(const char* _filePath, uint32_t _width, uint32_t _height, uint32_t _pitch, const void* _data, uint32_t /*_size*/, bool _yflip) BX_OVERRIDE
{ {
// Save screen shot as TGA.
saveTga(_filePath, _width, _height, _pitch, _data, false, _yflip); saveTga(_filePath, _width, _height, _pitch, _data, false, _yflip);
} }
@ -556,7 +572,7 @@ int _main_(int _argc, char** _argv)
} }
} }
// Take screenshot at frame 150. // Take screen shot at frame 150.
if (150 == frame) if (150 == frame)
{ {
bgfx::saveScreenShot("frame150.tga"); bgfx::saveScreenShot("frame150.tga");

Binary file not shown.

Binary file not shown.

View file

@ -386,8 +386,8 @@ namespace bgfx
virtual void captureFrame(const void* _data, uint32_t _size) = 0; virtual void captureFrame(const void* _data, uint32_t _size) = 0;
}; };
inline CallbackI::~CallbackI() inline CallbackI::~CallbackI()
{ {
} }
struct Memory struct Memory
@ -442,10 +442,10 @@ namespace bgfx
void end(); void end();
/// Add attribute to VertexDecl. Note: Must be called between begin/end. /// Add attribute to VertexDecl. Note: Must be called between begin/end.
void add(Attrib::Enum _attrib, uint8_t _num, AttribType::Enum _type, bool _normalized = false); void add(Attrib::Enum _attrib, uint8_t _num, AttribType::Enum _type, bool _normalized = false, bool _asInt = false);
/// Decode attribute. /// Decode attribute.
void decode(Attrib::Enum _attrib, uint8_t& _num, AttribType::Enum& _type, bool& _normalized) const; void decode(Attrib::Enum _attrib, uint8_t& _num, AttribType::Enum& _type, bool& _normalized, bool& _asInt) const;
/// Returns true if VertexDecl contains attribute. /// Returns true if VertexDecl contains attribute.
bool has(Attrib::Enum _attrib) const { return 0xff != m_attributes[_attrib]; } bool has(Attrib::Enum _attrib) const { return 0xff != m_attributes[_attrib]; }
@ -465,6 +465,12 @@ namespace bgfx
uint8_t m_attributes[Attrib::Count]; uint8_t m_attributes[Attrib::Count];
}; };
/// Pack vec4 into vertex stream format.
void vertexPack(const float _input[4], bool _inputNormalized, Attrib::Enum _attr, const VertexDecl& _decl, void* _data, uint32_t _index = 0);
/// Unpack vec4 from vertex stream format.
void vertexUnpack(float _output[4], Attrib::Enum _attr, const VertexDecl& _decl, const void* _data, uint32_t _index = 0);
/// Returns renderer backend API type. /// Returns renderer backend API type.
RendererType::Enum getRendererType(); RendererType::Enum getRendererType();

View file

@ -229,7 +229,8 @@ namespace bgfx
uint8_t num; uint8_t num;
AttribType::Enum type; AttribType::Enum type;
bool normalized; bool normalized;
_decl.decode(Attrib::Enum(attr), num, type, normalized); bool asInt;
_decl.decode(Attrib::Enum(attr), num, type, normalized, asInt);
elem->Format = s_attribType[type][num-1][normalized]; elem->Format = s_attribType[type][num-1][normalized];
elem->AlignedByteOffset = _decl.m_offset[attr]; elem->AlignedByteOffset = _decl.m_offset[attr];
} }

View file

@ -1045,7 +1045,8 @@ namespace bgfx
uint8_t num; uint8_t num;
AttribType::Enum type; AttribType::Enum type;
bool normalized; bool normalized;
_decl.decode(Attrib::Enum(attr), num, type, normalized); bool asInt;
_decl.decode(Attrib::Enum(attr), num, type, normalized, asInt);
memcpy(elem, &s_attrib[attr], sizeof(D3DVERTEXELEMENT9) ); memcpy(elem, &s_attrib[attr], sizeof(D3DVERTEXELEMENT9) );

View file

@ -1269,7 +1269,8 @@ namespace bgfx
uint8_t num; uint8_t num;
AttribType::Enum type; AttribType::Enum type;
bool normalized; bool normalized;
_vertexDecl.decode(attr, num, type, normalized); bool asInt;
_vertexDecl.decode(attr, num, type, normalized, asInt);
if (-1 != loc if (-1 != loc
&& 0xff != _vertexDecl.m_attributes[attr]) && 0xff != _vertexDecl.m_attributes[attr])

View file

@ -5,6 +5,7 @@
#include <string.h> #include <string.h>
#include <bx/hash.h> #include <bx/hash.h>
#include <bx/uint32_t.h>
#include "vertexdecl.h" #include "vertexdecl.h"
@ -65,23 +66,25 @@ namespace bgfx
m_hash = bx::hashMurmur2A(m_attributes, sizeof(m_attributes) ); m_hash = bx::hashMurmur2A(m_attributes, sizeof(m_attributes) );
} }
void VertexDecl::add(Attrib::Enum _attrib, uint8_t _num, AttribType::Enum _type, bool _normalized) void VertexDecl::add(Attrib::Enum _attrib, uint8_t _num, AttribType::Enum _type, bool _normalized, bool _asInt)
{ {
const uint8_t encoded_norm = (_normalized&1)<<6; const uint8_t encodedNorm = (_normalized&1)<<6;
const uint8_t encoded_type = (_type&3)<<3; const uint8_t encodedType = (_type&3)<<3;
const uint8_t encoded_num = (_num-1)&3; const uint8_t encodedNum = (_num-1)&3;
const uint8_t encodeAsInt = (_asInt&(!!"\x1\x1\x0\x0"[_type]) )<<7;
m_attributes[_attrib] = encoded_norm|encoded_type|encoded_num; m_attributes[_attrib] = encodedNorm|encodedType|encodedNum|encodeAsInt;
m_offset[_attrib] = m_stride; m_offset[_attrib] = m_stride;
m_stride += (*s_attribTypeSize[m_hash])[_type][_num-1]; m_stride += (*s_attribTypeSize[m_hash])[_type][_num-1];
} }
void VertexDecl::decode(Attrib::Enum _attrib, uint8_t& _num, AttribType::Enum& _type, bool& _normalized) const void VertexDecl::decode(Attrib::Enum _attrib, uint8_t& _num, AttribType::Enum& _type, bool& _normalized, bool& _asInt) const
{ {
uint8_t val = m_attributes[_attrib]; uint8_t val = m_attributes[_attrib];
_num = (val&3)+1; _num = (val&3)+1;
_type = AttribType::Enum((val>>3)&3); _type = AttribType::Enum((val>>3)&3);
_normalized = !!(val&(1<<6) ); _normalized = !!(val&(1<<6) );
_asInt = !!(val&(1<<7) );
} }
const char* getAttribName(Attrib::Enum _attr) const char* getAttribName(Attrib::Enum _attr)
@ -123,14 +126,16 @@ namespace bgfx
uint8_t num; uint8_t num;
AttribType::Enum type; AttribType::Enum type;
bool normalized; bool normalized;
_decl.decode(Attrib::Enum(attr), num, type, normalized); bool asInt;
_decl.decode(Attrib::Enum(attr), num, type, normalized, asInt);
BX_TRACE("\tattr %d - %s, num %d, type %d, norm %d, offset %d" BX_TRACE("\tattr %d - %s, num %d, type %d, norm %d, asint %d, offset %d"
, attr , attr
, getAttribName(Attrib::Enum(attr) ) , getAttribName(Attrib::Enum(attr) )
, num , num
, type , type
, normalized , normalized
, asInt
, _decl.m_offset[attr] , _decl.m_offset[attr]
); );
} }
@ -140,4 +145,218 @@ namespace bgfx
#endif // BGFX_CONFIG_DEBUG #endif // BGFX_CONFIG_DEBUG
} }
void vertexPack(const float _input[4], bool _inputNormalized, Attrib::Enum _attr, const VertexDecl& _decl, void* _data, uint32_t _index)
{
if (!_decl.has(_attr) )
{
return;
}
uint32_t stride = _decl.getStride();
uint8_t* data = (uint8_t*)_data + _index*stride + _decl.getOffset(_attr);
uint8_t num;
AttribType::Enum type;
bool normalized;
bool asInt;
_decl.decode(_attr, num, type, normalized, asInt);
switch (type)
{
case AttribType::Uint8:
{
uint8_t* packed = (uint8_t*)data;
if (_inputNormalized)
{
if (asInt)
{
switch (num)
{
default: *packed++ = uint8_t(*_input++ * 127.0f + 128.0f);
case 3: *packed++ = uint8_t(*_input++ * 127.0f + 128.0f);
case 2: *packed++ = uint8_t(*_input++ * 127.0f + 128.0f);
case 1: *packed++ = uint8_t(*_input++ * 127.0f + 128.0f);
}
}
else
{
switch (num)
{
default: *packed++ = uint8_t(*_input++ * 255.0f);
case 3: *packed++ = uint8_t(*_input++ * 255.0f);
case 2: *packed++ = uint8_t(*_input++ * 255.0f);
case 1: *packed++ = uint8_t(*_input++ * 255.0f);
}
}
}
else
{
switch (num)
{
default: *packed++ = uint8_t(*_input++);
case 3: *packed++ = uint8_t(*_input++);
case 2: *packed++ = uint8_t(*_input++);
case 1: *packed++ = uint8_t(*_input++);
}
}
}
break;
case AttribType::Uint16:
{
uint16_t* packed = (uint16_t*)data;
if (_inputNormalized)
{
if (asInt)
{
switch (num)
{
default: *packed++ = uint16_t(*_input++ * 32767.0f + 32768.0f);
case 3: *packed++ = uint16_t(*_input++ * 32767.0f + 32768.0f);
case 2: *packed++ = uint16_t(*_input++ * 32767.0f + 32768.0f);
case 1: *packed++ = uint16_t(*_input++ * 32767.0f + 32768.0f);
}
}
else
{
switch (num)
{
default: *packed++ = uint16_t(*_input++ * 65535.0f);
case 3: *packed++ = uint16_t(*_input++ * 65535.0f);
case 2: *packed++ = uint16_t(*_input++ * 65535.0f);
case 1: *packed++ = uint16_t(*_input++ * 65535.0f);
}
}
}
else
{
switch (num)
{
default: *packed++ = uint16_t(*_input++);
case 3: *packed++ = uint16_t(*_input++);
case 2: *packed++ = uint16_t(*_input++);
case 1: *packed++ = uint16_t(*_input++);
}
}
}
break;
case AttribType::Half:
{
uint16_t* packed = (uint16_t*)data;
switch (num)
{
default: *packed++ = bx::halfFromFloat(*_input++);
case 3: *packed++ = bx::halfFromFloat(*_input++);
case 2: *packed++ = bx::halfFromFloat(*_input++);
case 1: *packed++ = bx::halfFromFloat(*_input++);
}
}
break;
case AttribType::Float:
memcpy(data, _input, num*sizeof(float) );
break;
}
}
void vertexUnpack(float _output[4], Attrib::Enum _attr, const VertexDecl& _decl, const void* _data, uint32_t _index)
{
if (!_decl.has(_attr) )
{
memset(_output, 0, 4*sizeof(float) );
return;
}
uint32_t stride = _decl.getStride();
uint8_t* data = (uint8_t*)_data + _index*stride + _decl.getOffset(_attr);
uint8_t num;
AttribType::Enum type;
bool normalized;
bool asInt;
_decl.decode(_attr, num, type, normalized, asInt);
switch (type)
{
case AttribType::Uint8:
{
uint8_t* packed = (uint8_t*)data;
if (asInt)
{
switch (num)
{
default: *_output++ = (float(*packed++) - 128.0f)*1.0f/127.0f;
case 3: *_output++ = (float(*packed++) - 128.0f)*1.0f/127.0f;
case 2: *_output++ = (float(*packed++) - 128.0f)*1.0f/127.0f;
case 1: *_output++ = (float(*packed++) - 128.0f)*1.0f/127.0f;
}
}
else
{
switch (num)
{
default: *_output++ = float(*packed++)*1.0f/255.0f;
case 3: *_output++ = float(*packed++)*1.0f/255.0f;
case 2: *_output++ = float(*packed++)*1.0f/255.0f;
case 1: *_output++ = float(*packed++)*1.0f/255.0f;
}
}
}
break;
case AttribType::Uint16:
{
uint16_t* packed = (uint16_t*)data;
if (asInt)
{
switch (num)
{
default: *_output++ = (float(*packed++) - 32768.0f)*1.0f/32767.0f;
case 3: *_output++ = (float(*packed++) - 32768.0f)*1.0f/32767.0f;
case 2: *_output++ = (float(*packed++) - 32768.0f)*1.0f/32767.0f;
case 1: *_output++ = (float(*packed++) - 32768.0f)*1.0f/32767.0f;
}
}
else
{
switch (num)
{
default: *_output++ = float(*packed++)*1.0f/65535.0f;
case 3: *_output++ = float(*packed++)*1.0f/65535.0f;
case 2: *_output++ = float(*packed++)*1.0f/65535.0f;
case 1: *_output++ = float(*packed++)*1.0f/65535.0f;
}
}
}
break;
case AttribType::Half:
{
uint16_t* packed = (uint16_t*)data;
switch (num)
{
default: *_output++ = bx::halfToFloat(*packed++);
case 3: *_output++ = bx::halfToFloat(*packed++);
case 2: *_output++ = bx::halfToFloat(*packed++);
case 1: *_output++ = bx::halfToFloat(*packed++);
}
}
break;
case AttribType::Float:
memcpy(_output, data, num*sizeof(float) );
_output += num;
break;
}
switch (num)
{
case 1: *_output++ = 0.0f;
case 2: *_output++ = 0.0f;
case 3: *_output++ = 0.0f;
default: break;
}
}
} // namespace bgfx } // namespace bgfx

View file

@ -7,7 +7,10 @@
namespace bgfx namespace bgfx
{ {
/// Returns attribute name.
const char* getAttribName(Attrib::Enum _attr); const char* getAttribName(Attrib::Enum _attr);
/// Dump vertex declaration into debug output.
void dump(const VertexDecl& _decl); void dump(const VertexDecl& _decl);
} // namespace bgfx } // namespace bgfx

View file

@ -133,95 +133,42 @@ void triangleReorder(uint16_t* _indices, uint32_t _numIndices, uint32_t _numVert
delete [] newIndexList; delete [] newIndexList;
} }
uint32_t packUint32(uint8_t _x, uint8_t _y, uint8_t _z, uint8_t _w) void calcTangents(void* _vertices, uint16_t _numVertices, bgfx::VertexDecl _decl, const uint16_t* _indices, uint32_t _numIndices)
{
union
{
uint32_t ui32;
uint8_t arr[4];
} un;
un.arr[0] = _x;
un.arr[1] = _y;
un.arr[2] = _z;
un.arr[3] = _w;
return un.ui32;
}
void unpackUint32(uint8_t _result[4], uint32_t _packed)
{
union
{
uint32_t ui32;
uint8_t arr[4];
} un;
un.ui32 = _packed;
_result[0] = un.arr[0];
_result[1] = un.arr[1];
_result[2] = un.arr[2];
_result[3] = un.arr[3];
}
uint32_t packF4u(float _x, float _y = 0.0f, float _z = 0.0f, float _w = 0.0f)
{
const uint8_t xx = uint8_t(_x*127.0f + 128.0f);
const uint8_t yy = uint8_t(_y*127.0f + 128.0f);
const uint8_t zz = uint8_t(_z*127.0f + 128.0f);
const uint8_t ww = uint8_t(_w*127.0f + 128.0f);
return packUint32(xx, yy, zz, ww);
}
void unpackF4u(float _result[4], uint32_t _packed)
{
uint8_t unpacked[4];
unpackUint32(unpacked, _packed);
_result[0] = (float(unpacked[0]) - 128.0f)/127.0f;
_result[1] = (float(unpacked[1]) - 128.0f)/127.0f;
_result[2] = (float(unpacked[2]) - 128.0f)/127.0f;
_result[3] = (float(unpacked[3]) - 128.0f)/127.0f;
}
uint32_t packF2h(float _x, float _y)
{
union
{
uint32_t ui32;
uint16_t arr[2];
} un;
un.arr[0] = bx::halfFromFloat(_x);
un.arr[1] = bx::halfFromFloat(_y);
return un.ui32;
}
void unpackF2h(float _result[2], uint32_t _packed)
{
union
{
uint32_t ui32;
uint16_t arr[2];
} un;
un.ui32 = _packed;
_result[0] = bx::halfToFloat(un.arr[0]);
_result[1] = bx::halfToFloat(un.arr[1]);
}
template<typename Ty>
void calcTangents(const uint16_t* _indices, uint32_t _numIndices, Ty* _vertices, uint16_t _numVertices)
{ {
struct PosTexcoord
{
float m_x;
float m_y;
float m_z;
float m_pad0;
float m_u;
float m_v;
float m_pad1;
float m_pad2;
};
float* tangents = new float[6*_numVertices]; float* tangents = new float[6*_numVertices];
memset(tangents, 0, 6*_numVertices*sizeof(float) ); memset(tangents, 0, 6*_numVertices*sizeof(float) );
PosTexcoord v0;
PosTexcoord v1;
PosTexcoord v2;
for (uint32_t ii = 0, num = _numIndices/3; ii < num; ++ii) for (uint32_t ii = 0, num = _numIndices/3; ii < num; ++ii)
{ {
const uint16_t* indices = &_indices[ii*3]; const uint16_t* indices = &_indices[ii*3];
const Ty& v0 = _vertices[indices[0] ]; uint32_t i0 = indices[0];
const Ty& v1 = _vertices[indices[1] ]; uint32_t i1 = indices[1];
const Ty& v2 = _vertices[indices[2] ]; uint32_t i2 = indices[2];
bgfx::vertexUnpack(&v0.m_x, bgfx::Attrib::Position, _decl, _vertices, i0);
bgfx::vertexUnpack(&v0.m_u, bgfx::Attrib::TexCoord0, _decl, _vertices, i0);
bgfx::vertexUnpack(&v1.m_x, bgfx::Attrib::Position, _decl, _vertices, i1);
bgfx::vertexUnpack(&v1.m_u, bgfx::Attrib::TexCoord0, _decl, _vertices, i1);
bgfx::vertexUnpack(&v2.m_x, bgfx::Attrib::Position, _decl, _vertices, i2);
bgfx::vertexUnpack(&v2.m_u, bgfx::Attrib::TexCoord0, _decl, _vertices, i2);
const float bax = v1.m_x - v0.m_x; const float bax = v1.m_x - v0.m_x;
const float bay = v1.m_y - v0.m_y; const float bay = v1.m_y - v0.m_y;
@ -262,12 +209,11 @@ void calcTangents(const uint16_t* _indices, uint32_t _numIndices, Ty* _vertices,
for (uint32_t ii = 0; ii < _numVertices; ++ii) for (uint32_t ii = 0; ii < _numVertices; ++ii)
{ {
Ty& v0 = _vertices[ii];
const float* tanu = &tangents[ii*6]; const float* tanu = &tangents[ii*6];
const float* tanv = &tangents[ii*6 + 3]; const float* tanv = &tangents[ii*6 + 3];
float normal[4]; float normal[4];
unpackF4u(normal, v0.m_normal); bgfx::vertexUnpack(normal, bgfx::Attrib::Normal, _decl, _vertices, ii);
float ndt = vec3Dot(normal, tanu); float ndt = vec3Dot(normal, tanu);
float nxt[3]; float nxt[3];
@ -278,11 +224,11 @@ void calcTangents(const uint16_t* _indices, uint32_t _numIndices, Ty* _vertices,
tmp[1] = tanu[1] - normal[1] * ndt; tmp[1] = tanu[1] - normal[1] * ndt;
tmp[2] = tanu[2] - normal[2] * ndt; tmp[2] = tanu[2] - normal[2] * ndt;
float tangent[3]; float tangent[4];
vec3Norm(tangent, tmp); vec3Norm(tangent, tmp);
float tw = vec3Dot(nxt, tanv) < 0.0f ? -1.0f : 1.0f; tangent[3] = vec3Dot(nxt, tanv) < 0.0f ? -1.0f : 1.0f;
v0.m_tangent = packF4u(tangent[0], tangent[1], tangent[2], tw); bgfx::vertexPack(tangent, true, bgfx::Attrib::Tangent, _decl, _vertices, ii);
} }
} }
@ -752,6 +698,8 @@ int main(int _argc, const char* _argv[])
if (hasNormal) if (hasNormal)
{ {
hasTangent &= hasTexcoord;
switch (packNormal) switch (packNormal)
{ {
default: default:
@ -764,10 +712,10 @@ int main(int _argc, const char* _argv[])
break; break;
case 1: case 1:
decl.add(bgfx::Attrib::Normal, 4, bgfx::AttribType::Uint8, true); decl.add(bgfx::Attrib::Normal, 4, bgfx::AttribType::Uint8, true, true);
if (hasTangent) if (hasTangent)
{ {
decl.add(bgfx::Attrib::Tangent, 4, bgfx::AttribType::Uint8, true); decl.add(bgfx::Attrib::Tangent, 4, bgfx::AttribType::Uint8, true, true);
} }
break; break;
} }
@ -828,6 +776,11 @@ int main(int _argc, const char* _argv[])
} }
triReorderElapsed += bx::getHPCounter(); triReorderElapsed += bx::getHPCounter();
if (hasTangent)
{
calcTangents(vertexData, numVertices, decl, indexData, numIndices);
}
write(&writer, vertexData, numVertices, decl, indexData, numIndices, material, primitives); write(&writer, vertexData, numVertices, decl, indexData, numIndices, material, primitives);
primitives.clear(); primitives.clear();
@ -875,58 +828,14 @@ int main(int _argc, const char* _argv[])
uv[1] = -uv[1]; uv[1] = -uv[1];
} }
switch (packUv) bgfx::vertexPack(uv, true, bgfx::Attrib::TexCoord0, decl, vertices);
{
default:
case 0:
{
float* texcoord0 = (float*)(vertices + texcoord0Offset);
memcpy(texcoord0, uv, 2*sizeof(float) );
}
break;
case 1:
{
uint32_t* texcoord0 = (uint32_t*)(vertices + texcoord0Offset);
*texcoord0 = packF2h(uv[0], uv[1]);
}
break;
}
} }
if (hasNormal) if (hasNormal)
{ {
switch (packNormal) float normal[4];
{ vec3Norm(normal, (float*)&normals[index.m_normal]);
default: bgfx::vertexPack(normal, true, bgfx::Attrib::Normal, decl, vertices);
case 0:
{
float* normal = (float*)(vertices + normalOffset);
vec3Norm(normal, (float*)&normals[index.m_normal]);
if (hasTangent)
{
float* tangent = (float*)(vertices + tangentOffset);
memset(tangent, 0, 3*sizeof(float) );
}
}
break;
case 1:
{
float normal[3];
vec3Norm(normal, (float*)&normals[index.m_normal]);
uint32_t* nxyz0 = (uint32_t*)(vertices + normalOffset);
*nxyz0 = packF4u(normal[0], normal[1], normal[2]);
if (hasTangent)
{
uint32_t* txyz0 = (uint32_t*)(vertices + tangentOffset);
*txyz0 = packF4u(0.0f);
}
}
break;
}
} }
vertices += stride; vertices += stride;
@ -965,6 +874,11 @@ int main(int _argc, const char* _argv[])
} }
triReorderElapsed += bx::getHPCounter(); triReorderElapsed += bx::getHPCounter();
if (hasTangent)
{
calcTangents(vertexData, numVertices, decl, indexData, numIndices);
}
write(&writer, vertexData, numVertices, decl, indexData, numIndices, material, primitives); write(&writer, vertexData, numVertices, decl, indexData, numIndices, material, primitives);
} }