trying and failing andad trying and rince and repeat

This commit is contained in:
sam gateau 2018-10-01 17:45:16 -07:00
parent c12115bfda
commit 392e2ff535
4 changed files with 38 additions and 79 deletions

View file

@ -585,7 +585,6 @@ void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) {
FBXMesh& fbxMesh = extractedMesh;
graphics::MeshPointer mesh(new graphics::Mesh());
bool hasBlendShapes = !fbxMesh.blendshapes.empty();
int numVerts = extractedMesh.vertices.size();
if (!fbxMesh.normals.empty() && fbxMesh.tangents.empty()) {
@ -761,33 +760,7 @@ void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) {
bool interleavePositions = true;
bool interleaveNormalsTangents = true;
// TODO: We are using the same vertex format layout for all meshes because this is more efficient
// This work is going into rc73 release which is meant to be used for the SPot500 event and we are picking the format
// that works best for blendshaped and skinned meshes aka the avatars.
// We will improve this technique in a hot fix to 73.
hasBlendShapes = false;
// If has blend shapes allocate and assign buffers for pos and tangents now
if (hasBlendShapes) {
auto posBuffer = std::make_shared<gpu::Buffer>();
posBuffer->setData(positionsSize, (const gpu::Byte*) vertBuffer->getData() + positionsOffset);
vertexBufferStream->addBuffer(posBuffer, 0, positionElement.getSize());
auto normalsAndTangentsBuffer = std::make_shared<gpu::Buffer>();
normalsAndTangentsBuffer->setData(normalsAndTangentsSize, (const gpu::Byte*) vertBuffer->getData() + normalsAndTangentsOffset);
vertexBufferStream->addBuffer(normalsAndTangentsBuffer, 0, normalsAndTangentsStride);
// update channels and attribBuffer size accordingly
interleavePositions = false;
interleaveNormalsTangents = false;
tangentChannel = 1;
attribChannel = 2;
totalAttribBufferSize = totalVertsSize - positionsSize - normalsAndTangentsSize;
}
// Define the vertex format, compute the offset for each attributes as we append them to the vertex format
// Define the vertex format, compute the offset for each attributes as we append them to the vertex format
gpu::Offset bufOffset = 0;
if (positionsSize) {
vertexFormat->setAttribute(gpu::Stream::POSITION, posChannel, positionElement, bufOffset);

View file

@ -26,52 +26,53 @@ struct BlendshapeOffset {
const float oneOver511 = 1.0 / 511.0;
vec3 unpackSnorm3x10_1x2(int packedX10Y10Z10A2) {
vec4 my_unpacked = vec4(
clamp( float( (packedX10Y10Z10A2 & 0x000003FF) - 511 ) / 511.0, -1.0, 1.0),
clamp( float( ((packedX10Y10Z10A2 >> 10) & 0x000003FF) - 511 ) / 511.0, -1.0, 1.0),
clamp( float( ((packedX10Y10Z10A2 >> 20) & 0x000003FF) - 511 ) / 511.0, -1.0, 1.0),
0.0//clamp( float( int((packedX10Y10Z10A2 >> 30) & 0x00000003) - 1 ), -1.0, 1.0)
vec3 unpackSnorm3x10_1x2(int packed) {
vec4 _unpacked = vec4(
clamp( float( bitfieldExtract(packed, 0, 10)) * oneOver511, -1.0, 1.0),
clamp( float( bitfieldExtract(packed, 10, 10)) * oneOver511, -1.0, 1.0),
clamp( float( bitfieldExtract(packed, 20, 10)) * oneOver511, -1.0, 1.0),
0.0
);
return my_unpacked.xyz;
return _unpacked.xyz;
}
#if defined(GPU_GL410)
layout(binding=0) uniform samplerBuffer blendshapeOffsetsBuffer;
vec2 gpu_unpackHalf2x16(uint packed) {
return unpackHalf2x16(packed);
}
BlendshapeOffset getBlendshapeOffset(int i) {
vec4 fetched = texelFetch(blendshapeOffsetsBuffer, i);
ivec4 elem_packed = ivec4(floatBitsToUint(fetched.x), floatBitsToUint(fetched.y), floatBitsToUint(fetched.z), floatBitsToUint(fetched.w));
uvec4 elem_packed = uvec4(floatBitsToUint(fetched.x), floatBitsToUint(fetched.y), floatBitsToUint(fetched.z), floatBitsToUint(fetched.w));
BlendshapeOffset unpacked;
vec2 pZnZ = unpackHalf2x16(uint(elem_packed.y));
unpacked.position = vec3(unpackHalf2x16(uint(elem_packed.x)), pZnZ.x);
unpacked.position = vec3(gpu_unpackHalf2x16((elem_packed.x)), gpu_unpackHalf2x16(uint(elem_packed.y)).x);
<@if USE_NORMAL@>
unpacked.normal = vec3(unpackHalf2x16(uint(elem_packed.z)), pZnZ.y);
//unpacked.normal = unpackSnorm3x10_1x2((elem_packed.z)).xyz;
unpacked.normal = unpackSnorm3x10_1x2(int(elem_packed.z)).xyz;
<@endif@>
<@if USE_TANGENT@>
unpacked.tangent = unpackSnorm3x10_1x2((elem_packed.w)).xyz;
unpacked.tangent = unpackSnorm3x10_1x2(int(elem_packed.w)).xyz;
<@endif@>
return unpacked;
}
#else
layout(std140, binding=0) buffer blendshapeOffsetsBuffer {
ivec4 _packedBlendshapeOffsets[];
uvec4 _packedBlendshapeOffsets[];
};
BlendshapeOffset getBlendshapeOffset(int i) {
ivec4 elem_packed = _packedBlendshapeOffsets[i];
uvec4 elem_packed = _packedBlendshapeOffsets[i];
BlendshapeOffset unpacked;
vec2 pZnZ = unpackHalf2x16(uint(elem_packed.y));
unpacked.position = vec3(unpackHalf2x16(uint(elem_packed.x)), pZnZ.x);
unpacked.position = vec3(unpackHalf2x16((elem_packed.x)), unpackHalf2x16(uint(elem_packed.y)).x);
<@if USE_NORMAL@>
unpacked.normal = vec3(unpackHalf2x16(uint(elem_packed.z)), pZnZ.y);
//unpacked.normal = unpackSnorm3x10_1x2((elem_packed.z)).xyz;
unpacked.normal = unpackSnorm3x10_1x2(int(elem_packed.z)).xyz;
<@endif@>
<@if USE_TANGENT@>
unpacked.tangent = unpackSnorm3x10_1x2((elem_packed.w)).xyz;
unpacked.tangent = unpackSnorm3x10_1x2(int(elem_packed.w)).xyz;
<@endif@>
return unpacked;
@ -92,7 +93,7 @@ void evalBlendshape(int i, vec4 inPosition, out vec4 position
normal = normalize(inNormal + blendshapeOffset.normal.xyz);
<@endif@>
<@if USE_TANGENT@>
tangent = normalize(inTangent /*+ blendshapeOffset.tangent.xyz*/);
tangent = normalize(inTangent + blendshapeOffset.tangent.xyz);
<@endif@>
}

View file

@ -1633,6 +1633,8 @@ Blender::Blender(ModelPointer model, int blendNumber, const Geometry::WeakPointe
}
//#define DEBUG_PACKED_BLENDSHAPE_OFFSET 1
void Blender::run() {
QVector<BlendshapeOffset> blendshapeOffsets;
if (_model && _model->isLoaded()) {
@ -1651,8 +1653,7 @@ void Blender::run() {
offset += modelMeshBlendshapeOffsets->second.size();
std::vector<BlendshapeOffsetUnpacked> unpackedBlendshapeOffsets(modelMeshBlendshapeOffsets->second.size());
// const float NORMAL_COEFFICIENT_SCALE = 0.01f;
const float NORMAL_COEFFICIENT_SCALE = 1.0f;
const float NORMAL_COEFFICIENT_SCALE = 0.01f;
for (int i = 0, n = qMin(_blendshapeCoefficients.size(), mesh.blendshapes.size()); i < n; i++) {
float vertexCoefficient = _blendshapeCoefficients.at(i);
const float EPSILON = 0.0001f;
@ -1668,38 +1669,37 @@ void Blender::run() {
for (auto j = range.begin(); j < range.end(); j++) {
int index = blendshape.indices.at(j);
#ifdef PACKED_BLENDSHAPE_OFFSET
auto& currentBlendshapeOffset = unpackedBlendshapeOffsets[index];
currentBlendshapeOffset.positionOffsetAndSpare += blendshape.vertices.at(j) * vertexCoefficient;
currentBlendshapeOffset.normalOffsetAndSpare += blendshape.normals.at(j) * normalCoefficient;
if (doTangent) {
currentBlendshapeOffset.tangentOffsetAndSpare += blendshape.tangents.at(j) * normalCoefficient;
}
#else
auto& currentBlendshapeOffset = blendshapeOffsets[index];
currentBlendshapeOffset.positionOffsetAndSpare += glm::vec4(blendshape.vertices.at(j) * vertexCoefficient, 0.0f);
currentBlendshapeOffset.normalOffsetAndSpare += glm::vec4(blendshape.normals.at(j) * normalCoefficient, 0.0f);
if (index < mesh.tangents.size()) {
if ((int)j < blendshape.tangents.size()) {
currentBlendshapeOffset.tangentOffsetAndSpare += glm::vec4(blendshape.tangents.at(j) * normalCoefficient, 0.0f);
currentBlendshapeOffset.tangentOffsetAndSpare += blendshape.tangents.at(j) * normalCoefficient;
}
}
#ifdef DEBUG_PACKED_BLENDSHAPE_OFFSET
if (glm::any(glm::greaterThan(glm::abs(currentBlendshapeOffset.normalOffsetAndSpare), glm::vec3(1.0f)))) {
currentBlendshapeOffset.normalOffsetAndSpare = glm::clamp(currentBlendshapeOffset.normalOffsetAndSpare, glm::vec3(-1.0f), glm::vec3(1.0f));
}
if (glm::any(glm::greaterThan(glm::abs(currentBlendshapeOffset.tangentOffsetAndSpare), glm::vec3(1.0f)))) {
currentBlendshapeOffset.tangentOffsetAndSpare = glm::clamp(currentBlendshapeOffset.tangentOffsetAndSpare, glm::vec3(-1.0f), glm::vec3(1.0f));
}
#endif
}
});
}
#ifdef PACKED_BLENDSHAPE_OFFSET
// Blendshape offsets are generrated, now let's pack it on its way to gpu
tbb::parallel_for(tbb::blocked_range<int>(0, (int) unpackedBlendshapeOffsets.size()), [&](const tbb::blocked_range<int>& range) {
auto unpacked = unpackedBlendshapeOffsets.data() + range.begin();
auto packed = meshBlendshapeOffsets + range.begin();
for (auto j = range.begin(); j < range.end(); j++) {
(*packed).packedPosNorTan = glm::uvec4(
glm::packHalf2x16(glm::vec2(unpacked->positionOffsetAndSpare)),
glm::packHalf2x16(glm::vec2(unpacked->positionOffsetAndSpare.z, unpacked->normalOffsetAndSpare.z)),
glm::packHalf2x16(glm::vec2(unpacked->normalOffsetAndSpare)),
glm::packHalf2x16(glm::vec2(unpacked->positionOffsetAndSpare.z, 0.0f)),
glm::packSnorm3x10_1x2(glm::vec4(unpacked->normalOffsetAndSpare, 0.0f)),
glm::packSnorm3x10_1x2(glm::vec4(unpacked->tangentOffsetAndSpare, 0.0f))
);
@ -1707,8 +1707,6 @@ void Blender::run() {
packed++;
}
});
#endif
}
}
// post the result to the ModelBlender, which will dispatch to the model if still alive

View file

@ -75,10 +75,6 @@ struct SortedTriangleSet {
int subMeshIndex;
};
#define PACKED_BLENDSHAPE_OFFSET 1
#ifdef PACKED_BLENDSHAPE_OFFSET
struct BlendshapeOffsetPacked {
glm::uvec4 packedPosNorTan;
};
@ -90,15 +86,6 @@ struct BlendshapeOffsetUnpacked {
};
using BlendshapeOffset = BlendshapeOffsetPacked;
#else
struct BlendshapeOffsetUnpacked {
glm::vec4 positionOffsetAndSpare;
glm::vec4 normalOffsetAndSpare;
glm::vec4 tangentOffsetAndSpare;
};
using BlendshapeOffset = BlendshapeOffsetUnpacked;
#endif
/// A generic 3D model displaying geometry loaded from a URL.
class Model : public QObject, public std::enable_shared_from_this<Model>, public scriptable::ModelProvider {