diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp index 68fe38fc72..13c21d89e7 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp @@ -274,8 +274,9 @@ void GLBackend::renderPassDraw(const Batch& batch) { case Batch::COMMAND_drawIndexedInstanced: case Batch::COMMAND_multiDrawIndirect: case Batch::COMMAND_multiDrawIndexedIndirect: { +#ifdef GPU_BATCH_DETAILED_TRACING PROFILE_RANGE(render_gpu_gl_detail, "drawcall"); - +#endif // updates for draw calls ++_currentDraw; updateInput(); diff --git a/libraries/render-utils/src/Blendshape.slh b/libraries/render-utils/src/Blendshape.slh index 2dfb0c1540..344964173c 100644 --- a/libraries/render-utils/src/Blendshape.slh +++ b/libraries/render-utils/src/Blendshape.slh @@ -10,6 +10,10 @@ <@func declareBlendshape(USE_NORMAL, USE_TANGENT)@> +struct PackedBlendshapeOffset { + ivec4 packedPosNorTan; +}; + struct BlendshapeOffset { vec4 position; vec4 normal; @@ -32,10 +36,21 @@ BlendshapeOffset getBlendshapeOffset(int i) { } #else layout(std140, binding=0) buffer blendshapeOffsetsBuffer { - BlendshapeOffset _blendshapeOffsets[]; + ivec4 _blendshapeOffsets[]; + // BlendshapeOffset _blendshapeOffsets[]; }; BlendshapeOffset getBlendshapeOffset(int i) { - return _blendshapeOffsets[i]; + // return _blendshapeOffsets[i]; + + + ivec4 elem_packed = _blendshapeOffsets[i]; + + BlendshapeOffset unpacked; + unpacked.position = vec4(unpackHalf2x16(uint(elem_packed.x)), unpackHalf2x16(uint(elem_packed.y))); + unpacked.normal = vec4(0.0); + unpacked.tangent = vec4(0.0); + + return unpacked; } #endif diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index c15f3bf2c1..8c1ad8a2db 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1632,6 +1632,7 @@ Blender::Blender(ModelPointer model, int blendNumber, const Geometry::WeakPointe _blendshapeCoefficients(blendshapeCoefficients) { } + void Blender::run() { QVector blendshapeOffsets; if (_model && _model->isLoaded()) { @@ -1648,6 +1649,8 @@ void Blender::run() { blendshapeOffsets += modelMeshBlendshapeOffsets->second; BlendshapeOffset* meshBlendshapeOffsets = blendshapeOffsets.data() + offset; offset += modelMeshBlendshapeOffsets->second.size(); + std::vector unpackedBlendshapeOffsets(modelMeshBlendshapeOffsets->second.size()); + 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); @@ -1655,12 +1658,25 @@ void Blender::run() { if (vertexCoefficient < EPSILON) { continue; } + float normalCoefficient = vertexCoefficient * NORMAL_COEFFICIENT_SCALE; const FBXBlendshape& blendshape = mesh.blendshapes.at(i); + bool doTangent = (mesh.tangents.size()) && (blendshape.tangents.size()); + tbb::parallel_for(tbb::blocked_range(0, blendshape.indices.size()), [&](const tbb::blocked_range& range) { for (auto j = range.begin(); j < range.end(); j++) { int index = blendshape.indices.at(j); - auto& currentBlendshapeOffset = meshBlendshapeOffsets[index]; + +#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); @@ -1669,9 +1685,28 @@ void Blender::run() { currentBlendshapeOffset.tangentOffsetAndSpare += glm::vec4(blendshape.tangents.at(j) * normalCoefficient, 0.0f); } } +#endif } }); } + +#ifdef PACKED_BLENDSHAPE_OFFSET + + auto unpacked = unpackedBlendshapeOffsets.data(); + auto packed = meshBlendshapeOffsets; + + for (int i = 0; i < unpackedBlendshapeOffsets.size(); i++) { + auto pposXY = glm::packHalf2x16(glm::vec2(unpacked->positionOffsetAndSpare)); + auto pposZ = glm::packHalf2x16(glm::vec2(unpacked->positionOffsetAndSpare.z, 0.0f)); + auto pnor = glm::packSnorm3x10_1x2(glm::vec4(unpacked->normalOffsetAndSpare, 0.0f)); + auto ptan = glm::packSnorm3x10_1x2(glm::vec4(unpacked->tangentOffsetAndSpare, 0.0f)); + (*packed).packedPosNorTan = glm::uvec4(pposXY, pposZ, pnor, ptan); + + unpacked++; + packed++; + } +#endif + } } // post the result to the ModelBlender, which will dispatch to the model if still alive diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 45171a0c31..98451a7620 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -75,11 +75,30 @@ struct SortedTriangleSet { int subMeshIndex; }; -struct BlendshapeOffset { + + +#define PACKED_BLENDSHAPE_OFFSET 1 +#ifdef PACKED_BLENDSHAPE_OFFSET +struct BlendshapeOffsetPacked { + glm::ivec4 packedPosNorTan; +}; + +struct BlendshapeOffsetUnpacked { + glm::vec3 positionOffsetAndSpare; + glm::vec3 normalOffsetAndSpare; + glm::vec3 tangentOffsetAndSpare; +}; + +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, public scriptable::ModelProvider {