From 764ad724711e6cd5285af19a34b48e0afec2afd2 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 20 Nov 2014 09:54:41 -0800 Subject: [PATCH] adding the light map support from FBX --- .../resources/shaders/model_normal_map.frag | 2 +- interface/src/ModelUploader.cpp | 8 + interface/src/renderer/GeometryCache.cpp | 28 +- interface/src/renderer/GeometryCache.h | 4 +- interface/src/renderer/Model.cpp | 520 +++++++++++++----- interface/src/renderer/Model.h | 58 +- interface/src/renderer/TextureCache.h | 4 +- libraries/fbx/src/FBXReader.cpp | 37 ++ libraries/fbx/src/FBXReader.h | 2 + 9 files changed, 525 insertions(+), 138 deletions(-) diff --git a/interface/resources/shaders/model_normal_map.frag b/interface/resources/shaders/model_normal_map.frag index f5a1047b2b..af107e9d3c 100644 --- a/interface/resources/shaders/model_normal_map.frag +++ b/interface/resources/shaders/model_normal_map.frag @@ -4,7 +4,7 @@ // model_normal_map.frag // fragment shader // -// Created by Andrzej Kapolka on 10/29/13. +// Created by Andrzej Kapolka on 10/14/13. // Copyright 2013 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. diff --git a/interface/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp index 2599f39e83..d9e8ed0c40 100644 --- a/interface/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -522,6 +522,14 @@ bool ModelUploader::addTextures(const QString& texdir, const FBXGeometry& geomet } _textureFilenames.insert(part.specularTexture.filename); } + if (!part.emissiveTexture.filename.isEmpty() && part.emissiveTexture.content.isEmpty() && + !_textureFilenames.contains(part.emissiveTexture.filename)) { + if (!addPart(texdir + "/" + part.emissiveTexture.filename, + QString("texture%1").arg(++_texturesCount), true)) { + return false; + } + _textureFilenames.insert(part.emissiveTexture.filename); + } } } diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index 9052ec910f..cca0d120c2 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -575,7 +575,8 @@ bool NetworkGeometry::isLoadedWithTextures() const { foreach (const NetworkMeshPart& part, mesh.parts) { if ((part.diffuseTexture && !part.diffuseTexture->isLoaded()) || (part.normalTexture && !part.normalTexture->isLoaded()) || - (part.specularTexture && !part.specularTexture->isLoaded())) { + (part.specularTexture && !part.specularTexture->isLoaded()) || + (part.emissiveTexture && !part.emissiveTexture->isLoaded())) { return false; } } @@ -668,6 +669,9 @@ void NetworkGeometry::setLoadPriority(const QPointer& owner, float prio if (part.specularTexture) { part.specularTexture->setLoadPriority(owner, priority); } + if (part.emissiveTexture) { + part.emissiveTexture->setLoadPriority(owner, priority); + } } } } @@ -688,6 +692,9 @@ void NetworkGeometry::setLoadPriorities(const QHash, float>& p if (part.specularTexture) { part.specularTexture->setLoadPriorities(priorities); } + if (part.emissiveTexture) { + part.emissiveTexture->setLoadPriorities(priorities); + } } } } @@ -708,6 +715,9 @@ void NetworkGeometry::clearLoadPriority(const QPointer& owner) { if (part.specularTexture) { part.specularTexture->clearLoadPriority(owner); } + if (part.emissiveTexture) { + part.emissiveTexture->clearLoadPriority(owner); + } } } } @@ -733,6 +743,10 @@ void NetworkGeometry::setTextureWithNameToURL(const QString& name, const QUrl& u part.specularTexture = Application::getInstance()->getTextureCache()->getTexture(url, DEFAULT_TEXTURE, false, QByteArray()); part.specularTexture->setLoadPriorities(_loadPriorities); + } else if (part.emissiveTextureName == name) { + part.emissiveTexture = Application::getInstance()->getTextureCache()->getTexture(url, DEFAULT_TEXTURE, + false, QByteArray()); + part.emissiveTexture->setLoadPriorities(_loadPriorities); } } } @@ -764,6 +778,11 @@ QStringList NetworkGeometry::getTextureNames() const { QString textureURL = part.specularTexture->getURL().toString(); result << part.specularTextureName + ":" + textureURL; } + + if (!part.emissiveTextureName.isEmpty()) { + QString textureURL = part.emissiveTexture->getURL().toString(); + result << part.emissiveTextureName + ":" + textureURL; + } } } return result; @@ -911,6 +930,13 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { networkPart.specularTextureName = part.specularTexture.name; networkPart.specularTexture->setLoadPriorities(_loadPriorities); } + if (!part.emissiveTexture.filename.isEmpty()) { + networkPart.emissiveTexture = Application::getInstance()->getTextureCache()->getTexture( + _textureBase.resolved(QUrl(part.emissiveTexture.filename)), EMISSIVE_TEXTURE, + false, part.emissiveTexture.content); + networkPart.emissiveTextureName = part.emissiveTexture.name; + networkPart.emissiveTexture->setLoadPriorities(_loadPriorities); + } networkMesh.parts.append(networkPart); totalIndices += (part.quadIndices.size() + part.triangleIndices.size()); diff --git a/interface/src/renderer/GeometryCache.h b/interface/src/renderer/GeometryCache.h index e58177533c..6faad93fe4 100644 --- a/interface/src/renderer/GeometryCache.h +++ b/interface/src/renderer/GeometryCache.h @@ -155,7 +155,9 @@ public: QSharedPointer normalTexture; QString specularTextureName; QSharedPointer specularTexture; - + QString emissiveTextureName; + QSharedPointer emissiveTexture; + bool isTranslucent() const; }; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index fc3845d94f..c3e21aea7c 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -70,6 +70,11 @@ ProgramObject Model::_specularMapProgram; ProgramObject Model::_normalSpecularMapProgram; ProgramObject Model::_translucentProgram; +ProgramObject Model::_emissiveProgram; +ProgramObject Model::_emissiveNormalMapProgram; +ProgramObject Model::_emissiveSpecularMapProgram; +ProgramObject Model::_emissiveNormalSpecularMapProgram; + ProgramObject Model::_shadowProgram; ProgramObject Model::_skinProgram; @@ -78,6 +83,11 @@ ProgramObject Model::_skinSpecularMapProgram; ProgramObject Model::_skinNormalSpecularMapProgram; ProgramObject Model::_skinTranslucentProgram; +ProgramObject Model::_skinEmissiveProgram; +ProgramObject Model::_skinEmissiveNormalMapProgram; +ProgramObject Model::_skinEmissiveSpecularMapProgram; +ProgramObject Model::_skinEmissiveNormalSpecularMapProgram; + ProgramObject Model::_skinShadowProgram; Model::Locations Model::_locations; @@ -86,6 +96,11 @@ Model::Locations Model::_specularMapLocations; Model::Locations Model::_normalSpecularMapLocations; Model::Locations Model::_translucentLocations; +Model::Locations Model::_emissiveLocations; +Model::Locations Model::_emissiveNormalMapLocations; +Model::Locations Model::_emissiveSpecularMapLocations; +Model::Locations Model::_emissiveNormalSpecularMapLocations; + Model::SkinLocations Model::_skinLocations; Model::SkinLocations Model::_skinNormalMapLocations; Model::SkinLocations Model::_skinSpecularMapLocations; @@ -93,6 +108,11 @@ Model::SkinLocations Model::_skinNormalSpecularMapLocations; Model::SkinLocations Model::_skinShadowLocations; Model::SkinLocations Model::_skinTranslucentLocations; +Model::SkinLocations Model::_skinEmissiveLocations; +Model::SkinLocations Model::_skinEmissiveNormalMapLocations; +Model::SkinLocations Model::_skinEmissiveSpecularMapLocations; +Model::SkinLocations Model::_skinEmissiveNormalSpecularMapLocations; + void Model::setScale(const glm::vec3& scale) { setScaleInternal(scale); // if anyone sets scale manually, then we are no longer scaled to fit @@ -268,6 +288,39 @@ void Model::init() { _translucentProgram.link(); initProgram(_translucentProgram, _translucentLocations); + + // Emissive + _emissiveProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model.vert"); + _emissiveProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_emissive.frag"); + _emissiveProgram.link(); + + initProgram(_emissiveProgram, _emissiveLocations); + + _emissiveNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/model_normal_map.vert"); + _emissiveNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_emissive_normal_map.frag"); + _emissiveNormalMapProgram.link(); + + initProgram(_emissiveNormalMapProgram, _emissiveNormalMapLocations); + + _emissiveSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/model.vert"); + _emissiveSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_emissive_specular_map.frag"); + _emissiveSpecularMapProgram.link(); + + initProgram(_emissiveSpecularMapProgram, _emissiveSpecularMapLocations); + + _emissiveNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/model_normal_map.vert"); + _emissiveNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_emissive_normal_specular_map.frag"); + _emissiveNormalSpecularMapProgram.link(); + + initProgram(_emissiveNormalSpecularMapProgram, _emissiveNormalSpecularMapLocations, 2); + // end emissive + _shadowProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model_shadow.vert"); _shadowProgram.addShaderFromSourceFile(QGLShader::Fragment, @@ -319,6 +372,38 @@ void Model::init() { _skinTranslucentProgram.link(); initSkinProgram(_skinTranslucentProgram, _skinTranslucentLocations); + + + _skinEmissiveProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/skin_model.vert"); + _skinEmissiveProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_emissive.frag"); + _skinEmissiveProgram.link(); + + initSkinProgram(_skinEmissiveProgram, _skinEmissiveLocations); + + _skinEmissiveNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/skin_model_normal_map.vert"); + _skinEmissiveNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_emissive_normal_map.frag"); + _skinEmissiveNormalMapProgram.link(); + + initSkinProgram(_skinEmissiveNormalMapProgram, _skinEmissiveNormalMapLocations); + + _skinEmissiveSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/skin_model.vert"); + _skinEmissiveSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_emissive_specular_map.frag"); + _skinEmissiveSpecularMapProgram.link(); + + initSkinProgram(_skinEmissiveSpecularMapProgram, _skinEmissiveSpecularMapLocations); + + _skinEmissiveNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/skin_model_normal_map.vert"); + _skinEmissiveNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_emissive_normal_specular_map.frag"); + _skinEmissiveNormalSpecularMapProgram.link(); + + initSkinProgram(_skinEmissiveNormalSpecularMapProgram, _skinEmissiveNormalSpecularMapLocations, 2); + } } @@ -621,14 +706,23 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { //renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, book isSkinned, args); int opaqueMeshPartsRendered = 0; - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, true, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, true, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, true, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, true, args); + + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, true, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, true, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, true, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, true, args); // render translucent meshes afterwards //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true); @@ -642,14 +736,14 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { int translucentMeshPartsRendered = 0; const float MOSTLY_OPAQUE_THRESHOLD = 0.75f; - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args); GLBATCH(glDisable)(GL_ALPHA_TEST); GLBATCH(glEnable)(GL_BLEND); @@ -666,14 +760,14 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f; - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, true, args); } GLBATCH(glDepthMask)(true); @@ -1562,15 +1656,24 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { int opaqueMeshPartsRendered = 0; // now, for each model in the scene, render the mesh portions - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, args); - + /* opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, true, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, true, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, true, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, true, args); +*/ + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, true, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, true, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, true, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, true, args); + // render translucent meshes afterwards //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true); { @@ -1583,15 +1686,15 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { int translucentParts = 0; const float MOSTLY_OPAQUE_THRESHOLD = 0.75f; - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, true, args); - + /* translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args); + */ GLBATCH(glDisable)(GL_ALPHA_TEST); GLBATCH(glEnable)(GL_BLEND); GLBATCH(glDepthMask)(false); @@ -1607,15 +1710,15 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f; - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, true, args); - } + /* translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, true, args); + */ } GLBATCH(glDepthMask)(true); GLBATCH(glDepthFunc)(GL_LESS); @@ -1689,7 +1792,17 @@ void Model::segregateMeshGroups() { _meshesOpaqueSkinned.clear(); _meshesOpaqueTangentsSpecularSkinned.clear(); _meshesOpaqueSpecularSkinned.clear(); - + + _meshesOpaqueEmissiveTangents.clear(); + _meshesOpaqueEmissive.clear(); + _meshesOpaqueEmissiveTangentsSpecular.clear(); + _meshesOpaqueEmissiveSpecular.clear(); + + _meshesOpaqueEmissiveTangentsSkinned.clear(); + _meshesOpaqueEmissiveSkinned.clear(); + _meshesOpaqueEmissiveTangentsSpecularSkinned.clear(); + _meshesOpaqueEmissiveSpecularSkinned.clear(); + _unsortedMeshesTranslucentTangents.clear(); _unsortedMeshesTranslucent.clear(); _unsortedMeshesTranslucentTangentsSpecular.clear(); @@ -1710,6 +1823,16 @@ void Model::segregateMeshGroups() { _unsortedMeshesOpaqueTangentsSpecularSkinned.clear(); _unsortedMeshesOpaqueSpecularSkinned.clear(); + _unsortedMeshesOpaqueEmissiveTangents.clear(); + _unsortedMeshesOpaqueEmissive.clear(); + _unsortedMeshesOpaqueEmissiveTangentsSpecular.clear(); + _unsortedMeshesOpaqueEmissiveSpecular.clear(); + + _unsortedMeshesOpaqueEmissiveTangentsSkinned.clear(); + _unsortedMeshesOpaqueEmissiveSkinned.clear(); + _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned.clear(); + _unsortedMeshesOpaqueEmissiveSpecularSkinned.clear(); + const FBXGeometry& geometry = _geometry->getFBXGeometry(); const QVector& networkMeshes = _geometry->getMeshes(); @@ -1723,6 +1846,7 @@ void Model::segregateMeshGroups() { bool translucentMesh = networkMesh.getTranslucentPartCount(mesh) == networkMesh.parts.size(); bool hasTangents = !mesh.tangents.isEmpty(); bool hasSpecular = mesh.hasSpecularTexture(); + bool hasEmissive = mesh.hasEmissiveTexture(); bool isSkinned = state.clusterMatrices.size() > 1; QString materialID; @@ -1741,71 +1865,108 @@ void Model::segregateMeshGroups() { qDebug() << "materialID:" << materialID << "parts:" << mesh.parts.size(); } - if (translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { + if ( !hasEmissive) { + if (translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { - _unsortedMeshesTranslucent.insertMulti(materialID, i); + _unsortedMeshesTranslucent.insertMulti(materialID, i); - } else if (translucentMesh && hasTangents && !hasSpecular && !isSkinned) { + } else if (translucentMesh && hasTangents && !hasSpecular && !isSkinned) { - _unsortedMeshesTranslucentTangents.insertMulti(materialID, i); + _unsortedMeshesTranslucentTangents.insertMulti(materialID, i); - } else if (translucentMesh && hasTangents && hasSpecular && !isSkinned) { + } else if (translucentMesh && hasTangents && hasSpecular && !isSkinned) { - _unsortedMeshesTranslucentTangentsSpecular.insertMulti(materialID, i); + _unsortedMeshesTranslucentTangentsSpecular.insertMulti(materialID, i); - } else if (translucentMesh && !hasTangents && hasSpecular && !isSkinned) { + } else if (translucentMesh && !hasTangents && hasSpecular && !isSkinned) { - _unsortedMeshesTranslucentSpecular.insertMulti(materialID, i); + _unsortedMeshesTranslucentSpecular.insertMulti(materialID, i); - } else if (translucentMesh && hasTangents && !hasSpecular && isSkinned) { + } else if (translucentMesh && hasTangents && !hasSpecular && isSkinned) { - _unsortedMeshesTranslucentTangentsSkinned.insertMulti(materialID, i); + _unsortedMeshesTranslucentTangentsSkinned.insertMulti(materialID, i); - } else if (translucentMesh && !hasTangents && !hasSpecular && isSkinned) { + } else if (translucentMesh && !hasTangents && !hasSpecular && isSkinned) { - _unsortedMeshesTranslucentSkinned.insertMulti(materialID, i); + _unsortedMeshesTranslucentSkinned.insertMulti(materialID, i); - } else if (translucentMesh && hasTangents && hasSpecular && isSkinned) { + } else if (translucentMesh && hasTangents && hasSpecular && isSkinned) { - _unsortedMeshesTranslucentTangentsSpecularSkinned.insertMulti(materialID, i); + _unsortedMeshesTranslucentTangentsSpecularSkinned.insertMulti(materialID, i); - } else if (translucentMesh && !hasTangents && hasSpecular && isSkinned) { + } else if (translucentMesh && !hasTangents && hasSpecular && isSkinned) { - _unsortedMeshesTranslucentSpecularSkinned.insertMulti(materialID, i); + _unsortedMeshesTranslucentSpecularSkinned.insertMulti(materialID, i); - } else if (!translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { + } else if (!translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { - _unsortedMeshesOpaque.insertMulti(materialID, i); + _unsortedMeshesOpaque.insertMulti(materialID, i); - } else if (!translucentMesh && hasTangents && !hasSpecular && !isSkinned) { + } else if (!translucentMesh && hasTangents && !hasSpecular && !isSkinned) { - _unsortedMeshesOpaqueTangents.insertMulti(materialID, i); + _unsortedMeshesOpaqueTangents.insertMulti(materialID, i); - } else if (!translucentMesh && hasTangents && hasSpecular && !isSkinned) { + } else if (!translucentMesh && hasTangents && hasSpecular && !isSkinned) { - _unsortedMeshesOpaqueTangentsSpecular.insertMulti(materialID, i); + _unsortedMeshesOpaqueTangentsSpecular.insertMulti(materialID, i); - } else if (!translucentMesh && !hasTangents && hasSpecular && !isSkinned) { + } else if (!translucentMesh && !hasTangents && hasSpecular && !isSkinned) { - _unsortedMeshesOpaqueSpecular.insertMulti(materialID, i); + _unsortedMeshesOpaqueSpecular.insertMulti(materialID, i); - } else if (!translucentMesh && hasTangents && !hasSpecular && isSkinned) { + } else if (!translucentMesh && hasTangents && !hasSpecular && isSkinned) { - _unsortedMeshesOpaqueTangentsSkinned.insertMulti(materialID, i); + _unsortedMeshesOpaqueTangentsSkinned.insertMulti(materialID, i); - } else if (!translucentMesh && !hasTangents && !hasSpecular && isSkinned) { + } else if (!translucentMesh && !hasTangents && !hasSpecular && isSkinned) { - _unsortedMeshesOpaqueSkinned.insertMulti(materialID, i); + _unsortedMeshesOpaqueSkinned.insertMulti(materialID, i); - } else if (!translucentMesh && hasTangents && hasSpecular && isSkinned) { + } else if (!translucentMesh && hasTangents && hasSpecular && isSkinned) { - _unsortedMeshesOpaqueTangentsSpecularSkinned.insertMulti(materialID, i); + _unsortedMeshesOpaqueTangentsSpecularSkinned.insertMulti(materialID, i); - } else if (!translucentMesh && !hasTangents && hasSpecular && isSkinned) { + } else if (!translucentMesh && !hasTangents && hasSpecular && isSkinned) { - _unsortedMeshesOpaqueSpecularSkinned.insertMulti(materialID, i); + _unsortedMeshesOpaqueSpecularSkinned.insertMulti(materialID, i); + } else { + qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???"; + } } else { - qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???"; + if (!translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { + + _unsortedMeshesOpaqueEmissive.insertMulti(materialID, i); + + } else if (!translucentMesh && hasTangents && !hasSpecular && !isSkinned) { + + _unsortedMeshesOpaqueEmissiveTangents.insertMulti(materialID, i); + + } else if (!translucentMesh && hasTangents && hasSpecular && !isSkinned) { + + _unsortedMeshesOpaqueEmissiveTangentsSpecular.insertMulti(materialID, i); + + } else if (!translucentMesh && !hasTangents && hasSpecular && !isSkinned) { + + _unsortedMeshesOpaqueEmissiveSpecular.insertMulti(materialID, i); + + } else if (!translucentMesh && hasTangents && !hasSpecular && isSkinned) { + + _unsortedMeshesOpaqueEmissiveTangentsSkinned.insertMulti(materialID, i); + + } else if (!translucentMesh && !hasTangents && !hasSpecular && isSkinned) { + + _unsortedMeshesOpaqueEmissiveSkinned.insertMulti(materialID, i); + + } else if (!translucentMesh && hasTangents && hasSpecular && isSkinned) { + + _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned.insertMulti(materialID, i); + + } else if (!translucentMesh && !hasTangents && hasSpecular && isSkinned) { + + _unsortedMeshesOpaqueEmissiveSpecularSkinned.insertMulti(materialID, i); + } else { + qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???"; + } } } @@ -1873,6 +2034,38 @@ void Model::segregateMeshGroups() { _meshesOpaqueSpecularSkinned.append(i); } + foreach(int i, _unsortedMeshesOpaqueEmissive) { + _meshesOpaqueEmissive.append(i); + } + + foreach(int i, _unsortedMeshesOpaqueEmissiveTangents) { + _meshesOpaqueEmissiveTangents.append(i); + } + + foreach(int i, _unsortedMeshesOpaqueEmissiveTangentsSpecular) { + _meshesOpaqueEmissiveTangentsSpecular.append(i); + } + + foreach(int i, _unsortedMeshesOpaqueEmissiveSpecular) { + _meshesOpaqueEmissiveSpecular.append(i); + } + + foreach(int i, _unsortedMeshesOpaqueEmissiveSkinned) { + _meshesOpaqueEmissiveSkinned.append(i); + } + + foreach(int i, _unsortedMeshesOpaqueEmissiveTangentsSkinned) { + _meshesOpaqueEmissiveTangentsSkinned.append(i); + } + + foreach(int i, _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned) { + _meshesOpaqueEmissiveTangentsSpecularSkinned.append(i); + } + + foreach(int i, _unsortedMeshesOpaqueEmissiveSpecularSkinned) { + _meshesOpaqueEmissiveSpecularSkinned.append(i); + } + _unsortedMeshesTranslucentTangents.clear(); _unsortedMeshesTranslucent.clear(); _unsortedMeshesTranslucentTangentsSpecular.clear(); @@ -1893,10 +2086,20 @@ void Model::segregateMeshGroups() { _unsortedMeshesOpaqueTangentsSpecularSkinned.clear(); _unsortedMeshesOpaqueSpecularSkinned.clear(); + _unsortedMeshesOpaqueEmissiveTangents.clear(); + _unsortedMeshesOpaqueEmissive.clear(); + _unsortedMeshesOpaqueEmissiveTangentsSpecular.clear(); + _unsortedMeshesOpaqueEmissiveSpecular.clear(); + + _unsortedMeshesOpaqueEmissiveTangentsSkinned.clear(); + _unsortedMeshesOpaqueEmissiveSkinned.clear(); + _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned.clear(); + _unsortedMeshesOpaqueEmissiveSpecularSkinned.clear(); + _meshGroupsKnown = true; } -QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, bool isSkinned) { +QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned) { PROFILE_RANGE(__FUNCTION__); // depending on which parameters we were called with, pick the correct mesh group to render @@ -1917,22 +2120,41 @@ QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool h whichList = &_meshesTranslucentTangentsSpecularSkinned; } else if (translucent && !hasTangents && hasSpecular && isSkinned) { whichList = &_meshesTranslucentSpecularSkinned; - } else if (!translucent && !hasTangents && !hasSpecular && !isSkinned) { + + } else if (!translucent && !hasEmissive && !hasTangents && !hasSpecular && !isSkinned) { whichList = &_meshesOpaque; - } else if (!translucent && hasTangents && !hasSpecular && !isSkinned) { + } else if (!translucent && !hasEmissive && hasTangents && !hasSpecular && !isSkinned) { whichList = &_meshesOpaqueTangents; - } else if (!translucent && hasTangents && hasSpecular && !isSkinned) { + } else if (!translucent && !hasEmissive && hasTangents && hasSpecular && !isSkinned) { whichList = &_meshesOpaqueTangentsSpecular; - } else if (!translucent && !hasTangents && hasSpecular && !isSkinned) { + } else if (!translucent && !hasEmissive && !hasTangents && hasSpecular && !isSkinned) { whichList = &_meshesOpaqueSpecular; - } else if (!translucent && hasTangents && !hasSpecular && isSkinned) { + } else if (!translucent && !hasEmissive && hasTangents && !hasSpecular && isSkinned) { whichList = &_meshesOpaqueTangentsSkinned; - } else if (!translucent && !hasTangents && !hasSpecular && isSkinned) { + } else if (!translucent && !hasEmissive && !hasTangents && !hasSpecular && isSkinned) { whichList = &_meshesOpaqueSkinned; - } else if (!translucent && hasTangents && hasSpecular && isSkinned) { + } else if (!translucent && !hasEmissive && hasTangents && hasSpecular && isSkinned) { whichList = &_meshesOpaqueTangentsSpecularSkinned; - } else if (!translucent && !hasTangents && hasSpecular && isSkinned) { + } else if (!translucent && !hasEmissive && !hasTangents && hasSpecular && isSkinned) { whichList = &_meshesOpaqueSpecularSkinned; + + } else if (!translucent && hasEmissive && !hasTangents && !hasSpecular && !isSkinned) { + whichList = &_meshesOpaqueEmissive; + } else if (!translucent && hasEmissive && hasTangents && !hasSpecular && !isSkinned) { + whichList = &_meshesOpaqueEmissiveTangents; + } else if (!translucent && hasEmissive && hasTangents && hasSpecular && !isSkinned) { + whichList = &_meshesOpaqueEmissiveTangentsSpecular; + } else if (!translucent && hasEmissive && !hasTangents && hasSpecular && !isSkinned) { + whichList = &_meshesOpaqueEmissiveSpecular; + } else if (!translucent && hasEmissive && hasTangents && !hasSpecular && isSkinned) { + whichList = &_meshesOpaqueEmissiveTangentsSkinned; + } else if (!translucent && hasEmissive && !hasTangents && !hasSpecular && isSkinned) { + whichList = &_meshesOpaqueEmissiveSkinned; + } else if (!translucent && hasEmissive && hasTangents && hasSpecular && isSkinned) { + whichList = &_meshesOpaqueEmissiveTangentsSpecularSkinned; + } else if (!translucent && hasEmissive && !hasTangents && hasSpecular && isSkinned) { + whichList = &_meshesOpaqueEmissiveSpecularSkinned; + } else { qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???"; } @@ -1940,14 +2162,15 @@ QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool h } void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, - SkinLocations*& skinLocations, GLenum& specularTextureUnit) { + bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, + SkinLocations*& skinLocations, GLenum& specularTextureUnit, GLenum& emissiveTextureUnit) { ProgramObject* program = &_program; Locations* locations = &_locations; ProgramObject* skinProgram = &_skinProgram; skinLocations = &_skinLocations; specularTextureUnit = 0; + emissiveTextureUnit = 0; if (mode == SHADOW_RENDER_MODE) { program = &_shadowProgram; skinProgram = &_skinShadowProgram; @@ -1958,27 +2181,59 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f skinProgram = &_skinTranslucentProgram; skinLocations = &_skinTranslucentLocations; - } else if (hasTangents) { - if (hasSpecular) { - program = &_normalSpecularMapProgram; - locations = &_normalSpecularMapLocations; - skinProgram = &_skinNormalSpecularMapProgram; - skinLocations = &_skinNormalSpecularMapLocations; - specularTextureUnit = GL_TEXTURE2; + } else if (hasEmissive) { + if (hasTangents) { + if (hasSpecular) { + program = &_emissiveNormalSpecularMapProgram; + locations = &_emissiveNormalSpecularMapLocations; + skinProgram = &_skinEmissiveNormalSpecularMapProgram; + skinLocations = &_skinEmissiveNormalSpecularMapLocations; + specularTextureUnit = GL_TEXTURE2; + emissiveTextureUnit = GL_TEXTURE3; + } else { + program = &_emissiveNormalMapProgram; + locations = &_emissiveNormalMapLocations; + skinProgram = &_skinEmissiveNormalMapProgram; + skinLocations = &_skinEmissiveNormalMapLocations; + emissiveTextureUnit = GL_TEXTURE3; + } + } else if (hasSpecular) { + program = &_emissiveSpecularMapProgram; + locations = &_emissiveSpecularMapLocations; + skinProgram = &_skinEmissiveSpecularMapProgram; + skinLocations = &_skinEmissiveSpecularMapLocations; + specularTextureUnit = GL_TEXTURE1; + emissiveTextureUnit = GL_TEXTURE3; } else { - program = &_normalMapProgram; - locations = &_normalMapLocations; - skinProgram = &_skinNormalMapProgram; - skinLocations = &_skinNormalMapLocations; + program = &_emissiveProgram; + locations = &_emissiveLocations; + skinProgram = &_skinEmissiveProgram; + skinLocations = &_skinEmissiveLocations; + emissiveTextureUnit = GL_TEXTURE3; } - } else if (hasSpecular) { - program = &_specularMapProgram; - locations = &_specularMapLocations; - skinProgram = &_skinSpecularMapProgram; - skinLocations = &_skinSpecularMapLocations; - specularTextureUnit = GL_TEXTURE1; - } - + } 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; @@ -1996,7 +2251,7 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f } int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { + bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { PROFILE_RANGE(__FUNCTION__); int meshPartsRendered = 0; @@ -2004,18 +2259,19 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool bool pickProgramsNeeded = true; SkinLocations* skinLocations; GLenum specularTextureUnit; + GLenum emissiveTextureUnit; foreach(Model* model, _modelsInScene) { - QVector* whichList = model->pickMeshList(translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned); + QVector* whichList = model->pickMeshList(translucent, alphaThreshold, hasEmissive, hasTangents, hasSpecular, isSkinned); if (whichList) { QVector& list = *whichList; if (list.size() > 0) { if (pickProgramsNeeded) { - pickPrograms(batch, mode, translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned, args, skinLocations, specularTextureUnit); + pickPrograms(batch, mode, translucent, alphaThreshold, hasEmissive, hasTangents, hasSpecular, isSkinned, args, skinLocations, specularTextureUnit, emissiveTextureUnit); pickProgramsNeeded = false; } model->setupBatchTransform(batch); - meshPartsRendered += model->renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, skinLocations, specularTextureUnit); + meshPartsRendered += model->renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, skinLocations, specularTextureUnit, emissiveTextureUnit); GLBATCH(glPopMatrix)(); } } @@ -2028,12 +2284,12 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool } int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { + bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { PROFILE_RANGE(__FUNCTION__); int meshPartsRendered = 0; - QVector* whichList = pickMeshList(translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned); + QVector* whichList = pickMeshList(translucent, alphaThreshold, hasEmissive, hasTangents, hasSpecular, isSkinned); if (!whichList) { qDebug() << "unexpected!!! we don't know which list of meshes to render..."; @@ -2048,8 +2304,9 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl SkinLocations* skinLocations; GLenum specularTextureUnit; - pickPrograms(batch, mode, translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned, args, skinLocations, specularTextureUnit); - meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, skinLocations, specularTextureUnit); + GLenum emissiveTextureUnit; + pickPrograms(batch, mode, translucent, alphaThreshold, hasEmissive, hasTangents, hasSpecular, isSkinned, args, skinLocations, specularTextureUnit, emissiveTextureUnit); + meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, skinLocations, specularTextureUnit, emissiveTextureUnit); GLBATCH(glUseProgram)(0); return meshPartsRendered; @@ -2057,7 +2314,7 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, RenderArgs* args, - SkinLocations* skinLocations, GLenum specularTextureUnit) { + SkinLocations* skinLocations, GLenum specularTextureUnit, GLenum emissiveTextureUnit) { PROFILE_RANGE(__FUNCTION__); bool dontCullOutOfViewMeshParts = Menu::getInstance()->isOptionChecked(MenuOption::DontCullOutOfViewMeshParts); bool cullTooSmallMeshParts = !Menu::getInstance()->isOptionChecked(MenuOption::DontCullTooSmallMeshParts); @@ -2198,6 +2455,15 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod Application::getInstance()->getTextureCache()->getWhiteTextureID() : specularMap->getID()); GLBATCH(glActiveTexture)(GL_TEXTURE0); } + + if (emissiveTextureUnit) { + GLBATCH(glActiveTexture)(emissiveTextureUnit); + Texture* emissiveMap = networkPart.emissiveTexture.data(); + GLBATCH(glBindTexture)(GL_TEXTURE_2D, !emissiveMap ? + Application::getInstance()->getTextureCache()->getWhiteTextureID() : emissiveMap->getID()); + GLBATCH(glActiveTexture)(GL_TEXTURE0); + } + if (args) { args->_materialSwitches++; } @@ -2238,6 +2504,12 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glActiveTexture)(GL_TEXTURE0); } + if (emissiveTextureUnit) { + GLBATCH(glActiveTexture)(emissiveTextureUnit); + GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); + GLBATCH(glActiveTexture)(GL_TEXTURE0); + } + GLBATCH(glPopMatrix)(); } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 4dceb07655..c1ae190a1e 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -303,7 +303,12 @@ private: static ProgramObject _specularMapProgram; static ProgramObject _normalSpecularMapProgram; static ProgramObject _translucentProgram; - + + static ProgramObject _emissiveProgram; + static ProgramObject _emissiveNormalMapProgram; + static ProgramObject _emissiveSpecularMapProgram; + static ProgramObject _emissiveNormalSpecularMapProgram; + static ProgramObject _shadowProgram; static ProgramObject _skinProgram; @@ -311,7 +316,12 @@ private: static ProgramObject _skinSpecularMapProgram; static ProgramObject _skinNormalSpecularMapProgram; static ProgramObject _skinTranslucentProgram; - + + static ProgramObject _skinEmissiveProgram; + static ProgramObject _skinEmissiveNormalMapProgram; + static ProgramObject _skinEmissiveSpecularMapProgram; + static ProgramObject _skinEmissiveNormalSpecularMapProgram; + static ProgramObject _skinShadowProgram; static int _normalMapTangentLocation; @@ -328,6 +338,11 @@ private: static Locations _specularMapLocations; static Locations _normalSpecularMapLocations; static Locations _translucentLocations; + + static Locations _emissiveLocations; + static Locations _emissiveNormalMapLocations; + static Locations _emissiveSpecularMapLocations; + static Locations _emissiveNormalSpecularMapLocations; static void initProgram(ProgramObject& program, Locations& locations, int specularTextureUnit = 1); @@ -344,7 +359,12 @@ private: static SkinLocations _skinNormalSpecularMapLocations; static SkinLocations _skinShadowLocations; static SkinLocations _skinTranslucentLocations; - + + static SkinLocations _skinEmissiveLocations; + static SkinLocations _skinEmissiveNormalMapLocations; + static SkinLocations _skinEmissiveSpecularMapLocations; + static SkinLocations _skinEmissiveNormalSpecularMapLocations; + static void initSkinProgram(ProgramObject& program, SkinLocations& locations, int specularTextureUnit = 1); QVector _calculatedMeshBoxes; @@ -376,6 +396,16 @@ private: QMap _unsortedMeshesOpaqueTangentsSpecularSkinned; QMap _unsortedMeshesOpaqueSpecularSkinned; + QMap _unsortedMeshesOpaqueEmissive; + QMap _unsortedMeshesOpaqueEmissiveTangents; + QMap _unsortedMeshesOpaqueEmissiveTangentsSpecular; + QMap _unsortedMeshesOpaqueEmissiveSpecular; + + QMap _unsortedMeshesOpaqueEmissiveSkinned; + QMap _unsortedMeshesOpaqueEmissiveTangentsSkinned; + QMap _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned; + QMap _unsortedMeshesOpaqueEmissiveSpecularSkinned; + QVector _meshesTranslucent; QVector _meshesTranslucentTangents; QVector _meshesTranslucentTangentsSpecular; @@ -396,6 +426,16 @@ private: QVector _meshesOpaqueTangentsSpecularSkinned; QVector _meshesOpaqueSpecularSkinned; + QVector _meshesOpaqueEmissive; + QVector _meshesOpaqueEmissiveTangents; + QVector _meshesOpaqueEmissiveTangentsSpecular; + QVector _meshesOpaqueEmissiveSpecular; + + QVector _meshesOpaqueEmissiveSkinned; + QVector _meshesOpaqueEmissiveTangentsSkinned; + QVector _meshesOpaqueEmissiveTangentsSpecularSkinned; + QVector _meshesOpaqueEmissiveSpecularSkinned; + // Scene rendering support static QVector _modelsInScene; static gpu::Batch _sceneRenderBatch; @@ -407,19 +447,19 @@ private: void renderSetup(RenderArgs* args); bool renderCore(float alpha, RenderMode mode, RenderArgs* args); int renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL); + bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL); void setupBatchTransform(gpu::Batch& batch); - QVector* pickMeshList(bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, bool isSkinned); + QVector* pickMeshList(bool translucent, float alphaThreshold, bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned); int renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - RenderArgs* args, SkinLocations* skinLocations, GLenum specularTextureUnit); + RenderArgs* args, SkinLocations* skinLocations, GLenum specularTextureUnit, GLenum emissiveTextureUnit); static void pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, - SkinLocations*& skinLocations, GLenum& specularTextureUnit); + bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, + SkinLocations*& skinLocations, GLenum& specularTextureUnit, GLenum& emissiveTextureUnit); static int renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args); + bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args); }; diff --git a/interface/src/renderer/TextureCache.h b/interface/src/renderer/TextureCache.h index fd9131fe23..66734da9cd 100644 --- a/interface/src/renderer/TextureCache.h +++ b/interface/src/renderer/TextureCache.h @@ -25,7 +25,7 @@ class NetworkTexture; typedef QSharedPointer NetworkTexturePointer; -enum TextureType { DEFAULT_TEXTURE, NORMAL_TEXTURE, SPECULAR_TEXTURE, SPLAT_TEXTURE }; +enum TextureType { DEFAULT_TEXTURE, NORMAL_TEXTURE, SPECULAR_TEXTURE, EMISSIVE_TEXTURE, SPLAT_TEXTURE }; /// Stores cached textures, including render-to-texture targets. class TextureCache : public ResourceCache { @@ -67,7 +67,7 @@ public: /// Returns the ID of the primary framebuffer object's specular texture. GLuint getPrimarySpecularTextureID(); - + /// Enables or disables draw buffers on the primary framebuffer. Note: the primary framebuffer must be bound. void setPrimaryDrawBuffers(bool color, bool normal = false, bool specular = false); diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 4ffd3f6286..7c71bd6c15 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -41,6 +41,15 @@ bool FBXMesh::hasSpecularTexture() const { return false; } +bool FBXMesh::hasEmissiveTexture() const { + foreach (const FBXMeshPart& part, parts) { + if (!part.emissiveTexture.filename.isEmpty()) { + return true; + } + } + return false; +} + QStringList FBXGeometry::getJointNames() const { QStringList names; foreach (const FBXJoint& joint, joints) { @@ -1045,6 +1054,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) QHash diffuseTextures; QHash bumpTextures; QHash specularTextures; + QHash emissiveTextures; QHash localRotations; QHash xComponents; QHash yComponents; @@ -1417,6 +1427,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) ooChildToParent.insert(childID, parentID); } if (connection.properties.at(0) == "OP") { + int counter = 0; QByteArray type = connection.properties.at(3).toByteArray().toLower(); if (type.contains("diffuse")) { diffuseTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); @@ -1438,6 +1449,15 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } else if (type == "d|z") { zComponents.insert(getID(connection.properties, 2), getID(connection.properties, 1)); + + } else if (type.contains("shininess")) { + counter++; + + } else if (type.contains("emissive")) { + emissiveTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); + + } else { + counter++; } } parentMap.insert(getID(connection.properties, 1), getID(connection.properties, 2)); @@ -1666,6 +1686,20 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) if (!specularTextureID.isNull()) { specularTexture = getTexture(specularTextureID, textureNames, textureFilenames, textureContent); } + + FBXTexture emissiveTexture; + QString emissiveTextureID = emissiveTextures.value(childID); + if (!emissiveTextureID.isNull()) { + emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent); + + // FBX files generated by 3DSMax have an intermediate texture parent, apparently + foreach (const QString& childTextureID, childMap.values(diffuseTextureID)) { + if (textureFilenames.contains(childTextureID)) { + emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent); + } + } + } + for (int j = 0; j < extracted.partMaterialTextures.size(); j++) { if (extracted.partMaterialTextures.at(j).first == materialIndex) { @@ -1684,6 +1718,9 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) if (!specularTexture.filename.isNull()) { part.specularTexture = specularTexture; } + if (!emissiveTexture.filename.isNull()) { + part.emissiveTexture = emissiveTexture; + } part.materialID = material.id; } } diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 3c9e918686..9299b88b5a 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -120,6 +120,7 @@ public: FBXTexture diffuseTexture; FBXTexture normalTexture; FBXTexture specularTexture; + FBXTexture emissiveTexture; QString materialID; }; @@ -147,6 +148,7 @@ public: QVector blendshapes; bool hasSpecularTexture() const; + bool hasEmissiveTexture() const; }; /// A single animation frame extracted from an FBX document.