From 764ad724711e6cd5285af19a34b48e0afec2afd2 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 20 Nov 2014 09:54:41 -0800 Subject: [PATCH 1/8] 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. From 87471df7a193a114ed77bf14b8a1e72c4c86fcff Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 21 Nov 2014 18:08:34 -0800 Subject: [PATCH 2/8] First version of the lighmap working --- interface/resources/shaders/model.vert | 6 +- .../resources/shaders/model_normal_map.vert | 6 +- interface/resources/shaders/skin_model.vert | 4 +- .../shaders/skin_model_normal_map.vert | 4 +- interface/src/gpu/Stream.h | 1 + interface/src/renderer/GeometryCache.cpp | 7 +- interface/src/renderer/Model.cpp | 384 +++++++----------- interface/src/renderer/Model.h | 68 ++-- libraries/fbx/src/FBXReader.cpp | 260 +++++++++++- libraries/fbx/src/FBXReader.h | 8 +- libraries/shared/src/Transform.h | 20 +- 11 files changed, 468 insertions(+), 300 deletions(-) diff --git a/interface/resources/shaders/model.vert b/interface/resources/shaders/model.vert index a304187591..5ae6ea1cb6 100644 --- a/interface/resources/shaders/model.vert +++ b/interface/resources/shaders/model.vert @@ -11,6 +11,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +const int MAX_TEXCOORDS = 2; + +uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; + // the interpolated normal varying vec4 normal; @@ -22,7 +26,7 @@ void main(void) { gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = gl_MultiTexCoord0; + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); // use standard pipeline transform gl_Position = ftransform(); diff --git a/interface/resources/shaders/model_normal_map.vert b/interface/resources/shaders/model_normal_map.vert index 9fde196b06..2e98b8c4fc 100644 --- a/interface/resources/shaders/model_normal_map.vert +++ b/interface/resources/shaders/model_normal_map.vert @@ -11,6 +11,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +const int MAX_TEXCOORDS = 2; + +uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; + // the tangent vector attribute vec3 tangent; @@ -29,7 +33,7 @@ void main(void) { gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = gl_MultiTexCoord0; + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); // use standard pipeline transform gl_Position = ftransform(); diff --git a/interface/resources/shaders/skin_model.vert b/interface/resources/shaders/skin_model.vert index 072bf3c336..a8c25e885b 100644 --- a/interface/resources/shaders/skin_model.vert +++ b/interface/resources/shaders/skin_model.vert @@ -11,10 +11,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +const int MAX_TEXCOORDS = 2; const int MAX_CLUSTERS = 128; const int INDICES_PER_VERTEX = 4; uniform mat4 clusterMatrices[MAX_CLUSTERS]; +uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; attribute vec4 clusterIndices; attribute vec4 clusterWeights; @@ -38,7 +40,7 @@ void main(void) { gl_FrontColor = gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = gl_MultiTexCoord0; + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); gl_Position = gl_ModelViewProjectionMatrix * position; } diff --git a/interface/resources/shaders/skin_model_normal_map.vert b/interface/resources/shaders/skin_model_normal_map.vert index ac6c77f7cb..bbe5da35af 100644 --- a/interface/resources/shaders/skin_model_normal_map.vert +++ b/interface/resources/shaders/skin_model_normal_map.vert @@ -11,10 +11,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +const int MAX_TEXCOORDS = 2; const int MAX_CLUSTERS = 128; const int INDICES_PER_VERTEX = 4; uniform mat4 clusterMatrices[MAX_CLUSTERS]; +uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; // the tangent vector attribute vec3 tangent; @@ -46,7 +48,7 @@ void main(void) { gl_FrontColor = gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = gl_MultiTexCoord0; + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); gl_Position = gl_ModelViewProjectionMatrix * interpolatedPosition; } diff --git a/interface/src/gpu/Stream.h b/interface/src/gpu/Stream.h index 84b2edc5f3..d024182531 100644 --- a/interface/src/gpu/Stream.h +++ b/interface/src/gpu/Stream.h @@ -34,6 +34,7 @@ public: TANGENT, SKIN_CLUSTER_INDEX, SKIN_CLUSTER_WEIGHT, + TEXCOORD1, NUM_INPUT_SLOTS, }; diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index b0636d3321..04ff7bdecd 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -964,7 +964,8 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { 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 texCoords1Offset = texCoordsOffset + mesh.texCoords.size() * sizeof(glm::vec2); + int clusterIndicesOffset = texCoords1Offset + mesh.texCoords1.size() * sizeof(glm::vec2); int clusterWeightsOffset = clusterIndicesOffset + mesh.clusterIndices.size() * sizeof(glm::vec4); networkMesh._vertexBuffer->resize(clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4)); @@ -977,6 +978,8 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { networkMesh._vertexBuffer->setSubData(colorsOffset, mesh.colors.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.colors.constData()); networkMesh._vertexBuffer->setSubData(texCoordsOffset, mesh.texCoords.size() * sizeof(glm::vec2), (gpu::Resource::Byte*) mesh.texCoords.constData()); + networkMesh._vertexBuffer->setSubData(texCoords1Offset, + mesh.texCoords1.size() * sizeof(glm::vec2), (gpu::Resource::Byte*) mesh.texCoords1.constData()); networkMesh._vertexBuffer->setSubData(clusterIndicesOffset, mesh.clusterIndices.size() * sizeof(glm::vec4), (gpu::Resource::Byte*) mesh.clusterIndices.constData()); networkMesh._vertexBuffer->setSubData(clusterWeightsOffset, @@ -989,6 +992,7 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { if (mesh.tangents.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, tangentsOffset, sizeof(glm::vec3)); if (mesh.colors.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, colorsOffset, sizeof(glm::vec3)); if (mesh.texCoords.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, texCoordsOffset, sizeof(glm::vec2)); + if (mesh.texCoords1.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, texCoords1Offset, sizeof(glm::vec2)); if (mesh.clusterIndices.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, clusterIndicesOffset, sizeof(glm::vec4)); if (mesh.clusterWeights.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, clusterWeightsOffset, sizeof(glm::vec4)); @@ -999,6 +1003,7 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { if (mesh.tangents.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::TANGENT, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); if (mesh.colors.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::COLOR, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RGB)); if (mesh.texCoords.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::TEXCOORD, channelNum++, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV)); + if (mesh.texCoords1.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::TEXCOORD1, channelNum++, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV)); if (mesh.clusterIndices.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::SKIN_CLUSTER_INDEX, channelNum++, gpu::Element(gpu::VEC4, gpu::NFLOAT, gpu::XYZW)); if (mesh.clusterWeights.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT, channelNum++, gpu::Element(gpu::VEC4, gpu::NFLOAT, gpu::XYZW)); } diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index a4c4e51d69..d2a2378689 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -70,10 +70,10 @@ ProgramObject Model::_specularMapProgram; ProgramObject Model::_normalSpecularMapProgram; ProgramObject Model::_translucentProgram; -ProgramObject Model::_emissiveProgram; -ProgramObject Model::_emissiveNormalMapProgram; -ProgramObject Model::_emissiveSpecularMapProgram; -ProgramObject Model::_emissiveNormalSpecularMapProgram; +ProgramObject Model::_lightmapProgram; +ProgramObject Model::_lightmapNormalMapProgram; +ProgramObject Model::_lightmapSpecularMapProgram; +ProgramObject Model::_lightmapNormalSpecularMapProgram; ProgramObject Model::_shadowProgram; @@ -83,11 +83,6 @@ 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; @@ -96,10 +91,10 @@ 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::Locations Model::_lightmapLocations; +Model::Locations Model::_lightmapNormalMapLocations; +Model::Locations Model::_lightmapSpecularMapLocations; +Model::Locations Model::_lightmapNormalSpecularMapLocations; Model::SkinLocations Model::_skinLocations; Model::SkinLocations Model::_skinNormalMapLocations; @@ -108,11 +103,6 @@ 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 @@ -160,17 +150,40 @@ void Model::initProgram(ProgramObject& program, Model::Locations& locations, int glBindAttribLocation(program.programId(), gpu::Stream::TANGENT, "tangent"); + glBindAttribLocation(program.programId(), gpu::Stream::TEXCOORD1, "texcoord1"); + glLinkProgram(program.programId()); locations.tangent = program.attributeLocation("tangent"); locations.alphaThreshold = program.uniformLocation("alphaThreshold"); + locations.texcoordMatrices = program.uniformLocation("texcoordMatrices"); + + program.setUniformValue("diffuseMap", 0); program.setUniformValue("normalMap", 1); - program.setUniformValue("specularMap", specularTextureUnit); + int loc = program.uniformLocation("specularMap"); + if (loc >= 0) { + program.setUniformValue("specularMap", 2); + locations.specularTextureUnit = 2; + } else { + locations.specularTextureUnit = -1; + } + + loc = program.uniformLocation("emissiveMap"); + if (loc >= 0) { + program.setUniformValue("emissiveMap", 3); + locations.emissiveTextureUnit = 3; + } else { + locations.emissiveTextureUnit = -1; + } + + if (!program.isLinked()) { + program.release(); + } program.release(); @@ -289,37 +302,37 @@ void Model::init() { 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(); + // Lightmap + _lightmapProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model_lightmap.vert"); + _lightmapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_lightmap.frag"); + _lightmapProgram.link(); - initProgram(_emissiveProgram, _emissiveLocations); + initProgram(_lightmapProgram, _lightmapLocations); - _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(); + _lightmapNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/model_lightmap_normal_map.vert"); + _lightmapNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_lightmap_normal_map.frag"); + _lightmapNormalMapProgram.link(); - initProgram(_emissiveNormalMapProgram, _emissiveNormalMapLocations); + initProgram(_lightmapNormalMapProgram, _lightmapNormalMapLocations); - _emissiveSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/model.vert"); - _emissiveSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/model_emissive_specular_map.frag"); - _emissiveSpecularMapProgram.link(); + _lightmapSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/model_lightmap.vert"); + _lightmapSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_lightmap_specular_map.frag"); + _lightmapSpecularMapProgram.link(); - initProgram(_emissiveSpecularMapProgram, _emissiveSpecularMapLocations); + initProgram(_lightmapSpecularMapProgram, _lightmapSpecularMapLocations); - _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(); + _lightmapNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/model_lightmap_normal_map.vert"); + _lightmapNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_lightmap_normal_specular_map.frag"); + _lightmapNormalSpecularMapProgram.link(); - initProgram(_emissiveNormalSpecularMapProgram, _emissiveNormalSpecularMapLocations, 2); - // end emissive + initProgram(_lightmapNormalSpecularMapProgram, _lightmapNormalSpecularMapLocations, 2); + // end lightmap _shadowProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model_shadow.vert"); @@ -374,36 +387,6 @@ void Model::init() { 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); - } } @@ -716,13 +699,9 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* 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); @@ -1666,13 +1645,9 @@ void Model::endScene(RenderMode mode, RenderArgs* 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); @@ -1793,15 +1768,10 @@ void Model::segregateMeshGroups() { _meshesOpaqueTangentsSpecularSkinned.clear(); _meshesOpaqueSpecularSkinned.clear(); - _meshesOpaqueEmissiveTangents.clear(); - _meshesOpaqueEmissive.clear(); - _meshesOpaqueEmissiveTangentsSpecular.clear(); - _meshesOpaqueEmissiveSpecular.clear(); - - _meshesOpaqueEmissiveTangentsSkinned.clear(); - _meshesOpaqueEmissiveSkinned.clear(); - _meshesOpaqueEmissiveTangentsSpecularSkinned.clear(); - _meshesOpaqueEmissiveSpecularSkinned.clear(); + _meshesOpaqueLightmapTangents.clear(); + _meshesOpaqueLightmap.clear(); + _meshesOpaqueLightmapTangentsSpecular.clear(); + _meshesOpaqueLightmapSpecular.clear(); _unsortedMeshesTranslucentTangents.clear(); _unsortedMeshesTranslucent.clear(); @@ -1823,15 +1793,10 @@ void Model::segregateMeshGroups() { _unsortedMeshesOpaqueTangentsSpecularSkinned.clear(); _unsortedMeshesOpaqueSpecularSkinned.clear(); - _unsortedMeshesOpaqueEmissiveTangents.clear(); - _unsortedMeshesOpaqueEmissive.clear(); - _unsortedMeshesOpaqueEmissiveTangentsSpecular.clear(); - _unsortedMeshesOpaqueEmissiveSpecular.clear(); - - _unsortedMeshesOpaqueEmissiveTangentsSkinned.clear(); - _unsortedMeshesOpaqueEmissiveSkinned.clear(); - _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned.clear(); - _unsortedMeshesOpaqueEmissiveSpecularSkinned.clear(); + _unsortedMeshesOpaqueLightmapTangents.clear(); + _unsortedMeshesOpaqueLightmap.clear(); + _unsortedMeshesOpaqueLightmapTangentsSpecular.clear(); + _unsortedMeshesOpaqueLightmapSpecular.clear(); const FBXGeometry& geometry = _geometry->getFBXGeometry(); const QVector& networkMeshes = _geometry->getMeshes(); @@ -1846,7 +1811,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 haslightmap = mesh.hasEmissiveTexture(); bool isSkinned = state.clusterMatrices.size() > 1; QString materialID; @@ -1865,7 +1830,7 @@ void Model::segregateMeshGroups() { qDebug() << "materialID:" << materialID << "parts:" << mesh.parts.size(); } - if ( !hasEmissive) { + if ( !haslightmap) { if (translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { _unsortedMeshesTranslucent.insertMulti(materialID, i); @@ -1935,35 +1900,20 @@ void Model::segregateMeshGroups() { } else { if (!translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { - _unsortedMeshesOpaqueEmissive.insertMulti(materialID, i); + _unsortedMeshesOpaqueLightmap.insertMulti(materialID, i); } else if (!translucentMesh && hasTangents && !hasSpecular && !isSkinned) { - _unsortedMeshesOpaqueEmissiveTangents.insertMulti(materialID, i); + _unsortedMeshesOpaqueLightmapTangents.insertMulti(materialID, i); } else if (!translucentMesh && hasTangents && hasSpecular && !isSkinned) { - _unsortedMeshesOpaqueEmissiveTangentsSpecular.insertMulti(materialID, i); + _unsortedMeshesOpaqueLightmapTangentsSpecular.insertMulti(materialID, i); } else if (!translucentMesh && !hasTangents && hasSpecular && !isSkinned) { - _unsortedMeshesOpaqueEmissiveSpecular.insertMulti(materialID, i); + _unsortedMeshesOpaqueLightmapSpecular.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???"; } @@ -2034,36 +1984,20 @@ void Model::segregateMeshGroups() { _meshesOpaqueSpecularSkinned.append(i); } - foreach(int i, _unsortedMeshesOpaqueEmissive) { - _meshesOpaqueEmissive.append(i); + foreach(int i, _unsortedMeshesOpaqueLightmap) { + _meshesOpaqueLightmap.append(i); } - foreach(int i, _unsortedMeshesOpaqueEmissiveTangents) { - _meshesOpaqueEmissiveTangents.append(i); + foreach(int i, _unsortedMeshesOpaqueLightmapTangents) { + _meshesOpaqueLightmapTangents.append(i); } - foreach(int i, _unsortedMeshesOpaqueEmissiveTangentsSpecular) { - _meshesOpaqueEmissiveTangentsSpecular.append(i); + foreach(int i, _unsortedMeshesOpaqueLightmapTangentsSpecular) { + _meshesOpaqueLightmapTangentsSpecular.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); + foreach(int i, _unsortedMeshesOpaqueLightmapSpecular) { + _meshesOpaqueLightmapSpecular.append(i); } _unsortedMeshesTranslucentTangents.clear(); @@ -2086,20 +2020,15 @@ void Model::segregateMeshGroups() { _unsortedMeshesOpaqueTangentsSpecularSkinned.clear(); _unsortedMeshesOpaqueSpecularSkinned.clear(); - _unsortedMeshesOpaqueEmissiveTangents.clear(); - _unsortedMeshesOpaqueEmissive.clear(); - _unsortedMeshesOpaqueEmissiveTangentsSpecular.clear(); - _unsortedMeshesOpaqueEmissiveSpecular.clear(); - - _unsortedMeshesOpaqueEmissiveTangentsSkinned.clear(); - _unsortedMeshesOpaqueEmissiveSkinned.clear(); - _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned.clear(); - _unsortedMeshesOpaqueEmissiveSpecularSkinned.clear(); + _unsortedMeshesOpaqueLightmapTangents.clear(); + _unsortedMeshesOpaqueLightmap.clear(); + _unsortedMeshesOpaqueLightmapTangentsSpecular.clear(); + _unsortedMeshesOpaqueLightmapSpecular.clear(); _meshGroupsKnown = true; } -QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned) { +QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned) { PROFILE_RANGE(__FUNCTION__); // depending on which parameters we were called with, pick the correct mesh group to render @@ -2121,39 +2050,31 @@ QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool h } else if (translucent && !hasTangents && hasSpecular && isSkinned) { whichList = &_meshesTranslucentSpecularSkinned; - } else if (!translucent && !hasEmissive && !hasTangents && !hasSpecular && !isSkinned) { + } else if (!translucent && !hasLightmap && !hasTangents && !hasSpecular && !isSkinned) { whichList = &_meshesOpaque; - } else if (!translucent && !hasEmissive && hasTangents && !hasSpecular && !isSkinned) { + } else if (!translucent && !hasLightmap && hasTangents && !hasSpecular && !isSkinned) { whichList = &_meshesOpaqueTangents; - } else if (!translucent && !hasEmissive && hasTangents && hasSpecular && !isSkinned) { + } else if (!translucent && !hasLightmap && hasTangents && hasSpecular && !isSkinned) { whichList = &_meshesOpaqueTangentsSpecular; - } else if (!translucent && !hasEmissive && !hasTangents && hasSpecular && !isSkinned) { + } else if (!translucent && !hasLightmap && !hasTangents && hasSpecular && !isSkinned) { whichList = &_meshesOpaqueSpecular; - } else if (!translucent && !hasEmissive && hasTangents && !hasSpecular && isSkinned) { + } else if (!translucent && !hasLightmap && hasTangents && !hasSpecular && isSkinned) { whichList = &_meshesOpaqueTangentsSkinned; - } else if (!translucent && !hasEmissive && !hasTangents && !hasSpecular && isSkinned) { + } else if (!translucent && !hasLightmap && !hasTangents && !hasSpecular && isSkinned) { whichList = &_meshesOpaqueSkinned; - } else if (!translucent && !hasEmissive && hasTangents && hasSpecular && isSkinned) { + } else if (!translucent && !hasLightmap && hasTangents && hasSpecular && isSkinned) { whichList = &_meshesOpaqueTangentsSpecularSkinned; - } else if (!translucent && !hasEmissive && !hasTangents && hasSpecular && isSkinned) { + } else if (!translucent && !hasLightmap && !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 if (!translucent && hasLightmap && !hasTangents && !hasSpecular && !isSkinned) { + whichList = &_meshesOpaqueLightmap; + } else if (!translucent && hasLightmap && hasTangents && !hasSpecular && !isSkinned) { + whichList = &_meshesOpaqueLightmapTangents; + } else if (!translucent && hasLightmap && hasTangents && hasSpecular && !isSkinned) { + whichList = &_meshesOpaqueLightmapTangentsSpecular; + } else if (!translucent && hasLightmap && !hasTangents && hasSpecular && !isSkinned) { + whichList = &_meshesOpaqueLightmapSpecular; } else { qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???"; @@ -2162,15 +2083,13 @@ QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool h } void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, - SkinLocations*& skinLocations, GLenum& specularTextureUnit, GLenum& emissiveTextureUnit) { + bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, + Locations*& locations, SkinLocations*& skinLocations) { ProgramObject* program = &_program; - Locations* locations = &_locations; + locations = &_locations; ProgramObject* skinProgram = &_skinProgram; skinLocations = &_skinLocations; - specularTextureUnit = 0; - emissiveTextureUnit = 0; if (mode == SHADOW_RENDER_MODE) { program = &_shadowProgram; skinProgram = &_skinShadowProgram; @@ -2181,35 +2100,29 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f skinProgram = &_skinTranslucentProgram; skinLocations = &_skinTranslucentLocations; - } else if (hasEmissive) { + } else if (hasLightmap) { if (hasTangents) { if (hasSpecular) { - program = &_emissiveNormalSpecularMapProgram; - locations = &_emissiveNormalSpecularMapLocations; - skinProgram = &_skinEmissiveNormalSpecularMapProgram; - skinLocations = &_skinEmissiveNormalSpecularMapLocations; - specularTextureUnit = GL_TEXTURE2; - emissiveTextureUnit = GL_TEXTURE3; + program = &_lightmapNormalSpecularMapProgram; + locations = &_lightmapNormalSpecularMapLocations; + skinProgram = NULL; + skinLocations = NULL; } else { - program = &_emissiveNormalMapProgram; - locations = &_emissiveNormalMapLocations; - skinProgram = &_skinEmissiveNormalMapProgram; - skinLocations = &_skinEmissiveNormalMapLocations; - emissiveTextureUnit = GL_TEXTURE3; + program = &_lightmapNormalMapProgram; + locations = &_lightmapNormalMapLocations; + skinProgram = NULL; + skinLocations = NULL; } } else if (hasSpecular) { - program = &_emissiveSpecularMapProgram; - locations = &_emissiveSpecularMapLocations; - skinProgram = &_skinEmissiveSpecularMapProgram; - skinLocations = &_skinEmissiveSpecularMapLocations; - specularTextureUnit = GL_TEXTURE1; - emissiveTextureUnit = GL_TEXTURE3; + program = &_lightmapSpecularMapProgram; + locations = &_lightmapSpecularMapLocations; + skinProgram = NULL; + skinLocations = NULL; } else { - program = &_emissiveProgram; - locations = &_emissiveLocations; - skinProgram = &_skinEmissiveProgram; - skinLocations = &_skinEmissiveLocations; - emissiveTextureUnit = GL_TEXTURE3; + program = &_lightmapProgram; + locations = &_lightmapLocations; + skinProgram = NULL; + skinLocations = NULL; } } else { if (hasTangents) { @@ -2218,7 +2131,6 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f locations = &_normalSpecularMapLocations; skinProgram = &_skinNormalSpecularMapProgram; skinLocations = &_skinNormalSpecularMapLocations; - specularTextureUnit = GL_TEXTURE2; } else { program = &_normalMapProgram; locations = &_normalMapLocations; @@ -2230,7 +2142,6 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f locations = &_specularMapLocations; skinProgram = &_skinSpecularMapProgram; skinLocations = &_skinSpecularMapLocations; - specularTextureUnit = GL_TEXTURE1; } } @@ -2240,6 +2151,7 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f if (isSkinned) { activeProgram = skinProgram; activeLocations = skinLocations; + locations = skinLocations; } // This code replace the "bind()" on the QGLProgram if (!activeProgram->isLinked()) { @@ -2251,27 +2163,26 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f } int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { + bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { PROFILE_RANGE(__FUNCTION__); int meshPartsRendered = 0; bool pickProgramsNeeded = true; + Locations* locations; SkinLocations* skinLocations; - GLenum specularTextureUnit; - GLenum emissiveTextureUnit; foreach(Model* model, _modelsInScene) { - QVector* whichList = model->pickMeshList(translucent, alphaThreshold, hasEmissive, hasTangents, hasSpecular, isSkinned); + QVector* whichList = model->pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned); if (whichList) { QVector& list = *whichList; if (list.size() > 0) { if (pickProgramsNeeded) { - pickPrograms(batch, mode, translucent, alphaThreshold, hasEmissive, hasTangents, hasSpecular, isSkinned, args, skinLocations, specularTextureUnit, emissiveTextureUnit); + pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, args, locations, skinLocations); pickProgramsNeeded = false; } model->setupBatchTransform(batch); - meshPartsRendered += model->renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, skinLocations, specularTextureUnit, emissiveTextureUnit); + meshPartsRendered += model->renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, locations, skinLocations); GLBATCH(glPopMatrix)(); } } @@ -2284,12 +2195,12 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool } int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { + bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { PROFILE_RANGE(__FUNCTION__); int meshPartsRendered = 0; - QVector* whichList = pickMeshList(translucent, alphaThreshold, hasEmissive, hasTangents, hasSpecular, isSkinned); + QVector* whichList = pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned); if (!whichList) { qDebug() << "unexpected!!! we don't know which list of meshes to render..."; @@ -2302,11 +2213,10 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl return 0; } + Locations* locations; SkinLocations* skinLocations; - GLenum 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); + pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, args, locations, skinLocations); + meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, locations, skinLocations); GLBATCH(glUseProgram)(0); return meshPartsRendered; @@ -2314,7 +2224,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, GLenum emissiveTextureUnit) { + Locations* locations, SkinLocations* skinLocations) { PROFILE_RANGE(__FUNCTION__); bool dontCullOutOfViewMeshParts = Menu::getInstance()->isOptionChecked(MenuOption::DontCullOutOfViewMeshParts); bool cullTooSmallMeshParts = !Menu::getInstance()->isOptionChecked(MenuOption::DontCullTooSmallMeshParts); @@ -2431,7 +2341,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glMaterialfv)(GL_FRONT, GL_DIFFUSE, (const float*)&diffuse); GLBATCH(glMaterialfv)(GL_FRONT, GL_SPECULAR, (const float*)&specular); GLBATCH(glMaterialf)(GL_FRONT, GL_SHININESS, (part.shininess > 128.0f ? 128.0f: part.shininess)); - + Texture* diffuseMap = networkPart.diffuseTexture.data(); if (mesh.isEye && diffuseMap) { diffuseMap = (_dilatedTextures[i][j] = @@ -2439,7 +2349,18 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod } GLBATCH(glBindTexture)(GL_TEXTURE_2D, !diffuseMap ? Application::getInstance()->getTextureCache()->getWhiteTextureID() : diffuseMap->getID()); - + + if (locations->texcoordMatrices >= 0) { + glm::mat4 texcoordTransform[2]; + if (!part.diffuseTexture.transform.isIdentity()) { + part.diffuseTexture.transform.getMatrix(texcoordTransform[0]); + } + if (!part.emissiveTexture.transform.isIdentity()) { + part.emissiveTexture.transform.getMatrix(texcoordTransform[1]); + } + GLBATCH(glUniformMatrix4fv)(locations->texcoordMatrices, 2, false, (const float*) &texcoordTransform); + } + if (!mesh.tangents.isEmpty()) { GLBATCH(glActiveTexture)(GL_TEXTURE1); Texture* normalMap = networkPart.normalTexture.data(); @@ -2448,19 +2369,20 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glActiveTexture)(GL_TEXTURE0); } - if (specularTextureUnit) { - GLBATCH(glActiveTexture)(specularTextureUnit); + if (locations->specularTextureUnit >= 0) { + GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->specularTextureUnit); Texture* specularMap = networkPart.specularTexture.data(); GLBATCH(glBindTexture)(GL_TEXTURE_2D, !specularMap ? Application::getInstance()->getTextureCache()->getWhiteTextureID() : specularMap->getID()); GLBATCH(glActiveTexture)(GL_TEXTURE0); } - if (emissiveTextureUnit) { - GLBATCH(glActiveTexture)(emissiveTextureUnit); + if (locations->emissiveTextureUnit >= 0) { + GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->emissiveTextureUnit); Texture* emissiveMap = networkPart.emissiveTexture.data(); GLBATCH(glBindTexture)(GL_TEXTURE_2D, !emissiveMap ? Application::getInstance()->getTextureCache()->getWhiteTextureID() : emissiveMap->getID()); + // GLBATCH(glBindTexture)(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getWhiteTextureID()); GLBATCH(glActiveTexture)(GL_TEXTURE0); } @@ -2498,14 +2420,14 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glActiveTexture)(GL_TEXTURE0); } - if (specularTextureUnit) { - GLBATCH(glActiveTexture)(specularTextureUnit); + if (locations->specularTextureUnit >= 0) { + GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->specularTextureUnit); GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); GLBATCH(glActiveTexture)(GL_TEXTURE0); } - if (emissiveTextureUnit) { - GLBATCH(glActiveTexture)(emissiveTextureUnit); + if (locations->emissiveTextureUnit >= 0) { + GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->emissiveTextureUnit); GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); GLBATCH(glActiveTexture)(GL_TEXTURE0); } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index c1ae190a1e..7a3457423e 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -304,10 +304,10 @@ private: static ProgramObject _normalSpecularMapProgram; static ProgramObject _translucentProgram; - static ProgramObject _emissiveProgram; - static ProgramObject _emissiveNormalMapProgram; - static ProgramObject _emissiveSpecularMapProgram; - static ProgramObject _emissiveNormalSpecularMapProgram; + static ProgramObject _lightmapProgram; + static ProgramObject _lightmapNormalMapProgram; + static ProgramObject _lightmapSpecularMapProgram; + static ProgramObject _lightmapNormalSpecularMapProgram; static ProgramObject _shadowProgram; @@ -317,11 +317,6 @@ private: static ProgramObject _skinNormalSpecularMapProgram; static ProgramObject _skinTranslucentProgram; - static ProgramObject _skinEmissiveProgram; - static ProgramObject _skinEmissiveNormalMapProgram; - static ProgramObject _skinEmissiveSpecularMapProgram; - static ProgramObject _skinEmissiveNormalSpecularMapProgram; - static ProgramObject _skinShadowProgram; static int _normalMapTangentLocation; @@ -331,6 +326,9 @@ private: public: int tangent; int alphaThreshold; + int texcoordMatrices; + int specularTextureUnit; + int emissiveTextureUnit; }; static Locations _locations; @@ -339,10 +337,10 @@ private: static Locations _normalSpecularMapLocations; static Locations _translucentLocations; - static Locations _emissiveLocations; - static Locations _emissiveNormalMapLocations; - static Locations _emissiveSpecularMapLocations; - static Locations _emissiveNormalSpecularMapLocations; + static Locations _lightmapLocations; + static Locations _lightmapNormalMapLocations; + static Locations _lightmapSpecularMapLocations; + static Locations _lightmapNormalSpecularMapLocations; static void initProgram(ProgramObject& program, Locations& locations, int specularTextureUnit = 1); @@ -350,7 +348,7 @@ private: public: int clusterMatrices; int clusterIndices; - int clusterWeights; + int clusterWeights; }; static SkinLocations _skinLocations; @@ -360,11 +358,6 @@ private: 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; @@ -396,15 +389,10 @@ private: QMap _unsortedMeshesOpaqueTangentsSpecularSkinned; QMap _unsortedMeshesOpaqueSpecularSkinned; - QMap _unsortedMeshesOpaqueEmissive; - QMap _unsortedMeshesOpaqueEmissiveTangents; - QMap _unsortedMeshesOpaqueEmissiveTangentsSpecular; - QMap _unsortedMeshesOpaqueEmissiveSpecular; - - QMap _unsortedMeshesOpaqueEmissiveSkinned; - QMap _unsortedMeshesOpaqueEmissiveTangentsSkinned; - QMap _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned; - QMap _unsortedMeshesOpaqueEmissiveSpecularSkinned; + QMap _unsortedMeshesOpaqueLightmap; + QMap _unsortedMeshesOpaqueLightmapTangents; + QMap _unsortedMeshesOpaqueLightmapTangentsSpecular; + QMap _unsortedMeshesOpaqueLightmapSpecular; QVector _meshesTranslucent; QVector _meshesTranslucentTangents; @@ -426,15 +414,11 @@ private: QVector _meshesOpaqueTangentsSpecularSkinned; QVector _meshesOpaqueSpecularSkinned; - QVector _meshesOpaqueEmissive; - QVector _meshesOpaqueEmissiveTangents; - QVector _meshesOpaqueEmissiveTangentsSpecular; - QVector _meshesOpaqueEmissiveSpecular; + QVector _meshesOpaqueLightmap; + QVector _meshesOpaqueLightmapTangents; + QVector _meshesOpaqueLightmapTangentsSpecular; + QVector _meshesOpaqueLightmapSpecular; - QVector _meshesOpaqueEmissiveSkinned; - QVector _meshesOpaqueEmissiveTangentsSkinned; - QVector _meshesOpaqueEmissiveTangentsSpecularSkinned; - QVector _meshesOpaqueEmissiveSpecularSkinned; // Scene rendering support static QVector _modelsInScene; @@ -447,19 +431,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 hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL); + bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL); void setupBatchTransform(gpu::Batch& batch); - QVector* pickMeshList(bool translucent, float alphaThreshold, bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned); + QVector* pickMeshList(bool translucent, float alphaThreshold, bool hasLightmap, 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, GLenum emissiveTextureUnit); + RenderArgs* args, Locations* locations, SkinLocations* skinLocations); static void pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, - SkinLocations*& skinLocations, GLenum& specularTextureUnit, GLenum& emissiveTextureUnit); + bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, + Locations*& locations, SkinLocations*& skinLocations); static int renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args); + bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args); }; diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 2a97c50fea..130f1db550 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -32,6 +32,48 @@ using namespace std; +struct TextureParam { + glm::vec2 UVTranslation; + glm::vec2 UVScaling; + glm::vec4 cropping; + std::string UVSet; + + glm::vec3 translation; + glm::vec3 rotation; + glm::vec3 scaling; + uint8_t alphaSource; + uint8_t currentTextureBlendMode; + bool useMaterial; + + template + bool assign(T& ref, const T& v) { + if (ref == v) { + return false; + } else { + ref = v; + isDefault = false; + return true; + } + } + + bool isDefault; + + TextureParam() : + UVTranslation(0.0f), + UVScaling(1.0f), + cropping(0.0f), + UVSet("map1"), + translation(0.0f), + rotation(0.0f), + scaling(1.0f), + alphaSource(0), + currentTextureBlendMode(0), + useMaterial(true), + isDefault(true) + {} +}; + + bool FBXMesh::hasSpecularTexture() const { foreach (const FBXMeshPart& part, parts) { if (!part.specularTexture.filename.isEmpty()) { @@ -718,6 +760,7 @@ class Vertex { public: int originalIndex; glm::vec2 texCoord; + glm::vec2 texCoord1; }; uint qHash(const Vertex& vertex, uint seed = 0) { @@ -725,7 +768,7 @@ uint qHash(const Vertex& vertex, uint seed = 0) { } bool operator==(const Vertex& v1, const Vertex& v2) { - return v1.originalIndex == v2.originalIndex && v1.texCoord == v2.texCoord; + return v1.originalIndex == v2.originalIndex && v1.texCoord == v2.texCoord && v1.texCoord1 == v2.texCoord1; } class ExtractedMesh { @@ -734,6 +777,16 @@ public: QMultiHash newIndices; QVector > blendshapeIndexMaps; QVector > partMaterialTextures; + QHash texcoordSetMap; + std::map texcoordSetMap2; +}; + +class AttributeData { +public: + QVector texCoords; + QVector texCoordIndices; + std::string name; + int index; }; class MeshData { @@ -748,6 +801,8 @@ public: QVector texCoordIndices; QHash indices; + + std::vector attributes; }; void appendIndex(MeshData& data, QVector& indices, int index) { @@ -789,6 +844,20 @@ void appendIndex(MeshData& data, QVector& indices, int index) { vertex.texCoord = data.texCoords.at(texCoordIndex); } } + + bool hasMoreTexcoords = (data.attributes.size() > 1); + if (hasMoreTexcoords) { + if (data.attributes[1].texCoordIndices.empty()) { + if (index < data.attributes[1].texCoords.size()) { + vertex.texCoord1 = data.attributes[1].texCoords.at(index); + } + } else if (index < data.attributes[1].texCoordIndices.size()) { + int texCoordIndex = data.attributes[1].texCoordIndices.at(index); + if (texCoordIndex >= 0 && texCoordIndex < data.attributes[1].texCoords.size()) { + vertex.texCoord1 = data.attributes[1].texCoords.at(texCoordIndex); + } + } + } QHash::const_iterator it = data.indices.find(vertex); if (it == data.indices.constEnd()) { @@ -799,7 +868,7 @@ void appendIndex(MeshData& data, QVector& indices, int index) { data.extracted.mesh.vertices.append(position); data.extracted.mesh.normals.append(normal); data.extracted.mesh.texCoords.append(vertex.texCoord); - + if (hasMoreTexcoords) { data.extracted.mesh.texCoords1.append(vertex.texCoord1); } } else { indices.append(*it); data.extracted.mesh.normals[*it] += normal; @@ -838,13 +907,61 @@ ExtractedMesh extractMesh(const FBXNode& object) { // hack to work around wacky Makehuman exports data.normalsByVertex = true; } - } else if (child.name == "LayerElementUV" && child.properties.at(0).toInt() == 0) { - foreach (const FBXNode& subdata, child.children) { - if (subdata.name == "UV") { - data.texCoords = createVec2Vector(getDoubleVector(subdata)); + } else if (child.name == "LayerElementUV") { + if (child.properties.at(0).toInt() == 0) { + AttributeData attrib; + attrib.index = child.properties.at(0).toInt(); + int unknown = 0; + foreach (const FBXNode& subdata, child.children) { + if (subdata.name == "UV") { + data.texCoords = createVec2Vector(getDoubleVector(subdata)); + attrib.texCoords = createVec2Vector(getDoubleVector(subdata)); + } else if (subdata.name == "UVIndex") { + data.texCoordIndices = getIntVector(subdata); + attrib.texCoordIndices = getIntVector(subdata); + } else if (subdata.name == "Name") { + attrib.name = subdata.properties.at(0).toString().toStdString(); + } else { + std::string subname = subdata.name.data(); + if (subdata.name == "Version") { + } else if (subdata.name == "MappingInformationType") { + } else if (subdata.name == "ReferenceInformationType") { + } else { + unknown++; + } + } + } + data.extracted.texcoordSetMap.insert(QString(attrib.name.c_str()), data.attributes.size()); + data.attributes.push_back(attrib); + } else { + AttributeData attrib; + attrib.index = child.properties.at(0).toInt(); + int unknown = 0; + foreach (const FBXNode& subdata, child.children) { + if (subdata.name == "UV") { + attrib.texCoords = createVec2Vector(getDoubleVector(subdata)); + } else if (subdata.name == "UVIndex") { + attrib.texCoordIndices = getIntVector(subdata); + } else if (subdata.name == "Name") { + attrib.name = subdata.properties.at(0).toString().toStdString(); + } else { + std::string subname = subdata.name.data(); + if (subdata.name == "Version") { + } else if (subdata.name == "MappingInformationType") { + } else if (subdata.name == "ReferenceInformationType") { + } else { + unknown++; + } + } + } - } else if (subdata.name == "UVIndex") { - data.texCoordIndices = getIntVector(subdata); + QHash::iterator it = data.extracted.texcoordSetMap.find(QString(attrib.name.c_str())); + if (it == data.extracted.texcoordSetMap.end()) { + data.extracted.texcoordSetMap.insert(QString(attrib.name.c_str()), data.attributes.size()); + data.attributes.push_back(attrib); + } else { + // WTF same names for different UVs? + unknown = data.attributes.size(); } } } else if (child.name == "LayerElementMaterial") { @@ -1014,11 +1131,27 @@ public: FBXTexture getTexture(const QString& textureID, const QHash& textureNames, const QHash& textureFilenames, - const QHash& textureContent) { + const QHash& textureContent, + const QHash& textureParams) { FBXTexture texture; texture.filename = textureFilenames.value(textureID); texture.name = textureNames.value(textureID); texture.content = textureContent.value(texture.filename); + texture.transform.setIdentity(); + texture.texcoordSet = 0; + QHash::const_iterator it = textureParams.constFind(textureID); + if (it != textureParams.end()) { + const TextureParam& p = (*it); + texture.transform.setTranslation(p.translation); + texture.transform.setRotation(glm::quat(glm::radians(p.rotation))); + texture.transform.setScale(p.scaling); + if (p.UVSet != "map1" || (p.UVSet != "UVSet0")) { + texture.texcoordSet = 1; + } + + texture.texcoordSetName = p.UVSet; + + } return texture; } @@ -1034,6 +1167,23 @@ bool checkMaterialsHaveTextures(const QHash& materials, return false; } +int matchTextureUVSetToAttributeChannel(const std::string& texUVSetName, const QHash& texcoordChannels) { + if (texUVSetName.empty()) { + return 0; + } else { + QHash::const_iterator tcUnit = texcoordChannels.find(QString(texUVSetName.c_str())); + if (tcUnit != texcoordChannels.end()) { + int channel = (*tcUnit); + if (channel >= 2) { + channel = 0; + } + return channel; + } else { + return 0; + } + } +} + FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) { QHash meshes; QHash modelIDsToNames; @@ -1048,6 +1198,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) QHash animationCurves; QHash textureNames; QHash textureFilenames; + QHash textureParams; QHash textureContent; QHash materials; QHash typeFlags; @@ -1109,7 +1260,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } } QMultiHash blendshapeChannelIndices; - + int unknown = 0; FBXGeometry geometry; float unitScaleFactor = 1.0f; foreach (const FBXNode& child, node.children) { @@ -1312,7 +1463,10 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) models.insert(getID(object.properties), model); } else if (object.name == "Texture") { + TextureParam tex; + bool texparam = false; foreach (const FBXNode& subobject, object.children) { + std::string subname = subobject.name.data(); if (subobject.name == "RelativeFilename") { // trim off any path information QByteArray filename = subobject.properties.at(0).toByteArray(); @@ -1323,8 +1477,60 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) QString name = QString(subobject.properties.at(0).toByteArray()); name = name.left(name.indexOf('[')); textureNames.insert(getID(object.properties), name); + } else if (subobject.name == "Texture_Alpha_Source") { + tex.assign(tex.alphaSource, subobject.properties.at(0).value()); + } else if (subobject.name == "ModelUVTranslation") { + tex.assign(tex.UVTranslation, glm::vec2(subobject.properties.at(0).value(), + subobject.properties.at(1).value())); + } else if (subobject.name == "ModelUVScaling") { + tex.assign(tex.UVScaling, glm::vec2(subobject.properties.at(0).value(), + subobject.properties.at(1).value())); + } else if (subobject.name == "Cropping") { + tex.assign(tex.cropping, glm::vec4(subobject.properties.at(0).value(), + subobject.properties.at(1).value(), + subobject.properties.at(2).value(), + subobject.properties.at(3).value())); + } else if (subobject.name == "Properties70") { + + QByteArray propertyName; + int index; + propertyName = "P"; + index = 4; + foreach (const FBXNode& property, subobject.children) { + if (property.name == propertyName) { + QString v = property.properties.at(0).toString(); + std::string propName = v.toStdString(); + if (property.properties.at(0) == "UVSet") { + tex.assign(tex.UVSet, property.properties.at(index).toString().toStdString()); + } else if (property.properties.at(0) == "CurrentTextureBlendMode") { + tex.assign(tex.currentTextureBlendMode, property.properties.at(index).value()); + } else if (property.properties.at(0) == "UseMaterial") { + tex.assign(tex.useMaterial, property.properties.at(index).value()); + } else if (property.properties.at(0) == "Translation") { + tex.assign(tex.translation, getVec3(property.properties, index)); + } else if (property.properties.at(0) == "Rotation") { + tex.assign(tex.rotation, getVec3(property.properties, index)); + } else if (property.properties.at(0) == "Scaling") { + tex.assign(tex.scaling, getVec3(property.properties, index)); + } else { + unknown++; + } + } + } + } else { + if (subobject.name == "Type") { + } else if (subobject.name == "Version") { + } else if (subobject.name == "FileName") { + } else if (subobject.name == "Media") { + } else { + unknown++; + } } } + + if (!tex.isDefault) { + textureParams.insert(getID(object.properties), tex); + } } else if (object.name == "Video") { QByteArray filename; QByteArray content; @@ -1670,47 +1876,63 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) const QString& childID = children.at(i); if (materials.contains(childID)) { Material material = materials.value(childID); - + bool detectDifferentUVs = false; FBXTexture diffuseTexture; QString diffuseTextureID = diffuseTextures.value(childID); if (!diffuseTextureID.isNull()) { - diffuseTexture = getTexture(diffuseTextureID, textureNames, textureFilenames, textureContent); + diffuseTexture = getTexture(diffuseTextureID, textureNames, textureFilenames, textureContent, textureParams); // FBX files generated by 3DSMax have an intermediate texture parent, apparently foreach (const QString& childTextureID, childMap.values(diffuseTextureID)) { if (textureFilenames.contains(childTextureID)) { - diffuseTexture = getTexture(diffuseTextureID, textureNames, textureFilenames, textureContent); + diffuseTexture = getTexture(diffuseTextureID, textureNames, textureFilenames, textureContent, textureParams); } } + diffuseTexture.texcoordSet = matchTextureUVSetToAttributeChannel(diffuseTexture.texcoordSetName, extracted.texcoordSetMap); + + detectDifferentUVs = (diffuseTexture.texcoordSet != 0) || (!diffuseTexture.transform.isIdentity()); } FBXTexture normalTexture; QString bumpTextureID = bumpTextures.value(childID); if (!bumpTextureID.isNull()) { - normalTexture = getTexture(bumpTextureID, textureNames, textureFilenames, textureContent); + normalTexture = getTexture(bumpTextureID, textureNames, textureFilenames, textureContent, textureParams); generateTangents = true; + + normalTexture.texcoordSet = matchTextureUVSetToAttributeChannel(normalTexture.texcoordSetName, extracted.texcoordSetMap); + + detectDifferentUVs |= (normalTexture.texcoordSet != 0) || (!normalTexture.transform.isIdentity()); } FBXTexture specularTexture; QString specularTextureID = specularTextures.value(childID); if (!specularTextureID.isNull()) { - specularTexture = getTexture(specularTextureID, textureNames, textureFilenames, textureContent); + specularTexture = getTexture(specularTextureID, textureNames, textureFilenames, textureContent, textureParams); + specularTexture.texcoordSet = matchTextureUVSetToAttributeChannel(specularTexture.texcoordSetName, extracted.texcoordSetMap); + detectDifferentUVs |= (specularTexture.texcoordSet != 0) || (!specularTexture.transform.isIdentity()); } FBXTexture emissiveTexture; QString emissiveTextureID = emissiveTextures.value(childID); if (!emissiveTextureID.isNull()) { - emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent); + emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent, textureParams); // 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); + emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent, textureParams); } } + + emissiveTexture.texcoordSet = matchTextureUVSetToAttributeChannel(emissiveTexture.texcoordSetName, extracted.texcoordSetMap); + + detectDifferentUVs |= (emissiveTexture.texcoordSet != 0) || (!emissiveTexture.transform.isIdentity()); + } + + if (detectDifferentUVs) { + detectDifferentUVs = false; } - for (int j = 0; j < extracted.partMaterialTextures.size(); j++) { if (extracted.partMaterialTextures.at(j).first == materialIndex) { FBXMeshPart& part = extracted.mesh.parts[j]; @@ -1737,7 +1959,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) materialIndex++; } else if (textureFilenames.contains(childID)) { - FBXTexture texture = getTexture(childID, textureNames, textureFilenames, textureContent); + FBXTexture texture = getTexture(childID, textureNames, textureFilenames, textureContent, textureParams); for (int j = 0; j < extracted.partMaterialTextures.size(); j++) { int partTexture = extracted.partMaterialTextures.at(j).second; if (partTexture == textureIndex && !(partTexture == 0 && materialsHaveTextures)) { diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 892dd7a2fd..60e8ea2448 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -102,6 +103,10 @@ public: QString name; QByteArray filename; QByteArray content; + + Transform transform; + int texcoordSet; + std::string texcoordSetName; }; /// A single part of a mesh (with the same material). @@ -136,13 +141,14 @@ public: QVector tangents; QVector colors; QVector texCoords; + QVector texCoords1; QVector clusterIndices; QVector clusterWeights; QVector clusters; Extents meshExtents; - + bool isEye; QVector blendshapes; diff --git a/libraries/shared/src/Transform.h b/libraries/shared/src/Transform.h index 5ce5667a81..4adeccb46f 100644 --- a/libraries/shared/src/Transform.h +++ b/libraries/shared/src/Transform.h @@ -136,7 +136,10 @@ protected: void invalidCache() const { _flags.set(FLAG_CACHE_INVALID, true); } void flagTranslation() { _flags.set(FLAG_TRANSLATION, true); } + void unflagTranslation() { _flags.set(FLAG_TRANSLATION, false); } + void flagRotation() { _flags.set(FLAG_ROTATION, true); } + void unflagRotation() { _flags.set(FLAG_ROTATION, false); } void flagScaling() { _flags.set(FLAG_SCALING, true); } void unflagScaling() { _flags.set(FLAG_SCALING, false); } @@ -162,17 +165,23 @@ inline const Transform::Vec3& Transform::getTranslation() const { inline void Transform::setTranslation(const Vec3& translation) { invalidCache(); - flagTranslation(); + if (translation == Vec3()) { + unflagTranslation(); + } else { + flagTranslation(); + } _translation = translation; } inline void Transform::preTranslate(const Vec3& translation) { + if (translation == Vec3() ) return; invalidCache(); flagTranslation(); _translation += translation; } inline void Transform::postTranslate(const Vec3& translation) { + if (translation == Vec3() ) return; invalidCache(); flagTranslation(); @@ -192,11 +201,16 @@ inline const Transform::Quat& Transform::getRotation() const { inline void Transform::setRotation(const Quat& rotation) { invalidCache(); - flagRotation(); + if (rotation == Quat()) { + unflagRotation(); + } else { + flagRotation(); + } _rotation = rotation; } inline void Transform::preRotate(const Quat& rotation) { + if (rotation == Quat()) return; invalidCache(); if (isRotating()) { _rotation = rotation * _rotation; @@ -204,10 +218,12 @@ inline void Transform::preRotate(const Quat& rotation) { _rotation = rotation; } flagRotation(); + _translation = glm::rotate(rotation, _translation); } inline void Transform::postRotate(const Quat& rotation) { + if (rotation == Quat()) return; invalidCache(); if (isNonUniform()) { From 8b23a2cd1ee95f0b0648361350827a18cc8be060 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 24 Nov 2014 10:33:31 -0800 Subject: [PATCH 3/8] adding the shader files for the lightmap case --- .../resources/shaders/model_lightmap.frag | 36 +++++++++++++ .../resources/shaders/model_lightmap.vert | 40 ++++++++++++++ .../shaders/model_lightmap_normal_map.frag | 49 +++++++++++++++++ .../shaders/model_lightmap_normal_map.vert | 46 ++++++++++++++++ .../model_lightmap_normal_specular_map.frag | 53 +++++++++++++++++++ .../shaders/model_lightmap_specular_map.frag | 39 ++++++++++++++ 6 files changed, 263 insertions(+) create mode 100644 interface/resources/shaders/model_lightmap.frag create mode 100644 interface/resources/shaders/model_lightmap.vert create mode 100644 interface/resources/shaders/model_lightmap_normal_map.frag create mode 100644 interface/resources/shaders/model_lightmap_normal_map.vert create mode 100644 interface/resources/shaders/model_lightmap_normal_specular_map.frag create mode 100644 interface/resources/shaders/model_lightmap_specular_map.frag diff --git a/interface/resources/shaders/model_lightmap.frag b/interface/resources/shaders/model_lightmap.frag new file mode 100644 index 0000000000..0b7798f610 --- /dev/null +++ b/interface/resources/shaders/model_lightmap.frag @@ -0,0 +1,36 @@ +#version 120 + +// +// model_lightmap.frag +// fragment shader +// +// Created by Samuel Gateau on 11/19/14. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// the diffuse texture +uniform sampler2D diffuseMap; + +// the emissive map texture +uniform sampler2D emissiveMap; + +// the alpha threshold +uniform float alphaThreshold; + +// the interpolated normal +varying vec4 normal; + +// the interpolated texcoord1 +varying vec2 interpolatedTexcoord1; + +void main(void) { + // set the diffuse, normal, specular data + vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); + vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); + gl_FragData[0] = vec4(diffuse.rgb * (vec3(0.3) + emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); + gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); +} diff --git a/interface/resources/shaders/model_lightmap.vert b/interface/resources/shaders/model_lightmap.vert new file mode 100644 index 0000000000..021db11796 --- /dev/null +++ b/interface/resources/shaders/model_lightmap.vert @@ -0,0 +1,40 @@ +#version 120 + +// +// model_lightmap.vert +// vertex shader +// +// Created by Sam Gateau on 11/21/14. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +const int MAX_TEXCOORDS = 2; + +uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; + +attribute vec2 texcoord1; + +// the interpolated normal +varying vec4 normal; + +// the interpolated texcoord1 +varying vec2 interpolatedTexcoord1; + +void main(void) { + // transform and store the normal for interpolation + normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); + + // pass along the diffuse color + gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse; + + // and the texture coordinates + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); + interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(texcoord1.xy, 0.f, 1.f)).xy; + + // use standard pipeline transform + gl_Position = ftransform(); +} + diff --git a/interface/resources/shaders/model_lightmap_normal_map.frag b/interface/resources/shaders/model_lightmap_normal_map.frag new file mode 100644 index 0000000000..d63fd91fd0 --- /dev/null +++ b/interface/resources/shaders/model_lightmap_normal_map.frag @@ -0,0 +1,49 @@ +#version 120 + +// +// model_lightmap_normal_map.frag +// fragment shader +// +// Created by Samuel Gateau on 11/19/14. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// the diffuse texture +uniform sampler2D diffuseMap; + +// the normal map texture +uniform sampler2D normalMap; + +// the emissive map texture +uniform sampler2D emissiveMap; + +// the alpha threshold +uniform float alphaThreshold; + +// the interpolated normal +varying vec4 interpolatedNormal; + +// the interpolated tangent +varying vec4 interpolatedTangent; + +varying vec2 interpolatedTexcoord1; + +void main(void) { + // compute the view normal from the various bits + vec3 normalizedNormal = normalize(vec3(interpolatedNormal)); + vec3 normalizedTangent = normalize(vec3(interpolatedTangent)); + vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent)); + vec3 localNormal = vec3(texture2D(normalMap, gl_TexCoord[0].st)) - vec3(0.5, 0.5, 0.5); + vec4 viewNormal = vec4(normalizedTangent * localNormal.x + + normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0); + + // set the diffuse, normal, specular data + vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); + vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); + gl_FragData[0] = vec4(gl_Color.rgb * emissive.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[1] = viewNormal + vec4(0.5, 0.5, 0.5, 1.0); + gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); +} diff --git a/interface/resources/shaders/model_lightmap_normal_map.vert b/interface/resources/shaders/model_lightmap_normal_map.vert new file mode 100644 index 0000000000..08eca835c9 --- /dev/null +++ b/interface/resources/shaders/model_lightmap_normal_map.vert @@ -0,0 +1,46 @@ +#version 120 + +// +// model_lightmap_normal_map.vert +// vertex shader +// +// Created by Sam Gateau on 11/21/14. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +const int MAX_TEXCOORDS = 2; + +uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; + +// the tangent vector +attribute vec3 tangent; + +attribute vec2 texcoord1; + +// the interpolated normal +varying vec4 interpolatedNormal; + +// the interpolated tangent +varying vec4 interpolatedTangent; + +// the interpolated texcoord1 +varying vec2 interpolatedTexcoord1; + +void main(void) { + // transform and store the normal and tangent for interpolation + interpolatedNormal = gl_ModelViewMatrix * vec4(gl_Normal, 0.0); + interpolatedTangent = gl_ModelViewMatrix * vec4(tangent, 0.0); + + // pass along the diffuse color + gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse; + + // and the texture coordinates + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); + interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(texcoord1.xy, 0.f, 1.f)).xy; + + // use standard pipeline transform + gl_Position = ftransform(); +} diff --git a/interface/resources/shaders/model_lightmap_normal_specular_map.frag b/interface/resources/shaders/model_lightmap_normal_specular_map.frag new file mode 100644 index 0000000000..9b602c5a3b --- /dev/null +++ b/interface/resources/shaders/model_lightmap_normal_specular_map.frag @@ -0,0 +1,53 @@ +#version 120 + +// +// model_lightmap_normal_specular_map.frag +// fragment shader +// +// Created by Samuel Gateau on 11/19/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// the diffuse texture +uniform sampler2D diffuseMap; + +// the emissive map texture +uniform sampler2D emissiveMap; + +// the normal map texture +uniform sampler2D normalMap; + +// the specular map texture +uniform sampler2D specularMap; + +// the alpha threshold +uniform float alphaThreshold; + +// the interpolated normal +varying vec4 interpolatedNormal; + +// the interpolated tangent +varying vec4 interpolatedTangent; + +varying vec2 interpolatedTexcoord1; + +void main(void) { + // compute the view normal from the various bits + vec3 normalizedNormal = normalize(vec3(interpolatedNormal)); + vec3 normalizedTangent = normalize(vec3(interpolatedTangent)); + vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent)); + vec3 localNormal = vec3(texture2D(normalMap, gl_TexCoord[0].st)) - vec3(0.5, 0.5, 0.5); + vec4 viewNormal = vec4(normalizedTangent * localNormal.x + + normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0); + + // set the diffuse, normal, specular data + vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); + vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); + gl_FragData[0] = vec4(gl_Color.rgb * emissive.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[1] = viewNormal + vec4(0.5, 0.5, 0.5, 1.0); + gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, + gl_FrontMaterial.shininess / 128.0); +} diff --git a/interface/resources/shaders/model_lightmap_specular_map.frag b/interface/resources/shaders/model_lightmap_specular_map.frag new file mode 100644 index 0000000000..d60f21dffb --- /dev/null +++ b/interface/resources/shaders/model_lightmap_specular_map.frag @@ -0,0 +1,39 @@ +#version 120 + +// +// model_lightmap_specular_map.frag +// fragment shader +// +// Created by Samuel Gateau on 11/19/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// the diffuse texture +uniform sampler2D diffuseMap; + +// the emissive map texture +uniform sampler2D emissiveMap; + +// the specular texture +uniform sampler2D specularMap; + +// the alpha threshold +uniform float alphaThreshold; + +// the interpolated normal +varying vec4 normal; + +varying vec2 interpolatedTexcoord1; + +void main(void) { + // set the diffuse, normal, specular data + vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); + vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); + gl_FragData[0] = vec4(gl_Color.rgb * emissive.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); + gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, + gl_FrontMaterial.shininess / 128.0); +} From 6591f4dac296ce51dc23b307a766dbf9d061c3d3 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 24 Nov 2014 11:18:21 -0800 Subject: [PATCH 4/8] adjust lighmap shading equation --- interface/resources/shaders/model_lightmap.frag | 2 +- interface/resources/shaders/model_lightmap_normal_map.frag | 2 +- .../resources/shaders/model_lightmap_normal_specular_map.frag | 2 +- interface/resources/shaders/model_lightmap_specular_map.frag | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/resources/shaders/model_lightmap.frag b/interface/resources/shaders/model_lightmap.frag index 0b7798f610..67d9cd0218 100644 --- a/interface/resources/shaders/model_lightmap.frag +++ b/interface/resources/shaders/model_lightmap.frag @@ -30,7 +30,7 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(diffuse.rgb * (vec3(0.3) + emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(0.1) + 4 * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); } diff --git a/interface/resources/shaders/model_lightmap_normal_map.frag b/interface/resources/shaders/model_lightmap_normal_map.frag index d63fd91fd0..6d3e3aa861 100644 --- a/interface/resources/shaders/model_lightmap_normal_map.frag +++ b/interface/resources/shaders/model_lightmap_normal_map.frag @@ -43,7 +43,7 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(gl_Color.rgb * emissive.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(0.1) + 4 * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = viewNormal + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); } diff --git a/interface/resources/shaders/model_lightmap_normal_specular_map.frag b/interface/resources/shaders/model_lightmap_normal_specular_map.frag index 9b602c5a3b..89333bbcef 100644 --- a/interface/resources/shaders/model_lightmap_normal_specular_map.frag +++ b/interface/resources/shaders/model_lightmap_normal_specular_map.frag @@ -46,7 +46,7 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(gl_Color.rgb * emissive.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(0.1) + 4 * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = viewNormal + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, gl_FrontMaterial.shininess / 128.0); diff --git a/interface/resources/shaders/model_lightmap_specular_map.frag b/interface/resources/shaders/model_lightmap_specular_map.frag index d60f21dffb..3526ecdf9c 100644 --- a/interface/resources/shaders/model_lightmap_specular_map.frag +++ b/interface/resources/shaders/model_lightmap_specular_map.frag @@ -32,7 +32,7 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(gl_Color.rgb * emissive.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(0.1) + 4 * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, gl_FrontMaterial.shininess / 128.0); From f67b4b9ff4fa043e9805944110594c5d4346615a Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 24 Nov 2014 11:44:54 -0800 Subject: [PATCH 5/8] clean out comments so the 2 rendering modes for entities work, scene batch or per model batch --- interface/src/renderer/Model.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index d2a2378689..3f68201386 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1635,7 +1635,7 @@ 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, false, 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); @@ -1643,7 +1643,7 @@ void Model::endScene(RenderMode mode, RenderArgs* 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, true, false, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, false, args); @@ -1661,7 +1661,7 @@ 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, false, 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); @@ -1669,7 +1669,7 @@ void Model::endScene(RenderMode mode, RenderArgs* 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); @@ -1685,7 +1685,7 @@ 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, false, 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); @@ -1693,7 +1693,7 @@ void Model::endScene(RenderMode mode, RenderArgs* 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); From 68e2df8fc2e02dc0223ebe271ac90a48726936b9 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 24 Nov 2014 14:35:42 -0800 Subject: [PATCH 6/8] add a emissive parameter value to the lightmap shaders --- interface/resources/shaders/model.vert | 2 +- .../resources/shaders/model_lightmap.frag | 5 +++-- .../resources/shaders/model_lightmap.vert | 4 ++-- .../shaders/model_lightmap_normal_map.frag | 5 +++-- .../model_lightmap_normal_specular_map.frag | 5 +++-- .../shaders/model_lightmap_specular_map.frag | 5 +++-- .../resources/shaders/model_normal_map.vert | 2 +- interface/src/gpu/Batch.h | 2 ++ interface/src/gpu/GLBackend.cpp | 18 ++++++++++++++++++ interface/src/gpu/GLBackend.h | 1 + interface/src/renderer/GeometryCache.cpp | 2 ++ interface/src/renderer/Model.cpp | 5 +++++ interface/src/renderer/Model.h | 1 + 13 files changed, 45 insertions(+), 12 deletions(-) diff --git a/interface/resources/shaders/model.vert b/interface/resources/shaders/model.vert index 5ae6ea1cb6..bb0cb32d05 100644 --- a/interface/resources/shaders/model.vert +++ b/interface/resources/shaders/model.vert @@ -26,7 +26,7 @@ void main(void) { gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); // use standard pipeline transform gl_Position = ftransform(); diff --git a/interface/resources/shaders/model_lightmap.frag b/interface/resources/shaders/model_lightmap.frag index 67d9cd0218..b93f0abc6f 100644 --- a/interface/resources/shaders/model_lightmap.frag +++ b/interface/resources/shaders/model_lightmap.frag @@ -14,8 +14,9 @@ // the diffuse texture uniform sampler2D diffuseMap; -// the emissive map texture +// the emissive map texture and parameters uniform sampler2D emissiveMap; +uniform vec2 emissiveParams; // the alpha threshold uniform float alphaThreshold; @@ -30,7 +31,7 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(0.1) + 4 * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); } diff --git a/interface/resources/shaders/model_lightmap.vert b/interface/resources/shaders/model_lightmap.vert index 021db11796..ff1b07e503 100644 --- a/interface/resources/shaders/model_lightmap.vert +++ b/interface/resources/shaders/model_lightmap.vert @@ -31,8 +31,8 @@ void main(void) { gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); - interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(texcoord1.xy, 0.f, 1.f)).xy; + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); + interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(texcoord1.xy, 0.0, 1.0)).xy; // use standard pipeline transform gl_Position = ftransform(); diff --git a/interface/resources/shaders/model_lightmap_normal_map.frag b/interface/resources/shaders/model_lightmap_normal_map.frag index 6d3e3aa861..475126eb0c 100644 --- a/interface/resources/shaders/model_lightmap_normal_map.frag +++ b/interface/resources/shaders/model_lightmap_normal_map.frag @@ -17,8 +17,9 @@ uniform sampler2D diffuseMap; // the normal map texture uniform sampler2D normalMap; -// the emissive map texture +// the emissive map texture and parameters uniform sampler2D emissiveMap; +uniform vec2 emissiveParams; // the alpha threshold uniform float alphaThreshold; @@ -43,7 +44,7 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(0.1) + 4 * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = viewNormal + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); } diff --git a/interface/resources/shaders/model_lightmap_normal_specular_map.frag b/interface/resources/shaders/model_lightmap_normal_specular_map.frag index 89333bbcef..4d0d29ed71 100644 --- a/interface/resources/shaders/model_lightmap_normal_specular_map.frag +++ b/interface/resources/shaders/model_lightmap_normal_specular_map.frag @@ -14,8 +14,9 @@ // the diffuse texture uniform sampler2D diffuseMap; -// the emissive map texture +// the emissive map texture and parameters uniform sampler2D emissiveMap; +uniform vec2 emissiveParams; // the normal map texture uniform sampler2D normalMap; @@ -46,7 +47,7 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(0.1) + 4 * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = viewNormal + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, gl_FrontMaterial.shininess / 128.0); diff --git a/interface/resources/shaders/model_lightmap_specular_map.frag b/interface/resources/shaders/model_lightmap_specular_map.frag index 3526ecdf9c..c616764cae 100644 --- a/interface/resources/shaders/model_lightmap_specular_map.frag +++ b/interface/resources/shaders/model_lightmap_specular_map.frag @@ -14,8 +14,9 @@ // the diffuse texture uniform sampler2D diffuseMap; -// the emissive map texture +// the emissive map texture and parameters uniform sampler2D emissiveMap; +uniform vec2 emissiveParams; // the specular texture uniform sampler2D specularMap; @@ -32,7 +33,7 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(0.1) + 4 * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, gl_FrontMaterial.shininess / 128.0); diff --git a/interface/resources/shaders/model_normal_map.vert b/interface/resources/shaders/model_normal_map.vert index 2e98b8c4fc..3d91a75c63 100644 --- a/interface/resources/shaders/model_normal_map.vert +++ b/interface/resources/shaders/model_normal_map.vert @@ -33,7 +33,7 @@ void main(void) { gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); // use standard pipeline transform gl_Position = ftransform(); diff --git a/interface/src/gpu/Batch.h b/interface/src/gpu/Batch.h index d006473b50..5304740dd3 100644 --- a/interface/src/gpu/Batch.h +++ b/interface/src/gpu/Batch.h @@ -116,6 +116,7 @@ public: void _glUseProgram(GLuint program); void _glUniform1f(GLint location, GLfloat v0); + void _glUniform2f(GLint location, GLfloat v0, GLfloat v1); void _glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); void _glMatrixMode(GLenum mode); @@ -185,6 +186,7 @@ public: COMMAND_glUseProgram, COMMAND_glUniform1f, + COMMAND_glUniform2f, COMMAND_glUniformMatrix4fv, COMMAND_glMatrixMode, diff --git a/interface/src/gpu/GLBackend.cpp b/interface/src/gpu/GLBackend.cpp index d6e1a011a3..1f8e7bf99f 100644 --- a/interface/src/gpu/GLBackend.cpp +++ b/interface/src/gpu/GLBackend.cpp @@ -53,6 +53,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_glUseProgram), (&::gpu::GLBackend::do_glUniform1f), + (&::gpu::GLBackend::do_glUniform2f), (&::gpu::GLBackend::do_glUniformMatrix4fv), (&::gpu::GLBackend::do_glMatrixMode), @@ -691,6 +692,23 @@ void GLBackend::do_glUniform1f(Batch& batch, uint32 paramOffset) { CHECK_GL_ERROR(); } +void Batch::_glUniform2f(GLint location, GLfloat v0, GLfloat v1) { + ADD_COMMAND_GL(glUniform2f); + + _params.push_back(v1); + _params.push_back(v0); + _params.push_back(location); + + DO_IT_NOW(_glUniform2f, 1); +} +void GLBackend::do_glUniform2f(Batch& batch, uint32 paramOffset) { + glUniform2f( + batch._params[paramOffset + 2]._int, + batch._params[paramOffset + 1]._float, + batch._params[paramOffset + 0]._float); + CHECK_GL_ERROR(); +} + void Batch::_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { ADD_COMMAND_GL(glUniformMatrix4fv); diff --git a/interface/src/gpu/GLBackend.h b/interface/src/gpu/GLBackend.h index 71869229fd..0e4b38d89e 100644 --- a/interface/src/gpu/GLBackend.h +++ b/interface/src/gpu/GLBackend.h @@ -147,6 +147,7 @@ protected: void do_glUseProgram(Batch& batch, uint32 paramOffset); void do_glUniform1f(Batch& batch, uint32 paramOffset); + void do_glUniform2f(Batch& batch, uint32 paramOffset); void do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset); void do_glMatrixMode(Batch& batch, uint32 paramOffset); diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index 04ff7bdecd..ab27678546 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -830,6 +830,8 @@ void GeometryReader::run() { } try { QMetaObject::invokeMethod(geometry.data(), "setGeometry", Q_ARG(const FBXGeometry&, + + _url.path().toLower().endsWith(".svo") ? readSVO(_reply->readAll()) : readFBX(_reply->readAll(), _mapping))); } catch (const QString& error) { diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 3f68201386..2c43113b62 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -160,6 +160,8 @@ void Model::initProgram(ProgramObject& program, Model::Locations& locations, int locations.texcoordMatrices = program.uniformLocation("texcoordMatrices"); + locations.emissiveParams = program.uniformLocation("emissiveParams"); + program.setUniformValue("diffuseMap", 0); @@ -2378,6 +2380,9 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod } if (locations->emissiveTextureUnit >= 0) { + assert(locations->emissiveParams >= 0); // we should have the emissiveParams defined in the shader + GLBATCH(glUniform2f)(locations->emissiveParams, 0.1f, 4.0f); + GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->emissiveTextureUnit); Texture* emissiveMap = networkPart.emissiveTexture.data(); GLBATCH(glBindTexture)(GL_TEXTURE_2D, !emissiveMap ? diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 7a3457423e..d24e4d9f2e 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -329,6 +329,7 @@ private: int texcoordMatrices; int specularTextureUnit; int emissiveTextureUnit; + int emissiveParams; }; static Locations _locations; From 6a63099a0f339b4aae9d792b804209cec8bfeed0 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 24 Nov 2014 15:24:20 -0800 Subject: [PATCH 7/8] Fixed syntax issues and review critics, put all the debugging code in a #define block --- interface/src/renderer/GeometryCache.cpp | 1 - interface/src/renderer/Model.cpp | 7 +-- libraries/fbx/src/FBXReader.cpp | 57 +++++++++++++++--------- 3 files changed, 39 insertions(+), 26 deletions(-) diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index ab27678546..c7d8b7fc8a 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -971,7 +971,6 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { int clusterWeightsOffset = clusterIndicesOffset + mesh.clusterIndices.size() * sizeof(glm::vec4); networkMesh._vertexBuffer->resize(clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4)); - //networkMesh.vertexBuffer.allocate(clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4)); networkMesh._vertexBuffer->setSubData(0, mesh.vertices.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.vertices.constData()); networkMesh._vertexBuffer->setSubData(normalsOffset, mesh.normals.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.normals.constData()); diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 2c43113b62..ddcdfe3a84 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -387,8 +387,6 @@ void Model::init() { _skinTranslucentProgram.link(); initSkinProgram(_skinTranslucentProgram, _skinTranslucentLocations); - - } } @@ -1813,7 +1811,7 @@ void Model::segregateMeshGroups() { bool translucentMesh = networkMesh.getTranslucentPartCount(mesh) == networkMesh.parts.size(); bool hasTangents = !mesh.tangents.isEmpty(); bool hasSpecular = mesh.hasSpecularTexture(); - bool haslightmap = mesh.hasEmissiveTexture(); + bool hasLightmap = mesh.hasEmissiveTexture(); bool isSkinned = state.clusterMatrices.size() > 1; QString materialID; @@ -1832,7 +1830,7 @@ void Model::segregateMeshGroups() { qDebug() << "materialID:" << materialID << "parts:" << mesh.parts.size(); } - if ( !haslightmap) { + if (!hasLightmap) { if (translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { _unsortedMeshesTranslucent.insertMulti(materialID, i); @@ -2387,7 +2385,6 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod Texture* emissiveMap = networkPart.emissiveTexture.data(); GLBATCH(glBindTexture)(GL_TEXTURE_2D, !emissiveMap ? Application::getInstance()->getTextureCache()->getWhiteTextureID() : emissiveMap->getID()); - // GLBATCH(glBindTexture)(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getWhiteTextureID()); GLBATCH(glActiveTexture)(GL_TEXTURE0); } diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 130f1db550..0cebacf51a 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -30,6 +30,10 @@ #include "FBXReader.h" + +// TOOL: Uncomment the following line to enable the filtering of all the unkwnon fields of a node so we can break point easily while loading a model with problems... +//#define DEBUG_FBXREADER + using namespace std; struct TextureParam { @@ -868,7 +872,9 @@ void appendIndex(MeshData& data, QVector& indices, int index) { data.extracted.mesh.vertices.append(position); data.extracted.mesh.normals.append(normal); data.extracted.mesh.texCoords.append(vertex.texCoord); - if (hasMoreTexcoords) { data.extracted.mesh.texCoords1.append(vertex.texCoord1); } + if (hasMoreTexcoords) { + data.extracted.mesh.texCoords1.append(vertex.texCoord1); + } } else { indices.append(*it); data.extracted.mesh.normals[*it] += normal; @@ -911,7 +917,6 @@ ExtractedMesh extractMesh(const FBXNode& object) { if (child.properties.at(0).toInt() == 0) { AttributeData attrib; attrib.index = child.properties.at(0).toInt(); - int unknown = 0; foreach (const FBXNode& subdata, child.children) { if (subdata.name == "UV") { data.texCoords = createVec2Vector(getDoubleVector(subdata)); @@ -921,22 +926,25 @@ ExtractedMesh extractMesh(const FBXNode& object) { attrib.texCoordIndices = getIntVector(subdata); } else if (subdata.name == "Name") { attrib.name = subdata.properties.at(0).toString().toStdString(); - } else { + } +#if defined(DEBUG_FBXREADER) + else { + int unknown = 0; std::string subname = subdata.name.data(); - if (subdata.name == "Version") { - } else if (subdata.name == "MappingInformationType") { - } else if (subdata.name == "ReferenceInformationType") { + if ( (subdata.name == "Version") + || (subdata.name == "MappingInformationType") + || (subdata.name == "ReferenceInformationType") ) { } else { unknown++; } } +#endif } data.extracted.texcoordSetMap.insert(QString(attrib.name.c_str()), data.attributes.size()); data.attributes.push_back(attrib); } else { AttributeData attrib; attrib.index = child.properties.at(0).toInt(); - int unknown = 0; foreach (const FBXNode& subdata, child.children) { if (subdata.name == "UV") { attrib.texCoords = createVec2Vector(getDoubleVector(subdata)); @@ -944,15 +952,19 @@ ExtractedMesh extractMesh(const FBXNode& object) { attrib.texCoordIndices = getIntVector(subdata); } else if (subdata.name == "Name") { attrib.name = subdata.properties.at(0).toString().toStdString(); - } else { + } +#if defined(DEBUG_FBXREADER) + else { + int unknown = 0; std::string subname = subdata.name.data(); - if (subdata.name == "Version") { - } else if (subdata.name == "MappingInformationType") { - } else if (subdata.name == "ReferenceInformationType") { + if ( (subdata.name == "Version") + || (subdata.name == "MappingInformationType") + || (subdata.name == "ReferenceInformationType") ) { } else { unknown++; } } +#endif } QHash::iterator it = data.extracted.texcoordSetMap.find(QString(attrib.name.c_str())); @@ -961,7 +973,7 @@ ExtractedMesh extractMesh(const FBXNode& object) { data.attributes.push_back(attrib); } else { // WTF same names for different UVs? - unknown = data.attributes.size(); + qDebug() << "LayerElementUV #" << attrib.index << " is reusing the same name as #" << (*it) << ". Skip this texcoord attribute."; } } } else if (child.name == "LayerElementMaterial") { @@ -1145,12 +1157,10 @@ FBXTexture getTexture(const QString& textureID, texture.transform.setTranslation(p.translation); texture.transform.setRotation(glm::quat(glm::radians(p.rotation))); texture.transform.setScale(p.scaling); - if (p.UVSet != "map1" || (p.UVSet != "UVSet0")) { + if ((p.UVSet != "map1") || (p.UVSet != "UVSet0")) { texture.texcoordSet = 1; } - texture.texcoordSetName = p.UVSet; - } return texture; } @@ -1260,7 +1270,9 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } } QMultiHash blendshapeChannelIndices; +#if defined(DEBUG_FBXREADER) int unknown = 0; +#endif FBXGeometry geometry; float unitScaleFactor = 1.0f; foreach (const FBXNode& child, node.children) { @@ -1466,7 +1478,6 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) TextureParam tex; bool texparam = false; foreach (const FBXNode& subobject, object.children) { - std::string subname = subobject.name.data(); if (subobject.name == "RelativeFilename") { // trim off any path information QByteArray filename = subobject.properties.at(0).toByteArray(); @@ -1491,7 +1502,6 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) subobject.properties.at(2).value(), subobject.properties.at(3).value())); } else if (subobject.name == "Properties70") { - QByteArray propertyName; int index; propertyName = "P"; @@ -1499,7 +1509,6 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) foreach (const FBXNode& property, subobject.children) { if (property.name == propertyName) { QString v = property.properties.at(0).toString(); - std::string propName = v.toStdString(); if (property.properties.at(0) == "UVSet") { tex.assign(tex.UVSet, property.properties.at(index).toString().toStdString()); } else if (property.properties.at(0) == "CurrentTextureBlendMode") { @@ -1512,20 +1521,28 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) tex.assign(tex.rotation, getVec3(property.properties, index)); } else if (property.properties.at(0) == "Scaling") { tex.assign(tex.scaling, getVec3(property.properties, index)); - } else { + } +#if defined(DEBUG_FBXREADER) + else { + std::string propName = v.toStdString(); unknown++; } +#endif } } - } else { + } +#if defined(DEBUG_FBXREADER) + else { if (subobject.name == "Type") { } else if (subobject.name == "Version") { } else if (subobject.name == "FileName") { } else if (subobject.name == "Media") { } else { + std::string subname = subobject.name.data(); unknown++; } } +#endif } if (!tex.isDefault) { From 1f10a44ae496d7017450e145c916e86891377a54 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 24 Nov 2014 15:38:12 -0800 Subject: [PATCH 8/8] More typos in glsl --- interface/resources/shaders/model_lightmap_normal_map.vert | 4 ++-- interface/resources/shaders/skin_model.vert | 2 +- interface/resources/shaders/skin_model_normal_map.vert | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/resources/shaders/model_lightmap_normal_map.vert b/interface/resources/shaders/model_lightmap_normal_map.vert index 08eca835c9..4faf5688cf 100644 --- a/interface/resources/shaders/model_lightmap_normal_map.vert +++ b/interface/resources/shaders/model_lightmap_normal_map.vert @@ -38,8 +38,8 @@ void main(void) { gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); - interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(texcoord1.xy, 0.f, 1.f)).xy; + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); + interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(texcoord1.xy, 0.0, 1.0)).xy; // use standard pipeline transform gl_Position = ftransform(); diff --git a/interface/resources/shaders/skin_model.vert b/interface/resources/shaders/skin_model.vert index a8c25e885b..fd4dea51bb 100644 --- a/interface/resources/shaders/skin_model.vert +++ b/interface/resources/shaders/skin_model.vert @@ -40,7 +40,7 @@ void main(void) { gl_FrontColor = gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); gl_Position = gl_ModelViewProjectionMatrix * position; } diff --git a/interface/resources/shaders/skin_model_normal_map.vert b/interface/resources/shaders/skin_model_normal_map.vert index bbe5da35af..5814dfc584 100644 --- a/interface/resources/shaders/skin_model_normal_map.vert +++ b/interface/resources/shaders/skin_model_normal_map.vert @@ -48,7 +48,7 @@ void main(void) { gl_FrontColor = gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); gl_Position = gl_ModelViewProjectionMatrix * interpolatedPosition; }