mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 04:44:11 +02:00
Merge pull request #5866 from ZappoMan/mergeQuadsAndTriangles
merge model part quads and triangles together to reduce the number of draw calls
This commit is contained in:
commit
483884196c
7 changed files with 46 additions and 86 deletions
|
@ -168,7 +168,7 @@ Item {
|
|||
color: root.fontColor;
|
||||
font.pixelSize: root.fontSize
|
||||
text: "Triangles: " + root.triangles +
|
||||
" / Quads: " + root.quads + " / Material Switches: " + root.materialSwitches
|
||||
" / Material Switches: " + root.materialSwitches
|
||||
}
|
||||
Text {
|
||||
color: root.fontColor;
|
||||
|
|
|
@ -337,7 +337,6 @@ void Stats::updateStats() {
|
|||
|
||||
void Stats::setRenderDetails(const RenderDetails& details) {
|
||||
STAT_UPDATE(triangles, details._trianglesRendered);
|
||||
STAT_UPDATE(quads, details._quadsRendered);
|
||||
STAT_UPDATE(materialSwitches, details._materialSwitches);
|
||||
if (_expanded) {
|
||||
STAT_UPDATE(meshOpaque, details._opaque._rendered);
|
||||
|
|
|
@ -829,24 +829,30 @@ public:
|
|||
std::vector<AttributeData> attributes;
|
||||
};
|
||||
|
||||
gpu::BufferPointer FBXMeshPart::getTrianglesForQuads() const {
|
||||
gpu::BufferPointer FBXMeshPart::getMergedTriangles() const {
|
||||
// if we've been asked for our triangulation of the original quads, but we don't yet have them
|
||||
// then create them now.
|
||||
if (!trianglesForQuadsAvailable) {
|
||||
trianglesForQuadsAvailable = true;
|
||||
if (!mergedTrianglesAvailable) {
|
||||
mergedTrianglesAvailable = true;
|
||||
|
||||
quadsAsTrianglesIndicesBuffer = std::make_shared<gpu::Buffer>();
|
||||
mergedTrianglesIndicesBuffer = std::make_shared<gpu::Buffer>();
|
||||
|
||||
// QVector<int> quadIndices; // original indices from the FBX mesh
|
||||
QVector<quint32> quadsAsTrianglesIndices; // triangle versions of quads converted when first needed
|
||||
QVector<quint32> mergedTrianglesIndices; // triangle versions of quads converted when first needed
|
||||
const int INDICES_PER_ORIGINAL_TRIANGLE = 3;
|
||||
const int INDICES_PER_ORIGINAL_QUAD = 4;
|
||||
const int INDICES_PER_TRIANGULATED_QUAD = 6;
|
||||
int numberOfQuads = quadIndices.size() / INDICES_PER_ORIGINAL_QUAD;
|
||||
|
||||
quadsAsTrianglesIndices.resize(numberOfQuads * INDICES_PER_TRIANGULATED_QUAD);
|
||||
int numberOfTriangles = triangleIndices.size() / INDICES_PER_ORIGINAL_TRIANGLE;
|
||||
int mergedNumberOfIndices = (numberOfQuads * INDICES_PER_TRIANGULATED_QUAD) + triangleIndices.size();
|
||||
|
||||
// resized our merged indices to be enough room for our triangulated quads and our original triangles
|
||||
mergedTrianglesIndices.resize(mergedNumberOfIndices);
|
||||
|
||||
int originalIndex = 0;
|
||||
int triangulatedIndex = 0;
|
||||
|
||||
// triangulate our quads
|
||||
for (int fromQuad = 0; fromQuad < numberOfQuads; fromQuad++) {
|
||||
int i0 = quadIndices[originalIndex + 0];
|
||||
int i1 = quadIndices[originalIndex + 1];
|
||||
|
@ -860,23 +866,38 @@ gpu::BufferPointer FBXMeshPart::getTrianglesForQuads() const {
|
|||
// Triangle tri1 = { v0, v1, v2 };
|
||||
// Triangle tri2 = { v2, v3, v0 };
|
||||
|
||||
quadsAsTrianglesIndices[triangulatedIndex + 0] = i0;
|
||||
quadsAsTrianglesIndices[triangulatedIndex + 1] = i1;
|
||||
quadsAsTrianglesIndices[triangulatedIndex + 2] = i3;
|
||||
mergedTrianglesIndices[triangulatedIndex + 0] = i0;
|
||||
mergedTrianglesIndices[triangulatedIndex + 1] = i1;
|
||||
mergedTrianglesIndices[triangulatedIndex + 2] = i3;
|
||||
|
||||
quadsAsTrianglesIndices[triangulatedIndex + 3] = i1;
|
||||
quadsAsTrianglesIndices[triangulatedIndex + 4] = i2;
|
||||
quadsAsTrianglesIndices[triangulatedIndex + 5] = i3;
|
||||
mergedTrianglesIndices[triangulatedIndex + 3] = i1;
|
||||
mergedTrianglesIndices[triangulatedIndex + 4] = i2;
|
||||
mergedTrianglesIndices[triangulatedIndex + 5] = i3;
|
||||
|
||||
originalIndex += INDICES_PER_ORIGINAL_QUAD;
|
||||
triangulatedIndex += INDICES_PER_TRIANGULATED_QUAD;
|
||||
}
|
||||
|
||||
trianglesForQuadsIndicesCount = INDICES_PER_TRIANGULATED_QUAD * numberOfQuads;
|
||||
quadsAsTrianglesIndicesBuffer->append(quadsAsTrianglesIndices.size() * sizeof(quint32), (gpu::Byte*)quadsAsTrianglesIndices.data());
|
||||
// add our original triangs
|
||||
originalIndex = 0;
|
||||
for (int fromTriangle = 0; fromTriangle < numberOfTriangles; fromTriangle++) {
|
||||
int i0 = triangleIndices[originalIndex + 0];
|
||||
int i1 = triangleIndices[originalIndex + 1];
|
||||
int i2 = triangleIndices[originalIndex + 2];
|
||||
|
||||
mergedTrianglesIndices[triangulatedIndex + 0] = i0;
|
||||
mergedTrianglesIndices[triangulatedIndex + 1] = i1;
|
||||
mergedTrianglesIndices[triangulatedIndex + 2] = i2;
|
||||
|
||||
originalIndex += INDICES_PER_ORIGINAL_TRIANGLE;
|
||||
triangulatedIndex += INDICES_PER_ORIGINAL_TRIANGLE;
|
||||
}
|
||||
|
||||
mergedTrianglesIndicesCount = mergedNumberOfIndices;
|
||||
mergedTrianglesIndicesBuffer->append(mergedNumberOfIndices * sizeof(quint32), (gpu::Byte*)mergedTrianglesIndices.data());
|
||||
|
||||
}
|
||||
return quadsAsTrianglesIndicesBuffer;
|
||||
return mergedTrianglesIndicesBuffer;
|
||||
}
|
||||
|
||||
void appendIndex(MeshData& data, QVector<int>& indices, int index) {
|
||||
|
|
|
@ -117,10 +117,10 @@ public:
|
|||
/// A single part of a mesh (with the same material).
|
||||
class FBXMeshPart {
|
||||
public:
|
||||
|
||||
|
||||
QVector<int> quadIndices; // original indices from the FBX mesh
|
||||
QVector<int> triangleIndices; // original indices from the FBX mesh
|
||||
mutable gpu::BufferPointer quadsAsTrianglesIndicesBuffer;
|
||||
mutable gpu::BufferPointer mergedTrianglesIndicesBuffer; // both the quads and the triangles merged into a single set of triangles
|
||||
|
||||
glm::vec3 diffuseColor;
|
||||
glm::vec3 specularColor;
|
||||
|
@ -136,10 +136,10 @@ public:
|
|||
|
||||
QString materialID;
|
||||
model::MaterialPointer _material;
|
||||
mutable bool trianglesForQuadsAvailable = false;
|
||||
mutable int trianglesForQuadsIndicesCount = 0;
|
||||
mutable bool mergedTrianglesAvailable = false;
|
||||
mutable int mergedTrianglesIndicesCount = 0;
|
||||
|
||||
gpu::BufferPointer getTrianglesForQuads() const;
|
||||
gpu::BufferPointer getMergedTriangles() const;
|
||||
};
|
||||
|
||||
/// A single mesh (with optional blendshapes) extracted from an FBX document.
|
||||
|
|
|
@ -75,7 +75,6 @@ Model::Model(RigPointer rig, QObject* parent) :
|
|||
_isVisible(true),
|
||||
_blendNumber(0),
|
||||
_appliedBlendNumber(0),
|
||||
_calculatedMeshPartOffsetValid(false),
|
||||
_calculatedMeshPartBoxesValid(false),
|
||||
_calculatedMeshBoxesValid(false),
|
||||
_calculatedMeshTrianglesValid(false),
|
||||
|
@ -601,25 +600,6 @@ bool Model::convexHullContains(glm::vec3 point) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void Model::recalculateMeshPartOffsets() {
|
||||
if (!_calculatedMeshPartOffsetValid) {
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
int numberOfMeshes = geometry.meshes.size();
|
||||
_calculatedMeshPartOffset.clear();
|
||||
for (int i = 0; i < numberOfMeshes; i++) {
|
||||
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||
qint64 partOffset = 0;
|
||||
for (int j = 0; j < mesh.parts.size(); j++) {
|
||||
const FBXMeshPart& part = mesh.parts.at(j);
|
||||
_calculatedMeshPartOffset[QPair<int,int>(i, j)] = partOffset;
|
||||
partOffset += part.quadIndices.size() * sizeof(int);
|
||||
partOffset += part.triangleIndices.size() * sizeof(int);
|
||||
|
||||
}
|
||||
}
|
||||
_calculatedMeshPartOffsetValid = true;
|
||||
}
|
||||
}
|
||||
// TODO: we seem to call this too often when things haven't actually changed... look into optimizing this
|
||||
// Any script might trigger findRayIntersectionAgainstSubMeshes (and maybe convexHullContains), so these
|
||||
// can occur multiple times. In addition, rendering does it's own ray picking in order to decide which
|
||||
|
@ -636,8 +616,6 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) {
|
|||
_calculatedMeshTriangles.clear();
|
||||
_calculatedMeshTriangles.resize(numberOfMeshes);
|
||||
_calculatedMeshPartBoxes.clear();
|
||||
_calculatedMeshPartOffset.clear();
|
||||
_calculatedMeshPartOffsetValid = false;
|
||||
for (int i = 0; i < numberOfMeshes; i++) {
|
||||
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||
Extents scaledMeshExtents = calculateScaledOffsetExtents(mesh.meshExtents);
|
||||
|
@ -646,7 +624,6 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) {
|
|||
|
||||
if (pickAgainstTriangles) {
|
||||
QVector<Triangle> thisMeshTriangles;
|
||||
qint64 partOffset = 0;
|
||||
for (int j = 0; j < mesh.parts.size(); j++) {
|
||||
const FBXMeshPart& part = mesh.parts.at(j);
|
||||
|
||||
|
@ -732,15 +709,9 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) {
|
|||
}
|
||||
}
|
||||
_calculatedMeshPartBoxes[QPair<int,int>(i, j)] = thisPartBounds;
|
||||
_calculatedMeshPartOffset[QPair<int,int>(i, j)] = partOffset;
|
||||
|
||||
partOffset += part.quadIndices.size() * sizeof(int);
|
||||
partOffset += part.triangleIndices.size() * sizeof(int);
|
||||
|
||||
}
|
||||
_calculatedMeshTriangles[i] = thisMeshTriangles;
|
||||
_calculatedMeshPartBoxesValid = true;
|
||||
_calculatedMeshPartOffsetValid = true;
|
||||
}
|
||||
}
|
||||
_calculatedMeshBoxesValid = true;
|
||||
|
@ -1480,12 +1451,6 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran
|
|||
return; // bail asap
|
||||
}
|
||||
|
||||
// We need to make sure we have valid offsets calculated before we can render
|
||||
if (!_calculatedMeshPartOffsetValid) {
|
||||
_mutex.lock();
|
||||
recalculateMeshPartOffsets();
|
||||
_mutex.unlock();
|
||||
}
|
||||
auto textureCache = DependencyManager::get<TextureCache>();
|
||||
|
||||
gpu::Batch& batch = *(args->_batch);
|
||||
|
@ -1703,32 +1668,12 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran
|
|||
}
|
||||
}
|
||||
|
||||
qint64 offset;
|
||||
{
|
||||
// FIXME_STUTTER: We should n't have any lock here
|
||||
_mutex.lock();
|
||||
offset = _calculatedMeshPartOffset[QPair<int,int>(meshIndex, partIndex)];
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
||||
if (part.quadIndices.size() > 0) {
|
||||
batch.setIndexBuffer(gpu::UINT32, part.getTrianglesForQuads(), 0);
|
||||
batch.drawIndexed(gpu::TRIANGLES, part.trianglesForQuadsIndicesCount, 0);
|
||||
|
||||
offset += part.quadIndices.size() * sizeof(int);
|
||||
batch.setIndexBuffer(gpu::UINT32, (networkMesh._indexBuffer), 0); // restore this in case there are triangles too
|
||||
}
|
||||
|
||||
if (part.triangleIndices.size() > 0) {
|
||||
batch.drawIndexed(gpu::TRIANGLES, part.triangleIndices.size(), offset);
|
||||
offset += part.triangleIndices.size() * sizeof(int);
|
||||
}
|
||||
batch.setIndexBuffer(gpu::UINT32, part.getMergedTriangles(), 0);
|
||||
batch.drawIndexed(gpu::TRIANGLES, part.mergedTrianglesIndicesCount, 0);
|
||||
|
||||
if (args) {
|
||||
const int INDICES_PER_TRIANGLE = 3;
|
||||
const int INDICES_PER_QUAD = 4;
|
||||
args->_details._trianglesRendered += part.triangleIndices.size() / INDICES_PER_TRIANGLE;
|
||||
args->_details._quadsRendered += part.quadIndices.size() / INDICES_PER_QUAD;
|
||||
args->_details._trianglesRendered += part.mergedTrianglesIndicesCount / INDICES_PER_TRIANGLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -352,9 +352,6 @@ private:
|
|||
};
|
||||
|
||||
QHash<QPair<int,int>, AABox> _calculatedMeshPartBoxes; // world coordinate AABoxes for all sub mesh part boxes
|
||||
QHash<QPair<int,int>, qint64> _calculatedMeshPartOffset;
|
||||
bool _calculatedMeshPartOffsetValid;
|
||||
|
||||
|
||||
bool _calculatedMeshPartBoxesValid;
|
||||
QVector<AABox> _calculatedMeshBoxes; // world coordinate AABoxes for all sub mesh boxes
|
||||
|
@ -365,7 +362,6 @@ private:
|
|||
QMutex _mutex;
|
||||
|
||||
void recalculateMeshBoxes(bool pickAgainstTriangles = false);
|
||||
void recalculateMeshPartOffsets();
|
||||
|
||||
void segregateMeshGroups(); // used to calculate our list of translucent vs opaque meshes
|
||||
|
||||
|
|
|
@ -43,7 +43,6 @@ public:
|
|||
|
||||
int _materialSwitches = 0;
|
||||
int _trianglesRendered = 0;
|
||||
int _quadsRendered = 0;
|
||||
|
||||
Item _opaque;
|
||||
Item _translucent;
|
||||
|
|
Loading…
Reference in a new issue