fix the bug for blend shape when more than one and clean the model rendering with the new stream and buffer gpu api

This commit is contained in:
Sam Gateau 2014-11-03 23:26:39 -08:00
parent ed067791f2
commit f413f93c62
5 changed files with 38 additions and 221 deletions

View file

@ -120,7 +120,7 @@ Resource::Size Resource::Sysmem::resize(Size size) {
Resource::Size Resource::Sysmem::setData( Size size, const Byte* bytes ) {
if (allocate(size) == size) {
if (bytes) {
if (size && bytes) {
memcpy( _data, bytes, _size );
_stamp++;
}
@ -129,7 +129,7 @@ Resource::Size Resource::Sysmem::setData( Size size, const Byte* bytes ) {
}
Resource::Size Resource::Sysmem::setSubData( Size offset, Size size, const Byte* bytes) {
if (((offset + size) <= getSize()) && bytes) {
if (size && ((offset + size) <= getSize()) && bytes) {
memcpy( _data + offset, bytes, size );
_stamp++;
return size;

View file

@ -743,7 +743,7 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) {
_geometry = geometry;
foreach (const FBXMesh& mesh, _geometry.meshes) {
NetworkMesh networkMesh = { QOpenGLBuffer(QOpenGLBuffer::IndexBuffer), QOpenGLBuffer(QOpenGLBuffer::VertexBuffer) };
NetworkMesh networkMesh;
int totalIndices = 0;
foreach (const FBXMeshPart& part, mesh.parts) {
@ -773,26 +773,9 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) {
totalIndices += (part.quadIndices.size() + part.triangleIndices.size());
}
/*
networkMesh.indexBuffer.create();
networkMesh.indexBuffer.bind();
networkMesh.indexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
networkMesh.indexBuffer.allocate(totalIndices * sizeof(int));
int offset = 0;
foreach (const FBXMeshPart& part, mesh.parts) {
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, part.quadIndices.size() * sizeof(int),
part.quadIndices.constData());
offset += part.quadIndices.size() * sizeof(int);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, part.triangleIndices.size() * sizeof(int),
part.triangleIndices.constData());
offset += part.triangleIndices.size() * sizeof(int);
}
networkMesh.indexBuffer.release();
*/
{
networkMesh._indexBuffer = gpu::BufferPtr(new gpu::Buffer());
//networkMesh._indexBuffer.bind();
//networkMesh._indexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
networkMesh._indexBuffer->resize(totalIndices * sizeof(int));
int offset = 0;
foreach(const FBXMeshPart& part, mesh.parts) {
@ -803,54 +786,8 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) {
(gpu::Resource::Byte*) part.triangleIndices.constData());
offset += part.triangleIndices.size() * sizeof(int);
}
// networkMesh.indexBuffer.release();
}
/* networkMesh.vertexBuffer.create();
networkMesh.vertexBuffer.bind();
networkMesh.vertexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
// if we don't need to do any blending, the positions/normals can be static
if (mesh.blendshapes.isEmpty()) {
int normalsOffset = mesh.vertices.size() * sizeof(glm::vec3);
int tangentsOffset = normalsOffset + mesh.normals.size() * sizeof(glm::vec3);
int colorsOffset = tangentsOffset + mesh.tangents.size() * sizeof(glm::vec3);
int texCoordsOffset = colorsOffset + mesh.colors.size() * sizeof(glm::vec3);
int clusterIndicesOffset = texCoordsOffset + mesh.texCoords.size() * sizeof(glm::vec2);
int clusterWeightsOffset = clusterIndicesOffset + mesh.clusterIndices.size() * sizeof(glm::vec4);
networkMesh.vertexBuffer.allocate(clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4));
networkMesh.vertexBuffer.write(0, mesh.vertices.constData(), mesh.vertices.size() * sizeof(glm::vec3));
networkMesh.vertexBuffer.write(normalsOffset, mesh.normals.constData(), mesh.normals.size() * sizeof(glm::vec3));
networkMesh.vertexBuffer.write(tangentsOffset, mesh.tangents.constData(),
mesh.tangents.size() * sizeof(glm::vec3));
networkMesh.vertexBuffer.write(colorsOffset, mesh.colors.constData(), mesh.colors.size() * sizeof(glm::vec3));
networkMesh.vertexBuffer.write(texCoordsOffset, mesh.texCoords.constData(),
mesh.texCoords.size() * sizeof(glm::vec2));
networkMesh.vertexBuffer.write(clusterIndicesOffset, mesh.clusterIndices.constData(),
mesh.clusterIndices.size() * sizeof(glm::vec4));
networkMesh.vertexBuffer.write(clusterWeightsOffset, mesh.clusterWeights.constData(),
mesh.clusterWeights.size() * sizeof(glm::vec4));
// otherwise, at least the cluster indices/weights can be static
} else {
int colorsOffset = mesh.tangents.size() * sizeof(glm::vec3);
int texCoordsOffset = colorsOffset + mesh.colors.size() * sizeof(glm::vec3);
int clusterIndicesOffset = texCoordsOffset + mesh.texCoords.size() * sizeof(glm::vec2);
int clusterWeightsOffset = clusterIndicesOffset + mesh.clusterIndices.size() * sizeof(glm::vec4);
networkMesh.vertexBuffer.allocate(clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4));
networkMesh.vertexBuffer.write(0, mesh.tangents.constData(), mesh.tangents.size() * sizeof(glm::vec3));
networkMesh.vertexBuffer.write(colorsOffset, mesh.colors.constData(), mesh.colors.size() * sizeof(glm::vec3));
networkMesh.vertexBuffer.write(texCoordsOffset, mesh.texCoords.constData(),
mesh.texCoords.size() * sizeof(glm::vec2));
networkMesh.vertexBuffer.write(clusterIndicesOffset, mesh.clusterIndices.constData(),
mesh.clusterIndices.size() * sizeof(glm::vec4));
networkMesh.vertexBuffer.write(clusterWeightsOffset, mesh.clusterWeights.constData(),
mesh.clusterWeights.size() * sizeof(glm::vec4));
}
networkMesh.vertexBuffer.release();
*/
{
networkMesh._vertexBuffer = gpu::BufferPtr(new gpu::Buffer());
// if we don't need to do any blending, the positions/normals can be static
@ -932,7 +869,7 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) {
}
}
_meshes.append(networkMesh);
}

View file

@ -155,9 +155,6 @@ public:
/// The state associated with a single mesh.
class NetworkMesh {
public:
QOpenGLBuffer indexBuffer;
QOpenGLBuffer vertexBuffer;
gpu::BufferPtr _indexBuffer;
gpu::BufferPtr _vertexBuffer;

View file

@ -405,32 +405,15 @@ bool Model::updateGeometry() {
MeshState state;
state.clusterMatrices.resize(mesh.clusters.size());
_meshStates.append(state);
QOpenGLBuffer buffer;
if (!mesh.blendshapes.isEmpty()) {
buffer.setUsagePattern(QOpenGLBuffer::DynamicDraw);
buffer.create();
buffer.bind();
buffer.allocate((mesh.vertices.size() + mesh.normals.size()) * sizeof(glm::vec3));
buffer.write(0, mesh.vertices.constData(), mesh.vertices.size() * sizeof(glm::vec3));
buffer.write(mesh.vertices.size() * sizeof(glm::vec3), mesh.normals.constData(),
mesh.normals.size() * sizeof(glm::vec3));
buffer.release();
}
_blendedVertexBuffers.append(buffer);
gpu::BufferPtr buffer2(new gpu::Buffer());
gpu::BufferPtr buffer(new gpu::Buffer());
if (!mesh.blendshapes.isEmpty()) {
//buffer.setUsagePattern(QOpenGLBuffer::DynamicDraw);
//buffer.create();
//buffer.bind();
buffer2->resize((mesh.vertices.size() + mesh.normals.size()) * sizeof(glm::vec3));
buffer2->setSubData(0, mesh.vertices.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.vertices.constData());
buffer2->setSubData(mesh.vertices.size() * sizeof(glm::vec3),
buffer->resize((mesh.vertices.size() + mesh.normals.size()) * sizeof(glm::vec3));
buffer->setSubData(0, mesh.vertices.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.vertices.constData());
buffer->setSubData(mesh.vertices.size() * sizeof(glm::vec3),
mesh.normals.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.normals.constData());
// buffer.release();
}
_blendedVertexBuffers2.push_back(buffer2);
_blendedVertexBuffers.push_back(buffer);
}
foreach (const FBXAttachment& attachment, fbxGeometry.attachments) {
Model* model = new Model(this);
@ -572,8 +555,6 @@ bool Model::render(float alpha, RenderMode mode, RenderArgs* args) {
// Let's introduce a gpu::Batch to capture all the calls to the graphics api
gpu::Batch batch;
// GLBATCH(glEnableClientState)(GL_VERTEX_ARRAY);
// GLBATCH(glEnableClientState)(GL_NORMAL_ARRAY);
GLBATCH(glDisable)(GL_COLOR_MATERIAL);
@ -688,6 +669,10 @@ bool Model::render(float alpha, RenderMode mode, RenderArgs* args) {
GLBATCH(glDisableClientState)(GL_NORMAL_ARRAY);
GLBATCH(glDisableClientState)(GL_VERTEX_ARRAY);
GLBATCH(glDisableClientState)(GL_TEXTURE_COORD_ARRAY);
GLBATCH(glDisableClientState)(GL_COLOR_ARRAY);
GLBATCH(glDisableVertexAttribArray)(gpu::StreamFormat::SLOT_TANGENT);
GLBATCH(glDisableVertexAttribArray)(gpu::StreamFormat::SLOT_SKIN_CLUSTER_INDEX);
GLBATCH(glDisableVertexAttribArray)(gpu::StreamFormat::SLOT_SKIN_CLUSTER_WEIGHT);
// bind with 0 to switch back to normal operation
GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, 0);
@ -1414,7 +1399,7 @@ bool Model::maybeStartBlender() {
void Model::setBlendedVertices(int blendNumber, const QWeakPointer<NetworkGeometry>& geometry,
const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& normals) {
if (_geometry != geometry || _blendedVertexBuffers.isEmpty() || blendNumber < _appliedBlendNumber) {
if (_geometry != geometry || _blendedVertexBuffers.empty() || blendNumber < _appliedBlendNumber) {
return;
}
_appliedBlendNumber = blendNumber;
@ -1425,18 +1410,11 @@ void Model::setBlendedVertices(int blendNumber, const QWeakPointer<NetworkGeomet
if (mesh.blendshapes.isEmpty()) {
continue;
}
QOpenGLBuffer& buffer = _blendedVertexBuffers[i];
buffer.bind();
buffer.write(0, vertices.constData() + index, mesh.vertices.size() * sizeof(glm::vec3));
buffer.write(mesh.vertices.size() * sizeof(glm::vec3), normals.constData() + index,
mesh.normals.size() * sizeof(glm::vec3));
buffer.release();
gpu::BufferPtr& buffer2 = _blendedVertexBuffers2[i];
//buffer.bind();
buffer2->setSubData(0, mesh.vertices.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) vertices.constData() + index);
buffer2->setSubData(mesh.vertices.size() * sizeof(glm::vec3),
mesh.normals.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) normals.constData() + index);
gpu::BufferPtr& buffer = _blendedVertexBuffers[i];
buffer->setSubData(0, mesh.vertices.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) vertices.constData() + index*sizeof(glm::vec3));
buffer->setSubData(mesh.vertices.size() * sizeof(glm::vec3),
mesh.normals.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) normals.constData() + index*sizeof(glm::vec3));
index += mesh.vertices.size();
}
@ -1462,7 +1440,6 @@ void Model::deleteGeometry() {
}
_attachments.clear();
_blendedVertexBuffers.clear();
_blendedVertexBuffers2.clear();
_jointStates.clear();
_meshStates.clear();
clearShapes();
@ -1822,11 +1799,8 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl
activeProgram->link();
}
GLBATCH(glUseProgram)(activeProgram->programId());
// activeProgram->setUniformValue(activeLocations->alphaThreshold, alphaThreshold);
GLBATCH(glUniform1f)(activeLocations->alphaThreshold, alphaThreshold);
// i is the "index" from the original networkMeshes QVector...
foreach (int i, list) {
@ -1842,9 +1816,6 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl
const NetworkMesh& networkMesh = networkMeshes.at(i);
const FBXMesh& mesh = geometry.meshes.at(i);
//const_cast<QOpenGLBuffer&>(networkMesh.indexBuffer).bind();
// GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, const_cast<QOpenGLBuffer&>(networkMesh.indexBuffer).bufferId());
// GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, gpu::GLBackend::getBufferID((*networkMesh._indexBuffer)));
batch.setIndexBuffer(gpu::Element::TYPE_UINT32, (networkMesh._indexBuffer), 0);
int vertexCount = mesh.vertices.size();
if (vertexCount == 0) {
@ -1878,12 +1849,7 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl
continue; // skip this mesh
}
}
//const_cast<QOpenGLBuffer&>(networkMesh.vertexBuffer).bind();
// GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, const_cast<QOpenGLBuffer&>(networkMesh.vertexBuffer).bufferId());
// if (!mesh.blendshapes.isEmpty()) {
// GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, gpu::GLBackend::getBufferID((*networkMesh._vertexBuffer)));
// }
GLBATCH(glPushMatrix)();
//Application::getInstance()->loadTranslatedViewMatrix(_translation);
GLBATCH(glLoadMatrixf)((const GLfloat*)&Application::getInstance()->getUntranslatedViewMatrix());
@ -1895,76 +1861,23 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl
if (state.clusterMatrices.size() > 1) {
GLBATCH(glUniformMatrix4fv)(skinLocations->clusterMatrices, state.clusterMatrices.size(), false,
(const float*)state.clusterMatrices.constData());
int offset = (mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3) +
mesh.texCoords.size() * sizeof(glm::vec2) +
(mesh.blendshapes.isEmpty() ? vertexCount * 2 * sizeof(glm::vec3) : 0);
//skinProgram->setAttributeBuffer(skinLocations->clusterIndices, GL_FLOAT, offset, 4);
/* GLBATCH(glVertexAttribPointer)(skinLocations->clusterIndices, 4, GL_FLOAT, GL_TRUE, 0,
reinterpret_cast<const void*>(offset));
*/ //skinProgram->setAttributeBuffer(skinLocations->clusterWeights, GL_FLOAT,
// offset + vertexCount * sizeof(glm::vec4), 4);
/* if (!mesh.blendshapes.isEmpty()) {
GLBATCH(glVertexAttribPointer)(skinLocations->clusterWeights, 4, GL_FLOAT, GL_TRUE, 0, (const void*) (offset + vertexCount * sizeof(glm::vec4)));
//skinProgram->enableAttributeArray(skinLocations->clusterIndices);
GLBATCH(glEnableVertexAttribArray)(skinLocations->clusterIndices);
//skinProgram->enableAttributeArray(skinLocations->clusterWeights);
GLBATCH(glEnableVertexAttribArray)(skinLocations->clusterWeights);
}*/
} else {
GLBATCH(glMultMatrixf)((const GLfloat*)&state.clusterMatrices[0]);
}
if (mesh.blendshapes.isEmpty()) {
/* if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) {
//activeProgram->setAttributeBuffer(activeLocations->tangent, GL_FLOAT, vertexCount * 2 * sizeof(glm::vec3), 3);
GLBATCH(glVertexAttribPointer)(activeLocations->tangent, 3, GL_FLOAT, GL_TRUE, 0, (const void*)(vertexCount * 2 * sizeof(glm::vec3)));
//activeProgram->enableAttributeArray(activeLocations->tangent);
GLBATCH(glEnableVertexAttribArray)(activeLocations->tangent);
}
GLBATCH(glColorPointer)(3, GL_FLOAT, 0, (void*)(vertexCount * 2 * sizeof(glm::vec3) +
mesh.tangents.size() * sizeof(glm::vec3)));
GLBATCH(glTexCoordPointer)(2, GL_FLOAT, 0, (void*)(vertexCount * 2 * sizeof(glm::vec3) +
(mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3)));
*/
} else {
/* if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) {
//activeProgram->setAttributeBuffer(activeLocations->tangent, GL_FLOAT, 0, 3);
GLBATCH(glVertexAttribPointer)(activeLocations->tangent, 3, GL_FLOAT, GL_TRUE, 0, 0);
//activeProgram->enableAttributeArray(activeLocations->tangent);
GLBATCH(glEnableVertexAttribArray)(activeLocations->tangent);
}
GLBATCH(glColorPointer)(3, GL_FLOAT, 0, (void*)(mesh.tangents.size() * sizeof(glm::vec3)));
GLBATCH(glTexCoordPointer)(2, GL_FLOAT, 0, (void*)((mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3)));
*/
// _blendedVertexBuffers[i].bind();
// GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, _blendedVertexBuffers[i].bufferId());
// GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, gpu::GLBackend::getBufferID(*_blendedVertexBuffers2[i]));
batch.setInputBuffer(0, _blendedVertexBuffers2[i], 0, 0);
batch.setInputBuffer(1, _blendedVertexBuffers2[i], vertexCount * sizeof(glm::vec3), 0);
}
if (!mesh.blendshapes.isEmpty()) {
// GLBATCH(glVertexPointer)(3, GL_FLOAT, 0, 0);
// GLBATCH(glNormalPointer)(GL_FLOAT, 0, (void*)(vertexCount * sizeof(glm::vec3)));
/*
if (!mesh.colors.isEmpty()) {
GLBATCH(glEnableClientState)(GL_COLOR_ARRAY);
} else {
GLBATCH(glColor4f)(1.0f, 1.0f, 1.0f, 1.0f);
}
if (!mesh.texCoords.isEmpty()) {
GLBATCH(glEnableClientState)(GL_TEXTURE_COORD_ARRAY);
}*/
batch.setInputFormat(networkMesh._vertexFormat);
batch.setInputStream(2, networkMesh._vertexStream);
}
else{
batch.setInputFormat(networkMesh._vertexFormat);
batch.setInputStream(0, networkMesh._vertexStream);
} else {
batch.setInputFormat(networkMesh._vertexFormat);
batch.setInputBuffer(0, _blendedVertexBuffers[i], 0, sizeof(glm::vec3));
batch.setInputBuffer(1, _blendedVertexBuffers[i], vertexCount * sizeof(glm::vec3), sizeof(glm::vec3));
batch.setInputStream(2, networkMesh._vertexStream);
}
if (mesh.colors.isEmpty()) {
GLBATCH(glColor4f)(1.0f, 1.0f, 1.0f, 1.0f);
}
qint64 offset = 0;
for (int j = 0; j < networkMesh.parts.size(); j++) {
@ -2032,24 +1945,12 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl
meshPartsRendered++;
if (part.quadIndices.size() > 0) {
/* if (!mesh.blendshapes.isEmpty()) {
GLBATCH(glDrawRangeElements)(GL_QUADS, 0, vertexCount - 1, part.quadIndices.size(), GL_UNSIGNED_INT, (void*)offset);
}
else {*/
batch.drawIndexed(gpu::PRIMITIVE_QUADS, part.quadIndices.size(), offset);
// }
offset += part.quadIndices.size() * sizeof(int);
batch.drawIndexed(gpu::PRIMITIVE_QUADS, part.quadIndices.size(), offset);
offset += part.quadIndices.size() * sizeof(int);
}
if (part.triangleIndices.size() > 0) {
/* if (!mesh.blendshapes.isEmpty()) {
GLBATCH(glDrawRangeElements)(GL_TRIANGLES, 0, vertexCount - 1, part.triangleIndices.size(),
GL_UNSIGNED_INT, (void*)offset);
} else {*/
batch.drawIndexed(gpu::PRIMITIVE_TRIANGLES, part.triangleIndices.size(), offset);
// }
batch.drawIndexed(gpu::PRIMITIVE_TRIANGLES, part.triangleIndices.size(), offset);
offset += part.triangleIndices.size() * sizeof(int);
}
@ -2060,39 +1961,23 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl
args->_quadsRendered += part.quadIndices.size() / INDICES_PER_QUAD;
}
}
/**
if (!mesh.colors.isEmpty()) {
GLBATCH(glDisableClientState)(GL_COLOR_ARRAY);
}
if (!mesh.texCoords.isEmpty()) {
GLBATCH(glDisableClientState)(GL_TEXTURE_COORD_ARRAY);
}
*/
if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) {
GLBATCH(glActiveTexture)(GL_TEXTURE1);
GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
GLBATCH(glActiveTexture)(GL_TEXTURE0);
// activeProgram->disableAttributeArray(activeLocations->tangent);
// GLBATCH(glDisableVertexAttribArray)(activeLocations->tangent);
}
if (specularTextureUnit) {
GLBATCH(glActiveTexture)(specularTextureUnit);
GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
GLBATCH(glActiveTexture)(GL_TEXTURE0);
}
if (state.clusterMatrices.size() > 1) {
// skinProgram->disableAttributeArray(skinLocations->clusterIndices);
// GLBATCH(glDisableVertexAttribArray)(skinLocations->clusterIndices);
// skinProgram->disableAttributeArray(skinLocations->clusterWeights);
// GLBATCH(glDisableVertexAttribArray)(skinLocations->clusterWeights);
}
GLBATCH(glPopMatrix)();
}
//activeProgram->release();
GLBATCH(glUseProgram)(0);
return meshPartsRendered;

View file

@ -281,10 +281,8 @@ private:
QVector<float> _blendshapeCoefficients;
QUrl _url;
QVector<QOpenGLBuffer> _blendedVertexBuffers;
gpu::Buffers _blendedVertexBuffers2;
gpu::Buffers _blendedVertexBuffers;
QVector<QVector<QSharedPointer<Texture> > > _dilatedTextures;