From 56b4d58f181d54a8f430df5fc63070082de5e0ec Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 15 Oct 2014 17:08:47 -0700 Subject: [PATCH] implement mesh groups and pull out shader programs in renderMeshes() to outside the loop based on group --- interface/src/renderer/Model.cpp | 289 ++++++++++++++++++++++++------- interface/src/renderer/Model.h | 28 ++- 2 files changed, 245 insertions(+), 72 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 9587d34dc1..72a6ab7afe 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -47,7 +47,7 @@ Model::Model(QObject* parent) : _blendNumber(0), _appliedBlendNumber(0), _calculatedMeshBoxesValid(false), - _translucentMeshesKnown(false) { + _meshesGroupsKnown(false) { // we may have been created in the network thread, but we live in the main thread moveToThread(Application::getInstance()->thread()); @@ -273,7 +273,7 @@ void Model::reset() { _jointStates[i].setRotationInConstrainedFrame(geometry.joints.at(i).rotation, 0.0f); } - _translucentMeshesKnown = false; + _meshesGroupsKnown = false; } bool Model::updateGeometry() { @@ -323,6 +323,7 @@ bool Model::updateGeometry() { deleteGeometry(); _dilatedTextures.clear(); _geometry = geometry; + _meshesGroupsKnown = false; setJointStates(newJointStates); needToRebuild = true; } else if (_jointStates.isEmpty()) { @@ -425,8 +426,8 @@ bool Model::render(float alpha, RenderMode mode, RenderArgs* args) { } } - if (!_translucentMeshesKnown) { - calculateTranslucentMeshes(); + if (!_meshesGroupsKnown) { + segregateMeshGroups(); } glEnableClientState(GL_VERTEX_ARRAY); @@ -458,11 +459,30 @@ bool Model::render(float alpha, RenderMode mode, RenderArgs* args) { mode == DEFAULT_RENDER_MODE); const float DEFAULT_ALPHA_THRESHOLD = 0.5f; - int opaqueMeshPartsRendered = renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, args); + + //renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, book isSkinned, args); + int opaqueMeshPartsRendered = 0; + opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, args); + opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args); + opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, args); + opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, args); + opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args); + opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); + opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args); + opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); // render translucent meshes afterwards Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true); - int translucentMeshPartsRendered = renderMeshes(mode, true, 0.75f, args); + int translucentMeshPartsRendered = 0; + const float MOSTLY_OPAQUE_THRESHOLD = 0.75f; + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); glDisable(GL_ALPHA_TEST); glEnable(GL_BLEND); @@ -472,7 +492,15 @@ bool Model::render(float alpha, RenderMode mode, RenderArgs* args) { Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true); if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { - translucentMeshPartsRendered += renderMeshes(mode, true, 0.0f, args); + const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f; + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); } glDepthMask(true); @@ -1219,6 +1247,7 @@ void Model::applyNextGeometry() { // we retain a reference to the base geometry so that its reference count doesn't fall to zero _baseGeometry = _nextBaseGeometry; _geometry = _nextGeometry; + _meshesGroupsKnown = false; _nextBaseGeometry.reset(); _nextGeometry.reset(); } @@ -1250,37 +1279,210 @@ void Model::deleteGeometry() { _blendedBlendshapeCoefficients.clear(); } -void Model::calculateTranslucentMeshes() { - _translucentMeshes.clear(); - _opaqueMeshes.clear(); +void Model::segregateMeshGroups() { + _meshesTranslucentTangents.clear(); + _meshesTranslucent.clear(); + _meshesTranslucentTangentsSpecular.clear(); + _meshesTranslucentSpecular.clear(); + + _meshesTranslucentTangentsSkinned.clear(); + _meshesTranslucentSkinned.clear(); + _meshesTranslucentTangentsSpecularSkinned.clear(); + _meshesTranslucentSpecularSkinned.clear(); + + _meshesOpaqueTangents.clear(); + _meshesOpaque.clear(); + _meshesOpaqueTangentsSpecular.clear(); + _meshesOpaqueSpecular.clear(); + + _meshesOpaqueTangentsSkinned.clear(); + _meshesOpaqueSkinned.clear(); + _meshesOpaqueTangentsSpecularSkinned.clear(); + _meshesOpaqueSpecularSkinned.clear(); + const FBXGeometry& geometry = _geometry->getFBXGeometry(); const QVector& networkMeshes = _geometry->getMeshes(); for (int i = 0; i < networkMeshes.size(); i++) { const NetworkMesh& networkMesh = networkMeshes.at(i); const FBXMesh& mesh = geometry.meshes.at(i); + const MeshState& state = _meshStates.at(i); bool translucentMesh = networkMesh.getTranslucentPartCount(mesh) == networkMesh.parts.size(); - if (translucentMesh) { - _translucentMeshes.append(i); + bool hasTangents = !mesh.tangents.isEmpty(); + bool hasSpecular = mesh.hasSpecularTexture(); + bool isSkinned = state.clusterMatrices.size() > 1; + + if (translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { + + _meshesTranslucent.append(i); + + } else if (translucentMesh && hasTangents && !hasSpecular && !isSkinned) { + + _meshesTranslucentTangents.append(i); + + } else if (translucentMesh && hasTangents && hasSpecular && !isSkinned) { + + _meshesTranslucentTangentsSpecular.append(i); + + } else if (translucentMesh && !hasTangents && hasSpecular && !isSkinned) { + + _meshesTranslucentSpecular.append(i); + + } else if (translucentMesh && hasTangents && !hasSpecular && isSkinned) { + + _meshesTranslucentTangentsSkinned.append(i); + + } else if (translucentMesh && !hasTangents && !hasSpecular && isSkinned) { + + _meshesTranslucentSkinned.append(i); + + } else if (translucentMesh && hasTangents && hasSpecular && isSkinned) { + + _meshesTranslucentTangentsSpecularSkinned.append(i); + + } else if (translucentMesh && !hasTangents && hasSpecular && isSkinned) { + + _meshesTranslucentSpecularSkinned.append(i); + + } else if (!translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { + + _meshesOpaque.append(i); + + } else if (!translucentMesh && hasTangents && !hasSpecular && !isSkinned) { + + _meshesOpaqueTangents.append(i); + + } else if (!translucentMesh && hasTangents && hasSpecular && !isSkinned) { + + _meshesOpaqueTangentsSpecular.append(i); + + } else if (!translucentMesh && !hasTangents && hasSpecular && !isSkinned) { + + _meshesOpaqueSpecular.append(i); + + } else if (!translucentMesh && hasTangents && !hasSpecular && isSkinned) { + + _meshesOpaqueTangentsSkinned.append(i); + + } else if (!translucentMesh && !hasTangents && !hasSpecular && isSkinned) { + + _meshesOpaqueSkinned.append(i); + + } else if (!translucentMesh && hasTangents && hasSpecular && isSkinned) { + + _meshesOpaqueTangentsSpecularSkinned.append(i); + + } else if (!translucentMesh && !hasTangents && hasSpecular && isSkinned) { + + _meshesOpaqueSpecularSkinned.append(i); } else { - _opaqueMeshes.append(i); + qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???"; } } - _translucentMeshesKnown = true; + _meshesGroupsKnown = true; } -int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, RenderArgs* args) { +int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, + bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { int meshPartsRendered = 0; updateVisibleJointStates(); const FBXGeometry& geometry = _geometry->getFBXGeometry(); const QVector& networkMeshes = _geometry->getMeshes(); bool cullMeshParts = args && !Menu::getInstance()->isOptionChecked(MenuOption::DontCullMeshParts); + + // depending on which parameters we were called with, pick the correct mesh group to render + QList* whichList = NULL; + if (translucent && !hasTangents && !hasSpecular && !isSkinned) { + whichList = &_meshesTranslucent; + } else if (translucent && hasTangents && !hasSpecular && !isSkinned) { + whichList = &_meshesTranslucentTangents; + } else if (translucent && hasTangents && hasSpecular && !isSkinned) { + whichList = &_meshesTranslucentTangentsSpecular; + } else if (translucent && !hasTangents && hasSpecular && !isSkinned) { + whichList = &_meshesTranslucentSpecular; + } else if (translucent && hasTangents && !hasSpecular && isSkinned) { + whichList = &_meshesTranslucentTangentsSkinned; + } else if (translucent && !hasTangents && !hasSpecular && isSkinned) { + whichList = &_meshesTranslucentSkinned; + } else if (translucent && hasTangents && hasSpecular && isSkinned) { + whichList = &_meshesTranslucentTangentsSpecularSkinned; + } else if (translucent && !hasTangents && hasSpecular && isSkinned) { + whichList = &_meshesTranslucentSpecularSkinned; + } else if (!translucent && !hasTangents && !hasSpecular && !isSkinned) { + whichList = &_meshesOpaque; + } else if (!translucent && hasTangents && !hasSpecular && !isSkinned) { + whichList = &_meshesOpaqueTangents; + } else if (!translucent && hasTangents && hasSpecular && !isSkinned) { + whichList = &_meshesOpaqueTangentsSpecular; + } else if (!translucent && !hasTangents && hasSpecular && !isSkinned) { + whichList = &_meshesOpaqueSpecular; + } else if (!translucent && hasTangents && !hasSpecular && isSkinned) { + whichList = &_meshesOpaqueTangentsSkinned; + } else if (!translucent && !hasTangents && !hasSpecular && isSkinned) { + whichList = &_meshesOpaqueSkinned; + } else if (!translucent && hasTangents && hasSpecular && isSkinned) { + whichList = &_meshesOpaqueTangentsSpecularSkinned; + } else if (!translucent && !hasTangents && hasSpecular && isSkinned) { + whichList = &_meshesOpaqueSpecularSkinned; + } else { + qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???"; + } - // if we're called in translucent mode, then use our translucent list vs opaque list - QList& list = translucent ? _translucentMeshes : _opaqueMeshes; + if (!whichList) { + qDebug() << "unexpected!!! we don't know which list of meshes to render..."; + return 0; + } + QList& list = *whichList; + + ProgramObject* program = &_program; + Locations* locations = &_locations; + ProgramObject* skinProgram = &_skinProgram; + SkinLocations* skinLocations = &_skinLocations; + GLenum specularTextureUnit = 0; + if (mode == SHADOW_RENDER_MODE) { + program = &_shadowProgram; + skinProgram = &_skinShadowProgram; + skinLocations = &_skinShadowLocations; + } else if (translucent && alphaThreshold == 0.0f) { + program = &_translucentProgram; + locations = &_translucentLocations; + skinProgram = &_skinTranslucentProgram; + skinLocations = &_skinTranslucentLocations; + + } else if (hasTangents) { + if (hasSpecular) { + program = &_normalSpecularMapProgram; + locations = &_normalSpecularMapLocations; + skinProgram = &_skinNormalSpecularMapProgram; + skinLocations = &_skinNormalSpecularMapLocations; + specularTextureUnit = GL_TEXTURE2; + } else { + program = &_normalMapProgram; + locations = &_normalMapLocations; + skinProgram = &_skinNormalMapProgram; + skinLocations = &_skinNormalMapLocations; + } + } else if (hasSpecular) { + program = &_specularMapProgram; + locations = &_specularMapLocations; + skinProgram = &_skinSpecularMapProgram; + skinLocations = &_skinSpecularMapLocations; + specularTextureUnit = GL_TEXTURE1; + } + ProgramObject* activeProgram = program; + Locations* activeLocations = locations; + + if (isSkinned) { + skinProgram->bind(); + activeProgram = skinProgram; + activeLocations = skinLocations; + } else { + program->bind(); + } + activeProgram->setUniformValue(activeLocations->alphaThreshold, alphaThreshold); // i is the "index" from the original networkMeshes QVector... foreach (int i, list) { @@ -1316,52 +1518,11 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, const_cast(networkMesh.vertexBuffer).bind(); - ProgramObject* program = &_program; - Locations* locations = &_locations; - ProgramObject* skinProgram = &_skinProgram; - SkinLocations* skinLocations = &_skinLocations; - GLenum specularTextureUnit = 0; - if (mode == SHADOW_RENDER_MODE) { - program = &_shadowProgram; - skinProgram = &_skinShadowProgram; - skinLocations = &_skinShadowLocations; - - } else if (translucent && alphaThreshold == 0.0f) { - program = &_translucentProgram; - locations = &_translucentLocations; - skinProgram = &_skinTranslucentProgram; - skinLocations = &_skinTranslucentLocations; - - } else if (!mesh.tangents.isEmpty()) { - if (mesh.hasSpecularTexture()) { - program = &_normalSpecularMapProgram; - locations = &_normalSpecularMapLocations; - skinProgram = &_skinNormalSpecularMapProgram; - skinLocations = &_skinNormalSpecularMapLocations; - specularTextureUnit = GL_TEXTURE2; - - } else { - program = &_normalMapProgram; - locations = &_normalMapLocations; - skinProgram = &_skinNormalMapProgram; - skinLocations = &_skinNormalMapLocations; - } - } else if (mesh.hasSpecularTexture()) { - program = &_specularMapProgram; - locations = &_specularMapLocations; - skinProgram = &_skinSpecularMapProgram; - skinLocations = &_skinSpecularMapLocations; - specularTextureUnit = GL_TEXTURE1; - } - - const MeshState& state = _meshStates.at(i); - ProgramObject* activeProgram = program; - Locations* activeLocations = locations; glPushMatrix(); Application::getInstance()->loadTranslatedViewMatrix(_translation); - + + const MeshState& state = _meshStates.at(i); if (state.clusterMatrices.size() > 1) { - skinProgram->bind(); glUniformMatrix4fvARB(skinLocations->clusterMatrices, state.clusterMatrices.size(), false, (const float*)state.clusterMatrices.constData()); int offset = (mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3) + @@ -1372,16 +1533,10 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, offset + vertexCount * sizeof(glm::vec4), 4); skinProgram->enableAttributeArray(skinLocations->clusterIndices); skinProgram->enableAttributeArray(skinLocations->clusterWeights); - activeProgram = skinProgram; - activeLocations = skinLocations; - } else { glMultMatrixf((const GLfloat*)&state.clusterMatrices[0]); - program->bind(); } - activeProgram->setUniformValue(activeLocations->alphaThreshold, alphaThreshold); - if (mesh.blendshapes.isEmpty()) { if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) { activeProgram->setAttributeBuffer(activeLocations->tangent, GL_FLOAT, vertexCount * 2 * sizeof(glm::vec3), 3); @@ -1509,8 +1664,8 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, } glPopMatrix(); - activeProgram->release(); } + activeProgram->release(); return meshPartsRendered; } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index d0e59305ad..55a2eed9d1 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -251,7 +251,7 @@ private: void applyNextGeometry(); void deleteGeometry(); - int renderMeshes(RenderMode mode, bool translucent, float alphaThreshold = 0.5f, RenderArgs* args = NULL); + int renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL); QVector createJointStates(const FBXGeometry& geometry); void initJointTransforms(); @@ -333,11 +333,29 @@ private: QVector _calculatedMeshBoxes; bool _calculatedMeshBoxesValid; - void calculateTranslucentMeshes(); // used to calculate our list of translucent vs opaque meshes + void segregateMeshGroups(); // used to calculate our list of translucent vs opaque meshes - bool _translucentMeshesKnown; - QList _translucentMeshes; // indices of the meshes that are translucent - QList _opaqueMeshes; // indices of the meshes that are opaque + bool _meshesGroupsKnown; + + QList _meshesTranslucent; + QList _meshesTranslucentTangents; + QList _meshesTranslucentTangentsSpecular; + QList _meshesTranslucentSpecular; + + QList _meshesTranslucentSkinned; + QList _meshesTranslucentTangentsSkinned; + QList _meshesTranslucentTangentsSpecularSkinned; + QList _meshesTranslucentSpecularSkinned; + + QList _meshesOpaque; + QList _meshesOpaqueTangents; + QList _meshesOpaqueTangentsSpecular; + QList _meshesOpaqueSpecular; + + QList _meshesOpaqueSkinned; + QList _meshesOpaqueTangentsSkinned; + QList _meshesOpaqueTangentsSpecularSkinned; + QList _meshesOpaqueSpecularSkinned; };