mirror of
https://github.com/lubosz/overte.git
synced 2025-04-10 20:43:39 +02:00
Interleaving the attributes and relying on just 3 input buffers
This commit is contained in:
parent
0fe13ea5ee
commit
e8d922a56c
5 changed files with 116 additions and 12 deletions
|
@ -585,13 +585,15 @@ void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) {
|
|||
|
||||
FBXMesh& fbxMesh = extractedMesh;
|
||||
graphics::MeshPointer mesh(new graphics::Mesh());
|
||||
bool blendShapes = !fbxMesh.blendshapes.empty();
|
||||
int numVerts = extractedMesh.vertices.size();
|
||||
|
||||
// Grab the vertices in a buffer
|
||||
auto vb = std::make_shared<gpu::Buffer>();
|
||||
vb->setData(extractedMesh.vertices.size() * sizeof(glm::vec3),
|
||||
(const gpu::Byte*) extractedMesh.vertices.data());
|
||||
gpu::BufferView vbv(vb, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ));
|
||||
mesh->setVertexBuffer(vbv);
|
||||
// mesh->setVertexBuffer(vbv);
|
||||
|
||||
if (!fbxMesh.normals.empty() && fbxMesh.tangents.empty()) {
|
||||
// Fill with a dummy value to force tangents to be present if there are normals
|
||||
|
@ -634,7 +636,10 @@ void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) {
|
|||
// Normals and tangents are interleaved
|
||||
const int normalsOffset = 0;
|
||||
const int tangentsOffset = normalsOffset + sizeof(NormalType);
|
||||
const int colorsOffset = normalsOffset + normalsSize + tangentsSize;
|
||||
const int totalNTSize = normalsOffset + normalsSize + tangentsSize;
|
||||
//const int colorsOffset = normalsOffset + normalsSize + tangentsSize;
|
||||
|
||||
const int colorsOffset = 0;
|
||||
const int texCoordsOffset = colorsOffset + colorsSize;
|
||||
const int texCoords1Offset = texCoordsOffset + texCoordsSize;
|
||||
const int clusterIndicesOffset = texCoords1Offset + texCoords1Size;
|
||||
|
@ -642,6 +647,10 @@ void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) {
|
|||
const int totalAttributeSize = clusterWeightsOffset + clusterWeightsSize;
|
||||
|
||||
// Copy all attribute data in a single attribute buffer
|
||||
|
||||
auto attribNTBuffer = std::make_shared<gpu::Buffer>();
|
||||
attribNTBuffer->resize(totalNTSize);
|
||||
|
||||
auto attribBuffer = std::make_shared<gpu::Buffer>();
|
||||
attribBuffer->resize(totalAttributeSize);
|
||||
|
||||
|
@ -665,9 +674,10 @@ void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) {
|
|||
normalsAndTangents.push_back(packedNormal);
|
||||
normalsAndTangents.push_back(packedTangent);
|
||||
}
|
||||
attribBuffer->setSubData(normalsOffset, normalsAndTangentsSize, (const gpu::Byte*) normalsAndTangents.data());
|
||||
attribNTBuffer->setSubData(normalsOffset, normalsAndTangentsSize, (const gpu::Byte*) normalsAndTangents.data());
|
||||
}
|
||||
|
||||
|
||||
if (colorsSize > 0) {
|
||||
#if FBX_PACK_COLORS
|
||||
std::vector<ColorType> colors;
|
||||
|
@ -723,50 +733,123 @@ void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) {
|
|||
}
|
||||
attribBuffer->setSubData(clusterWeightsOffset, clusterWeightsSize, (const gpu::Byte*) fbxMesh.clusterWeights.constData());
|
||||
|
||||
auto vf = std::make_shared<gpu::Stream::Format>();
|
||||
auto vbs = std::make_shared<gpu::BufferStream>();
|
||||
|
||||
gpu::Offset buf0Offset = 12;
|
||||
vf->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ));
|
||||
vbs->addBuffer(vb, 0, buf0Offset);
|
||||
|
||||
gpu::Offset buf1Offset = 0;
|
||||
if (normalsSize) {
|
||||
mesh->addAttribute(gpu::Stream::NORMAL,
|
||||
/* mesh->addAttribute(gpu::Stream::NORMAL,
|
||||
graphics::BufferView(attribBuffer, normalsOffset, normalsAndTangentsSize,
|
||||
normalsAndTangentsStride, FBX_NORMAL_ELEMENT));
|
||||
mesh->addAttribute(gpu::Stream::TANGENT,
|
||||
graphics::BufferView(attribBuffer, tangentsOffset, normalsAndTangentsSize,
|
||||
normalsAndTangentsStride, FBX_NORMAL_ELEMENT));
|
||||
*/
|
||||
vf->setAttribute(gpu::Stream::NORMAL, 1, FBX_NORMAL_ELEMENT, 0);
|
||||
vf->setAttribute(gpu::Stream::TANGENT, 1, FBX_NORMAL_ELEMENT, 4);
|
||||
buf1Offset = 8;
|
||||
vbs->addBuffer(attribNTBuffer, 0, buf1Offset);
|
||||
}
|
||||
|
||||
gpu::Offset buf2Offset = 0;
|
||||
if (colorsSize) {
|
||||
mesh->addAttribute(gpu::Stream::COLOR,
|
||||
/* mesh->addAttribute(gpu::Stream::COLOR,
|
||||
graphics::BufferView(attribBuffer, colorsOffset, colorsSize, FBX_COLOR_ELEMENT));
|
||||
*/
|
||||
vf->setAttribute(gpu::Stream::COLOR, 2, FBX_COLOR_ELEMENT, buf2Offset);
|
||||
buf2Offset += 4;
|
||||
}
|
||||
if (texCoordsSize) {
|
||||
mesh->addAttribute(gpu::Stream::TEXCOORD,
|
||||
/* mesh->addAttribute(gpu::Stream::TEXCOORD,
|
||||
graphics::BufferView( attribBuffer, texCoordsOffset, texCoordsSize,
|
||||
gpu::Element(gpu::VEC2, gpu::HALF, gpu::UV)));
|
||||
*/ vf->setAttribute(gpu::Stream::TEXCOORD, 2, gpu::Element(gpu::VEC2, gpu::HALF, gpu::UV), buf2Offset);
|
||||
buf2Offset += 4;
|
||||
}
|
||||
if (texCoords1Size) {
|
||||
mesh->addAttribute( gpu::Stream::TEXCOORD1,
|
||||
/* mesh->addAttribute( gpu::Stream::TEXCOORD1,
|
||||
graphics::BufferView(attribBuffer, texCoords1Offset, texCoords1Size,
|
||||
gpu::Element(gpu::VEC2, gpu::HALF, gpu::UV)));
|
||||
*/ vf->setAttribute(gpu::Stream::TEXCOORD1, 2, gpu::Element(gpu::VEC2, gpu::HALF, gpu::UV), buf2Offset);
|
||||
buf2Offset += 4;
|
||||
} else if (texCoordsSize) {
|
||||
mesh->addAttribute(gpu::Stream::TEXCOORD1,
|
||||
/* mesh->addAttribute(gpu::Stream::TEXCOORD1,
|
||||
graphics::BufferView(attribBuffer, texCoordsOffset, texCoordsSize,
|
||||
gpu::Element(gpu::VEC2, gpu::HALF, gpu::UV)));
|
||||
*/ vf->setAttribute(gpu::Stream::TEXCOORD1, 2, gpu::Element(gpu::VEC2, gpu::HALF, gpu::UV), buf2Offset - 4);
|
||||
}
|
||||
|
||||
if (clusterIndicesSize) {
|
||||
if (fbxMesh.clusters.size() < UINT8_MAX) {
|
||||
mesh->addAttribute(gpu::Stream::SKIN_CLUSTER_INDEX,
|
||||
/* mesh->addAttribute(gpu::Stream::SKIN_CLUSTER_INDEX,
|
||||
graphics::BufferView(attribBuffer, clusterIndicesOffset, clusterIndicesSize,
|
||||
gpu::Element(gpu::VEC4, gpu::UINT8, gpu::XYZW)));
|
||||
*/
|
||||
vf->setAttribute(gpu::Stream::SKIN_CLUSTER_INDEX, 2, gpu::Element(gpu::VEC4, gpu::UINT8, gpu::XYZW), buf2Offset);
|
||||
buf2Offset += 4;
|
||||
|
||||
} else {
|
||||
mesh->addAttribute(gpu::Stream::SKIN_CLUSTER_INDEX,
|
||||
/* mesh->addAttribute(gpu::Stream::SKIN_CLUSTER_INDEX,
|
||||
graphics::BufferView(attribBuffer, clusterIndicesOffset, clusterIndicesSize,
|
||||
gpu::Element(gpu::VEC4, gpu::UINT16, gpu::XYZW)));
|
||||
*/ vf->setAttribute(gpu::Stream::SKIN_CLUSTER_INDEX, 2, gpu::Element(gpu::VEC4, gpu::UINT16, gpu::XYZW), buf2Offset);
|
||||
buf2Offset += 8;
|
||||
}
|
||||
}
|
||||
if (clusterWeightsSize) {
|
||||
mesh->addAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT,
|
||||
/* mesh->addAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT,
|
||||
graphics::BufferView(attribBuffer, clusterWeightsOffset, clusterWeightsSize,
|
||||
gpu::Element(gpu::VEC4, gpu::NUINT16, gpu::XYZW)));
|
||||
*/ vf->setAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT, 2, gpu::Element(gpu::VEC4, gpu::NUINT16, gpu::XYZW), buf2Offset);
|
||||
buf2Offset += 8;
|
||||
}
|
||||
|
||||
{
|
||||
auto vColorOffset = 0;
|
||||
auto vColorSize = colorsSize / numVerts;
|
||||
|
||||
auto vTexcoord0Offset = vColorOffset + vColorSize;
|
||||
auto vTexcoord0Size = texCoordsSize / numVerts;
|
||||
|
||||
auto vTexcoord1Offset = vTexcoord0Offset + vTexcoord0Size;
|
||||
auto vTexcoord1Size = texCoords1Size / numVerts;
|
||||
|
||||
auto vClusterIndiceOffset = vTexcoord1Offset + vTexcoord1Size;
|
||||
auto vClusterIndiceSize = clusterIndicesSize / numVerts;
|
||||
|
||||
auto vClusterWeightOffset = vClusterIndiceOffset + vClusterIndiceSize;
|
||||
auto vClusterWeightSize = clusterWeightsSize / numVerts;
|
||||
|
||||
auto vStride = vClusterWeightOffset + vClusterWeightSize;
|
||||
//int vStride = buf2Offset;
|
||||
std::vector<gpu::Byte> dest;
|
||||
dest.resize(totalAttributeSize);
|
||||
auto vDest = dest.data();
|
||||
|
||||
auto source = attribBuffer->getData();
|
||||
|
||||
|
||||
for (int i = 0; i < numVerts; i++) {
|
||||
|
||||
if (vColorSize) memcpy(vDest + vColorOffset, source + colorsOffset + i * vColorSize, vColorSize);
|
||||
if (vTexcoord0Size) memcpy(vDest + vTexcoord0Offset, source + texCoordsOffset + i * vTexcoord0Size, vTexcoord0Size);
|
||||
if (vTexcoord1Size) memcpy(vDest + vTexcoord1Offset, source + texCoords1Offset + i * vTexcoord1Size, vTexcoord1Size);
|
||||
if (vClusterIndiceSize) memcpy(vDest + vClusterIndiceOffset, source + clusterIndicesOffset + i * vClusterIndiceSize, vClusterIndiceSize);
|
||||
if (vClusterWeightSize) memcpy(vDest + vClusterWeightOffset, source + clusterWeightsOffset + i * vClusterWeightSize, vClusterWeightSize);
|
||||
|
||||
vDest += vStride;
|
||||
}
|
||||
|
||||
attribBuffer->setData(totalAttributeSize, dest.data());
|
||||
|
||||
vbs->addBuffer(attribBuffer, 0, vStride);
|
||||
}
|
||||
|
||||
mesh->setVertexFormatAndStream(vf, vbs);
|
||||
|
||||
unsigned int totalIndices = 0;
|
||||
foreach(const FBXMeshPart& part, extractedMesh.parts) {
|
||||
|
|
|
@ -27,6 +27,8 @@ void GL45Backend::resetInputStage() {
|
|||
}
|
||||
|
||||
void GL45Backend::updateInput() {
|
||||
// PROFILE_RANGE(render_gpu, __FUNCTION__);
|
||||
|
||||
bool isStereoNow = isStereo();
|
||||
// track stereo state change potentially happening wihtout changing the input format
|
||||
// this is a rare case requesting to invalid the format
|
||||
|
@ -36,6 +38,7 @@ void GL45Backend::updateInput() {
|
|||
_input._lastUpdateStereoState = isStereoNow;
|
||||
|
||||
if (_input._invalidFormat) {
|
||||
PROFILE_RANGE(render_gpu, "bindInputFormat");
|
||||
InputStageState::ActivationCache newActivation;
|
||||
|
||||
// Assign the vertex format required
|
||||
|
@ -128,16 +131,22 @@ void GL45Backend::updateInput() {
|
|||
}
|
||||
|
||||
if (_input._invalidBuffers.any()) {
|
||||
// PROFILE_RANGE(render_gpu, "bindInputBuffers");
|
||||
auto vbo = _input._bufferVBOs.data();
|
||||
auto offset = _input._bufferOffsets.data();
|
||||
auto stride = _input._bufferStrides.data();
|
||||
|
||||
for (GLuint buffer = 0; buffer < _input._buffers.size(); buffer++, vbo++, offset++, stride++) {
|
||||
int numSet = 0;
|
||||
auto numBuffers = _input._buffers.size();
|
||||
for (GLuint buffer = 0; buffer < numBuffers; buffer++, vbo++, offset++, stride++) {
|
||||
if (_input._invalidBuffers.test(buffer)) {
|
||||
glBindVertexBuffer(buffer, (*vbo), (*offset), (GLsizei)(*stride));
|
||||
numSet++;
|
||||
}
|
||||
}
|
||||
|
||||
PROFILE_COUNTER_IF_CHANGED(render_gpu, "numVBSbound", int, numSet);
|
||||
|
||||
_input._invalidBuffers.reset();
|
||||
(void)CHECK_GL_ERROR();
|
||||
}
|
||||
|
|
|
@ -152,6 +152,8 @@ public:
|
|||
|
||||
BufferStream makeRangedStream(uint32 offset, uint32 count = -1) const;
|
||||
|
||||
BufferStream& operator = (const BufferStream& src) = default;
|
||||
|
||||
protected:
|
||||
Buffers _buffers;
|
||||
Offsets _offsets;
|
||||
|
|
|
@ -32,6 +32,13 @@ Mesh::Mesh(const Mesh& mesh) :
|
|||
Mesh::~Mesh() {
|
||||
}
|
||||
|
||||
void Mesh::setVertexFormatAndStream(const gpu::Stream::FormatPointer& vf, const gpu::BufferStreamPointer& vbs) {
|
||||
_vertexFormat = vf;
|
||||
_vertexStream = (*vbs);
|
||||
|
||||
_vertexBuffer = BufferView(vbs->getBuffers()[0], vbs->getOffsets()[0], vbs->getBuffers()[0]->getSize(), vbs->getStrides()[0], gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ));
|
||||
}
|
||||
|
||||
void Mesh::setVertexBuffer(const BufferView& buffer) {
|
||||
_vertexBuffer = buffer;
|
||||
evalVertexFormat();
|
||||
|
|
|
@ -59,6 +59,9 @@ public:
|
|||
void removeAttribute(Slot slot);
|
||||
const BufferView getAttributeBuffer(int attrib) const;
|
||||
|
||||
// Force vertex stream and Vertex format
|
||||
void setVertexFormatAndStream(const gpu::Stream::FormatPointer& vf, const gpu::BufferStreamPointer& vbs);
|
||||
|
||||
// Stream format
|
||||
const gpu::Stream::FormatPointer getVertexFormat() const { return _vertexFormat; }
|
||||
|
||||
|
|
Loading…
Reference in a new issue