diff options
author | Paul Lemire <paul.lemire@kdab.com> | 2020-08-18 16:33:32 +0200 |
---|---|---|
committer | Paul Lemire <paul.lemire@kdab.com> | 2020-08-26 12:53:06 +0200 |
commit | 607235b72918a416268b45772c6bbc2f86c32e9b (patch) | |
tree | ca2902c6d9612d20d2ad35a41aa591a55d1af4e1 | |
parent | 29281788884b69d7e7a86a17efbbe4c62c680e19 (diff) |
Handle mat4 as vertex attributes
This will be required for instance drawing were providing a per instance
matrix attribute is really convenient.
Change-Id: I8329d22c346f254942288129e06d59b80c54ebe3
Reviewed-by: Mike Krus <mike.krus@kdab.com>
-rw-r--r-- | src/plugins/renderers/rhi/renderer/renderer.cpp | 40 |
1 files changed, 22 insertions, 18 deletions
diff --git a/src/plugins/renderers/rhi/renderer/renderer.cpp b/src/plugins/renderers/rhi/renderer/renderer.cpp index 489e8aa02..fd8b5c1e9 100644 --- a/src/plugins/renderers/rhi/renderer/renderer.cpp +++ b/src/plugins/renderers/rhi/renderer/renderer.cpp @@ -834,7 +834,7 @@ std::optional<QRhiVertexInputAttribute::Format> rhiAttributeType(Attribute *attr return QRhiVertexInputAttribute::Float2; if (attr->vertexSize() == 3) return QRhiVertexInputAttribute::Float3; - if (attr->vertexSize() == 4) + if (attr->vertexSize() >= 4) return QRhiVertexInputAttribute::Float4; break; } @@ -1651,8 +1651,8 @@ bool Renderer::prepareGeometryInputBindings(const Geometry *geometry, const RHIS QVarLengthArray<QRhiVertexInputAttribute, 8> &rhiAttributes, QHash<int, int> &attributeNameToBinding) { + // shader requires no attributes if (shader->attributes().size() == 0) - // shader requires no attributes return true; // QRhiVertexInputBinding -> specifies the stride of an attribute, @@ -1676,6 +1676,12 @@ bool Renderer::prepareGeometryInputBindings(const Geometry *geometry, const RHIS Attribute *attrib = m_nodesManager->attributeManager()->lookupResource(attribute_id); if (attrib->attributeType() != QAttribute::VertexAttribute) continue; + const int location = locationForAttribute(attrib, shader); + // In case the shader doesn't use the attribute, we would get no + // location. This is not a failure, just that we provide more attributes + // than required. + if (location == -1) + continue; const bool isPerInstanceAttr = attrib->divisor() != 0; const QRhiVertexInputBinding::Classification classification = isPerInstanceAttr @@ -1702,21 +1708,16 @@ bool Renderer::prepareGeometryInputBindings(const Geometry *geometry, const RHIS }; uint byteStride = attrib->byteStride(); + const uint vertexTypeByteSize = getAttributeByteSize(attrib->vertexBaseType()); // in GL 0 means tighly packed, we therefore assume a tighly packed // attribute and compute the stride if that happens if (byteStride == 0) - byteStride = attrib->vertexSize() * getAttributeByteSize(attrib->vertexBaseType()); + byteStride = attrib->vertexSize() * vertexTypeByteSize; const BufferBinding binding = { attrib->bufferId(), byteStride, classification, isPerInstanceAttr ? attrib->divisor() : 1U }; - const int location = locationForAttribute(attrib, shader); - // In case the shader doesn't use the attribute, we would get no - // location. This is not a failure, just that we provide more attributes - // than required. - if (location == -1) - continue; const auto it = std::find_if(uniqueBindings.begin(), uniqueBindings.end(), [binding](const BufferBinding &a) { @@ -1738,19 +1739,22 @@ bool Renderer::prepareGeometryInputBindings(const Geometry *geometry, const RHIS return false; } - rhiAttributes.push_back({ bindingIndex, - location, - *attributeType, - attrib->byteOffset() }); + // Special Handling for Matrix as Vertex Attributes + // If an attribute has a size > 4 it can only be a matrix based type + // for which we will actually upload several attributes at contiguous + // locations + const uint elementsPerColumn = 4; + const int attributeSpan = std::ceil(float(attrib->vertexSize()) / elementsPerColumn); + for (int i = 0; i < attributeSpan; ++i) { + rhiAttributes.push_back({ bindingIndex, + location + i, + *attributeType, + attrib->byteOffset() + (i * elementsPerColumn * vertexTypeByteSize)}); + } attributeNameToBinding.insert(attrib->nameId(), bindingIndex); } - if (uniqueBindings.empty() || rhiAttributes.empty()) { - qCWarning(Backend) << "No bindings or no attributes where found"; - return false; - } - inputBindings.resize(uniqueBindings.size()); for (int i = 0, m = uniqueBindings.size(); i < m; ++i) { const BufferBinding binding = uniqueBindings.at(i); |