adding the light map support from FBX

This commit is contained in:
Sam Gateau 2014-11-20 09:54:41 -08:00
parent c2adc6256e
commit 764ad72471
9 changed files with 525 additions and 138 deletions

View file

@ -4,7 +4,7 @@
// model_normal_map.frag // model_normal_map.frag
// fragment shader // fragment shader
// //
// Created by Andrzej Kapolka on 10/29/13. // Created by Andrzej Kapolka on 10/14/13.
// Copyright 2013 High Fidelity, Inc. // Copyright 2013 High Fidelity, Inc.
// //
// Distributed under the Apache License, Version 2.0. // Distributed under the Apache License, Version 2.0.

View file

@ -522,6 +522,14 @@ bool ModelUploader::addTextures(const QString& texdir, const FBXGeometry& geomet
} }
_textureFilenames.insert(part.specularTexture.filename); _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);
}
} }
} }

View file

@ -575,7 +575,8 @@ bool NetworkGeometry::isLoadedWithTextures() const {
foreach (const NetworkMeshPart& part, mesh.parts) { foreach (const NetworkMeshPart& part, mesh.parts) {
if ((part.diffuseTexture && !part.diffuseTexture->isLoaded()) || if ((part.diffuseTexture && !part.diffuseTexture->isLoaded()) ||
(part.normalTexture && !part.normalTexture->isLoaded()) || (part.normalTexture && !part.normalTexture->isLoaded()) ||
(part.specularTexture && !part.specularTexture->isLoaded())) { (part.specularTexture && !part.specularTexture->isLoaded()) ||
(part.emissiveTexture && !part.emissiveTexture->isLoaded())) {
return false; return false;
} }
} }
@ -668,6 +669,9 @@ void NetworkGeometry::setLoadPriority(const QPointer<QObject>& owner, float prio
if (part.specularTexture) { if (part.specularTexture) {
part.specularTexture->setLoadPriority(owner, priority); part.specularTexture->setLoadPriority(owner, priority);
} }
if (part.emissiveTexture) {
part.emissiveTexture->setLoadPriority(owner, priority);
}
} }
} }
} }
@ -688,6 +692,9 @@ void NetworkGeometry::setLoadPriorities(const QHash<QPointer<QObject>, float>& p
if (part.specularTexture) { if (part.specularTexture) {
part.specularTexture->setLoadPriorities(priorities); part.specularTexture->setLoadPriorities(priorities);
} }
if (part.emissiveTexture) {
part.emissiveTexture->setLoadPriorities(priorities);
}
} }
} }
} }
@ -708,6 +715,9 @@ void NetworkGeometry::clearLoadPriority(const QPointer<QObject>& owner) {
if (part.specularTexture) { if (part.specularTexture) {
part.specularTexture->clearLoadPriority(owner); 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, part.specularTexture = Application::getInstance()->getTextureCache()->getTexture(url, DEFAULT_TEXTURE,
false, QByteArray()); false, QByteArray());
part.specularTexture->setLoadPriorities(_loadPriorities); 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(); QString textureURL = part.specularTexture->getURL().toString();
result << part.specularTextureName + ":" + textureURL; result << part.specularTextureName + ":" + textureURL;
} }
if (!part.emissiveTextureName.isEmpty()) {
QString textureURL = part.emissiveTexture->getURL().toString();
result << part.emissiveTextureName + ":" + textureURL;
}
} }
} }
return result; return result;
@ -911,6 +930,13 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) {
networkPart.specularTextureName = part.specularTexture.name; networkPart.specularTextureName = part.specularTexture.name;
networkPart.specularTexture->setLoadPriorities(_loadPriorities); 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); networkMesh.parts.append(networkPart);
totalIndices += (part.quadIndices.size() + part.triangleIndices.size()); totalIndices += (part.quadIndices.size() + part.triangleIndices.size());

View file

@ -155,7 +155,9 @@ public:
QSharedPointer<NetworkTexture> normalTexture; QSharedPointer<NetworkTexture> normalTexture;
QString specularTextureName; QString specularTextureName;
QSharedPointer<NetworkTexture> specularTexture; QSharedPointer<NetworkTexture> specularTexture;
QString emissiveTextureName;
QSharedPointer<NetworkTexture> emissiveTexture;
bool isTranslucent() const; bool isTranslucent() const;
}; };

View file

@ -70,6 +70,11 @@ ProgramObject Model::_specularMapProgram;
ProgramObject Model::_normalSpecularMapProgram; ProgramObject Model::_normalSpecularMapProgram;
ProgramObject Model::_translucentProgram; ProgramObject Model::_translucentProgram;
ProgramObject Model::_emissiveProgram;
ProgramObject Model::_emissiveNormalMapProgram;
ProgramObject Model::_emissiveSpecularMapProgram;
ProgramObject Model::_emissiveNormalSpecularMapProgram;
ProgramObject Model::_shadowProgram; ProgramObject Model::_shadowProgram;
ProgramObject Model::_skinProgram; ProgramObject Model::_skinProgram;
@ -78,6 +83,11 @@ ProgramObject Model::_skinSpecularMapProgram;
ProgramObject Model::_skinNormalSpecularMapProgram; ProgramObject Model::_skinNormalSpecularMapProgram;
ProgramObject Model::_skinTranslucentProgram; ProgramObject Model::_skinTranslucentProgram;
ProgramObject Model::_skinEmissiveProgram;
ProgramObject Model::_skinEmissiveNormalMapProgram;
ProgramObject Model::_skinEmissiveSpecularMapProgram;
ProgramObject Model::_skinEmissiveNormalSpecularMapProgram;
ProgramObject Model::_skinShadowProgram; ProgramObject Model::_skinShadowProgram;
Model::Locations Model::_locations; Model::Locations Model::_locations;
@ -86,6 +96,11 @@ Model::Locations Model::_specularMapLocations;
Model::Locations Model::_normalSpecularMapLocations; Model::Locations Model::_normalSpecularMapLocations;
Model::Locations Model::_translucentLocations; 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::_skinLocations;
Model::SkinLocations Model::_skinNormalMapLocations; Model::SkinLocations Model::_skinNormalMapLocations;
Model::SkinLocations Model::_skinSpecularMapLocations; Model::SkinLocations Model::_skinSpecularMapLocations;
@ -93,6 +108,11 @@ Model::SkinLocations Model::_skinNormalSpecularMapLocations;
Model::SkinLocations Model::_skinShadowLocations; Model::SkinLocations Model::_skinShadowLocations;
Model::SkinLocations Model::_skinTranslucentLocations; 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) { void Model::setScale(const glm::vec3& scale) {
setScaleInternal(scale); setScaleInternal(scale);
// if anyone sets scale manually, then we are no longer scaled to fit // if anyone sets scale manually, then we are no longer scaled to fit
@ -268,6 +288,39 @@ void Model::init() {
_translucentProgram.link(); _translucentProgram.link();
initProgram(_translucentProgram, _translucentLocations); 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::Vertex, Application::resourcesPath() + "shaders/model_shadow.vert");
_shadowProgram.addShaderFromSourceFile(QGLShader::Fragment, _shadowProgram.addShaderFromSourceFile(QGLShader::Fragment,
@ -319,6 +372,38 @@ void Model::init() {
_skinTranslucentProgram.link(); _skinTranslucentProgram.link();
initSkinProgram(_skinTranslucentProgram, _skinTranslucentLocations); 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); //renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, book isSkinned, args);
int opaqueMeshPartsRendered = 0; 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, false, false, args);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args); opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, 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, false, true, false, args);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, args); opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, true, args);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args); opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, false, args);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, true, args);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args); opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, 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, 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 // render translucent meshes afterwards
//Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true); //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true);
@ -642,14 +736,14 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
int translucentMeshPartsRendered = 0; int translucentMeshPartsRendered = 0;
const float MOSTLY_OPAQUE_THRESHOLD = 0.75f; 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, false, false, args);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, 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, false, true, false, args);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, true, args);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, false, args);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, true, args);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, 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, true, true, true, args);
GLBATCH(glDisable)(GL_ALPHA_TEST); GLBATCH(glDisable)(GL_ALPHA_TEST);
GLBATCH(glEnable)(GL_BLEND); 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) { if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) {
const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f; 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, false, false, args);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, 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, false, true, false, args);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, true, args);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, false, args);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, true, args);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, 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, true, true, true, args);
} }
GLBATCH(glDepthMask)(true); GLBATCH(glDepthMask)(true);
@ -1562,15 +1656,24 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
int opaqueMeshPartsRendered = 0; int opaqueMeshPartsRendered = 0;
// now, for each model in the scene, render the mesh portions // 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, false, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, 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, false, true, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, true, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, true, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, 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, 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 // render translucent meshes afterwards
//Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true); //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true);
{ {
@ -1583,15 +1686,15 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
int translucentParts = 0; int translucentParts = 0;
const float MOSTLY_OPAQUE_THRESHOLD = 0.75f; 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, false, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, 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, false, true, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, true, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, true, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, 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, true, true, true, args);
*/
GLBATCH(glDisable)(GL_ALPHA_TEST); GLBATCH(glDisable)(GL_ALPHA_TEST);
GLBATCH(glEnable)(GL_BLEND); GLBATCH(glEnable)(GL_BLEND);
GLBATCH(glDepthMask)(false); GLBATCH(glDepthMask)(false);
@ -1607,15 +1710,15 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) {
const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f; 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, false, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, 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, false, true, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, true, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, true, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, 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, true, true, true, args);
} */ }
GLBATCH(glDepthMask)(true); GLBATCH(glDepthMask)(true);
GLBATCH(glDepthFunc)(GL_LESS); GLBATCH(glDepthFunc)(GL_LESS);
@ -1689,7 +1792,17 @@ void Model::segregateMeshGroups() {
_meshesOpaqueSkinned.clear(); _meshesOpaqueSkinned.clear();
_meshesOpaqueTangentsSpecularSkinned.clear(); _meshesOpaqueTangentsSpecularSkinned.clear();
_meshesOpaqueSpecularSkinned.clear(); _meshesOpaqueSpecularSkinned.clear();
_meshesOpaqueEmissiveTangents.clear();
_meshesOpaqueEmissive.clear();
_meshesOpaqueEmissiveTangentsSpecular.clear();
_meshesOpaqueEmissiveSpecular.clear();
_meshesOpaqueEmissiveTangentsSkinned.clear();
_meshesOpaqueEmissiveSkinned.clear();
_meshesOpaqueEmissiveTangentsSpecularSkinned.clear();
_meshesOpaqueEmissiveSpecularSkinned.clear();
_unsortedMeshesTranslucentTangents.clear(); _unsortedMeshesTranslucentTangents.clear();
_unsortedMeshesTranslucent.clear(); _unsortedMeshesTranslucent.clear();
_unsortedMeshesTranslucentTangentsSpecular.clear(); _unsortedMeshesTranslucentTangentsSpecular.clear();
@ -1710,6 +1823,16 @@ void Model::segregateMeshGroups() {
_unsortedMeshesOpaqueTangentsSpecularSkinned.clear(); _unsortedMeshesOpaqueTangentsSpecularSkinned.clear();
_unsortedMeshesOpaqueSpecularSkinned.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 FBXGeometry& geometry = _geometry->getFBXGeometry();
const QVector<NetworkMesh>& networkMeshes = _geometry->getMeshes(); const QVector<NetworkMesh>& networkMeshes = _geometry->getMeshes();
@ -1723,6 +1846,7 @@ void Model::segregateMeshGroups() {
bool translucentMesh = networkMesh.getTranslucentPartCount(mesh) == networkMesh.parts.size(); bool translucentMesh = networkMesh.getTranslucentPartCount(mesh) == networkMesh.parts.size();
bool hasTangents = !mesh.tangents.isEmpty(); bool hasTangents = !mesh.tangents.isEmpty();
bool hasSpecular = mesh.hasSpecularTexture(); bool hasSpecular = mesh.hasSpecularTexture();
bool hasEmissive = mesh.hasEmissiveTexture();
bool isSkinned = state.clusterMatrices.size() > 1; bool isSkinned = state.clusterMatrices.size() > 1;
QString materialID; QString materialID;
@ -1741,71 +1865,108 @@ void Model::segregateMeshGroups() {
qDebug() << "materialID:" << materialID << "parts:" << mesh.parts.size(); 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 { } 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); _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(); _unsortedMeshesTranslucentTangents.clear();
_unsortedMeshesTranslucent.clear(); _unsortedMeshesTranslucent.clear();
_unsortedMeshesTranslucentTangentsSpecular.clear(); _unsortedMeshesTranslucentTangentsSpecular.clear();
@ -1893,10 +2086,20 @@ void Model::segregateMeshGroups() {
_unsortedMeshesOpaqueTangentsSpecularSkinned.clear(); _unsortedMeshesOpaqueTangentsSpecularSkinned.clear();
_unsortedMeshesOpaqueSpecularSkinned.clear(); _unsortedMeshesOpaqueSpecularSkinned.clear();
_unsortedMeshesOpaqueEmissiveTangents.clear();
_unsortedMeshesOpaqueEmissive.clear();
_unsortedMeshesOpaqueEmissiveTangentsSpecular.clear();
_unsortedMeshesOpaqueEmissiveSpecular.clear();
_unsortedMeshesOpaqueEmissiveTangentsSkinned.clear();
_unsortedMeshesOpaqueEmissiveSkinned.clear();
_unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned.clear();
_unsortedMeshesOpaqueEmissiveSpecularSkinned.clear();
_meshGroupsKnown = true; _meshGroupsKnown = true;
} }
QVector<int>* Model::pickMeshList(bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, bool isSkinned) { QVector<int>* Model::pickMeshList(bool translucent, float alphaThreshold, bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned) {
PROFILE_RANGE(__FUNCTION__); PROFILE_RANGE(__FUNCTION__);
// depending on which parameters we were called with, pick the correct mesh group to render // depending on which parameters we were called with, pick the correct mesh group to render
@ -1917,22 +2120,41 @@ QVector<int>* Model::pickMeshList(bool translucent, float alphaThreshold, bool h
whichList = &_meshesTranslucentTangentsSpecularSkinned; whichList = &_meshesTranslucentTangentsSpecularSkinned;
} else if (translucent && !hasTangents && hasSpecular && isSkinned) { } else if (translucent && !hasTangents && hasSpecular && isSkinned) {
whichList = &_meshesTranslucentSpecularSkinned; whichList = &_meshesTranslucentSpecularSkinned;
} else if (!translucent && !hasTangents && !hasSpecular && !isSkinned) {
} else if (!translucent && !hasEmissive && !hasTangents && !hasSpecular && !isSkinned) {
whichList = &_meshesOpaque; whichList = &_meshesOpaque;
} else if (!translucent && hasTangents && !hasSpecular && !isSkinned) { } else if (!translucent && !hasEmissive && hasTangents && !hasSpecular && !isSkinned) {
whichList = &_meshesOpaqueTangents; whichList = &_meshesOpaqueTangents;
} else if (!translucent && hasTangents && hasSpecular && !isSkinned) { } else if (!translucent && !hasEmissive && hasTangents && hasSpecular && !isSkinned) {
whichList = &_meshesOpaqueTangentsSpecular; whichList = &_meshesOpaqueTangentsSpecular;
} else if (!translucent && !hasTangents && hasSpecular && !isSkinned) { } else if (!translucent && !hasEmissive && !hasTangents && hasSpecular && !isSkinned) {
whichList = &_meshesOpaqueSpecular; whichList = &_meshesOpaqueSpecular;
} else if (!translucent && hasTangents && !hasSpecular && isSkinned) { } else if (!translucent && !hasEmissive && hasTangents && !hasSpecular && isSkinned) {
whichList = &_meshesOpaqueTangentsSkinned; whichList = &_meshesOpaqueTangentsSkinned;
} else if (!translucent && !hasTangents && !hasSpecular && isSkinned) { } else if (!translucent && !hasEmissive && !hasTangents && !hasSpecular && isSkinned) {
whichList = &_meshesOpaqueSkinned; whichList = &_meshesOpaqueSkinned;
} else if (!translucent && hasTangents && hasSpecular && isSkinned) { } else if (!translucent && !hasEmissive && hasTangents && hasSpecular && isSkinned) {
whichList = &_meshesOpaqueTangentsSpecularSkinned; whichList = &_meshesOpaqueTangentsSpecularSkinned;
} else if (!translucent && !hasTangents && hasSpecular && isSkinned) { } else if (!translucent && !hasEmissive && !hasTangents && hasSpecular && isSkinned) {
whichList = &_meshesOpaqueSpecularSkinned; 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 { } else {
qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???"; qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???";
} }
@ -1940,14 +2162,15 @@ QVector<int>* Model::pickMeshList(bool translucent, float alphaThreshold, bool h
} }
void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, void Model::pickPrograms(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,
SkinLocations*& skinLocations, GLenum& specularTextureUnit) { SkinLocations*& skinLocations, GLenum& specularTextureUnit, GLenum& emissiveTextureUnit) {
ProgramObject* program = &_program; ProgramObject* program = &_program;
Locations* locations = &_locations; Locations* locations = &_locations;
ProgramObject* skinProgram = &_skinProgram; ProgramObject* skinProgram = &_skinProgram;
skinLocations = &_skinLocations; skinLocations = &_skinLocations;
specularTextureUnit = 0; specularTextureUnit = 0;
emissiveTextureUnit = 0;
if (mode == SHADOW_RENDER_MODE) { if (mode == SHADOW_RENDER_MODE) {
program = &_shadowProgram; program = &_shadowProgram;
skinProgram = &_skinShadowProgram; skinProgram = &_skinShadowProgram;
@ -1958,27 +2181,59 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f
skinProgram = &_skinTranslucentProgram; skinProgram = &_skinTranslucentProgram;
skinLocations = &_skinTranslucentLocations; skinLocations = &_skinTranslucentLocations;
} else if (hasTangents) { } else if (hasEmissive) {
if (hasSpecular) { if (hasTangents) {
program = &_normalSpecularMapProgram; if (hasSpecular) {
locations = &_normalSpecularMapLocations; program = &_emissiveNormalSpecularMapProgram;
skinProgram = &_skinNormalSpecularMapProgram; locations = &_emissiveNormalSpecularMapLocations;
skinLocations = &_skinNormalSpecularMapLocations; skinProgram = &_skinEmissiveNormalSpecularMapProgram;
specularTextureUnit = GL_TEXTURE2; 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 { } else {
program = &_normalMapProgram; program = &_emissiveProgram;
locations = &_normalMapLocations; locations = &_emissiveLocations;
skinProgram = &_skinNormalMapProgram; skinProgram = &_skinEmissiveProgram;
skinLocations = &_skinNormalMapLocations; skinLocations = &_skinEmissiveLocations;
emissiveTextureUnit = GL_TEXTURE3;
} }
} else if (hasSpecular) { } else {
program = &_specularMapProgram; if (hasTangents) {
locations = &_specularMapLocations; if (hasSpecular) {
skinProgram = &_skinSpecularMapProgram; program = &_normalSpecularMapProgram;
skinLocations = &_skinSpecularMapLocations; locations = &_normalSpecularMapLocations;
specularTextureUnit = GL_TEXTURE1; 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; ProgramObject* activeProgram = program;
Locations* activeLocations = locations; 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, 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__); PROFILE_RANGE(__FUNCTION__);
int meshPartsRendered = 0; int meshPartsRendered = 0;
@ -2004,18 +2259,19 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool
bool pickProgramsNeeded = true; bool pickProgramsNeeded = true;
SkinLocations* skinLocations; SkinLocations* skinLocations;
GLenum specularTextureUnit; GLenum specularTextureUnit;
GLenum emissiveTextureUnit;
foreach(Model* model, _modelsInScene) { foreach(Model* model, _modelsInScene) {
QVector<int>* whichList = model->pickMeshList(translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned); QVector<int>* whichList = model->pickMeshList(translucent, alphaThreshold, hasEmissive, hasTangents, hasSpecular, isSkinned);
if (whichList) { if (whichList) {
QVector<int>& list = *whichList; QVector<int>& list = *whichList;
if (list.size() > 0) { if (list.size() > 0) {
if (pickProgramsNeeded) { 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; pickProgramsNeeded = false;
} }
model->setupBatchTransform(batch); 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)(); 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, 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__); PROFILE_RANGE(__FUNCTION__);
int meshPartsRendered = 0; int meshPartsRendered = 0;
QVector<int>* whichList = pickMeshList(translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned); QVector<int>* whichList = pickMeshList(translucent, alphaThreshold, hasEmissive, hasTangents, hasSpecular, isSkinned);
if (!whichList) { if (!whichList) {
qDebug() << "unexpected!!! we don't know which list of meshes to render..."; 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; SkinLocations* skinLocations;
GLenum specularTextureUnit; GLenum specularTextureUnit;
pickPrograms(batch, mode, translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned, args, skinLocations, specularTextureUnit); GLenum emissiveTextureUnit;
meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, skinLocations, specularTextureUnit); 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); GLBATCH(glUseProgram)(0);
return meshPartsRendered; return meshPartsRendered;
@ -2057,7 +2314,7 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl
int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, RenderArgs* args, int Model::renderMeshesFromList(QVector<int>& 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__); PROFILE_RANGE(__FUNCTION__);
bool dontCullOutOfViewMeshParts = Menu::getInstance()->isOptionChecked(MenuOption::DontCullOutOfViewMeshParts); bool dontCullOutOfViewMeshParts = Menu::getInstance()->isOptionChecked(MenuOption::DontCullOutOfViewMeshParts);
bool cullTooSmallMeshParts = !Menu::getInstance()->isOptionChecked(MenuOption::DontCullTooSmallMeshParts); bool cullTooSmallMeshParts = !Menu::getInstance()->isOptionChecked(MenuOption::DontCullTooSmallMeshParts);
@ -2198,6 +2455,15 @@ int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMod
Application::getInstance()->getTextureCache()->getWhiteTextureID() : specularMap->getID()); Application::getInstance()->getTextureCache()->getWhiteTextureID() : specularMap->getID());
GLBATCH(glActiveTexture)(GL_TEXTURE0); 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) { if (args) {
args->_materialSwitches++; args->_materialSwitches++;
} }
@ -2238,6 +2504,12 @@ int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMod
GLBATCH(glActiveTexture)(GL_TEXTURE0); GLBATCH(glActiveTexture)(GL_TEXTURE0);
} }
if (emissiveTextureUnit) {
GLBATCH(glActiveTexture)(emissiveTextureUnit);
GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
GLBATCH(glActiveTexture)(GL_TEXTURE0);
}
GLBATCH(glPopMatrix)(); GLBATCH(glPopMatrix)();
} }

View file

@ -303,7 +303,12 @@ private:
static ProgramObject _specularMapProgram; static ProgramObject _specularMapProgram;
static ProgramObject _normalSpecularMapProgram; static ProgramObject _normalSpecularMapProgram;
static ProgramObject _translucentProgram; static ProgramObject _translucentProgram;
static ProgramObject _emissiveProgram;
static ProgramObject _emissiveNormalMapProgram;
static ProgramObject _emissiveSpecularMapProgram;
static ProgramObject _emissiveNormalSpecularMapProgram;
static ProgramObject _shadowProgram; static ProgramObject _shadowProgram;
static ProgramObject _skinProgram; static ProgramObject _skinProgram;
@ -311,7 +316,12 @@ private:
static ProgramObject _skinSpecularMapProgram; static ProgramObject _skinSpecularMapProgram;
static ProgramObject _skinNormalSpecularMapProgram; static ProgramObject _skinNormalSpecularMapProgram;
static ProgramObject _skinTranslucentProgram; static ProgramObject _skinTranslucentProgram;
static ProgramObject _skinEmissiveProgram;
static ProgramObject _skinEmissiveNormalMapProgram;
static ProgramObject _skinEmissiveSpecularMapProgram;
static ProgramObject _skinEmissiveNormalSpecularMapProgram;
static ProgramObject _skinShadowProgram; static ProgramObject _skinShadowProgram;
static int _normalMapTangentLocation; static int _normalMapTangentLocation;
@ -328,6 +338,11 @@ private:
static Locations _specularMapLocations; static Locations _specularMapLocations;
static Locations _normalSpecularMapLocations; static Locations _normalSpecularMapLocations;
static Locations _translucentLocations; 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); static void initProgram(ProgramObject& program, Locations& locations, int specularTextureUnit = 1);
@ -344,7 +359,12 @@ private:
static SkinLocations _skinNormalSpecularMapLocations; static SkinLocations _skinNormalSpecularMapLocations;
static SkinLocations _skinShadowLocations; static SkinLocations _skinShadowLocations;
static SkinLocations _skinTranslucentLocations; 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); static void initSkinProgram(ProgramObject& program, SkinLocations& locations, int specularTextureUnit = 1);
QVector<AABox> _calculatedMeshBoxes; QVector<AABox> _calculatedMeshBoxes;
@ -376,6 +396,16 @@ private:
QMap<QString, int> _unsortedMeshesOpaqueTangentsSpecularSkinned; QMap<QString, int> _unsortedMeshesOpaqueTangentsSpecularSkinned;
QMap<QString, int> _unsortedMeshesOpaqueSpecularSkinned; QMap<QString, int> _unsortedMeshesOpaqueSpecularSkinned;
QMap<QString, int> _unsortedMeshesOpaqueEmissive;
QMap<QString, int> _unsortedMeshesOpaqueEmissiveTangents;
QMap<QString, int> _unsortedMeshesOpaqueEmissiveTangentsSpecular;
QMap<QString, int> _unsortedMeshesOpaqueEmissiveSpecular;
QMap<QString, int> _unsortedMeshesOpaqueEmissiveSkinned;
QMap<QString, int> _unsortedMeshesOpaqueEmissiveTangentsSkinned;
QMap<QString, int> _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned;
QMap<QString, int> _unsortedMeshesOpaqueEmissiveSpecularSkinned;
QVector<int> _meshesTranslucent; QVector<int> _meshesTranslucent;
QVector<int> _meshesTranslucentTangents; QVector<int> _meshesTranslucentTangents;
QVector<int> _meshesTranslucentTangentsSpecular; QVector<int> _meshesTranslucentTangentsSpecular;
@ -396,6 +426,16 @@ private:
QVector<int> _meshesOpaqueTangentsSpecularSkinned; QVector<int> _meshesOpaqueTangentsSpecularSkinned;
QVector<int> _meshesOpaqueSpecularSkinned; QVector<int> _meshesOpaqueSpecularSkinned;
QVector<int> _meshesOpaqueEmissive;
QVector<int> _meshesOpaqueEmissiveTangents;
QVector<int> _meshesOpaqueEmissiveTangentsSpecular;
QVector<int> _meshesOpaqueEmissiveSpecular;
QVector<int> _meshesOpaqueEmissiveSkinned;
QVector<int> _meshesOpaqueEmissiveTangentsSkinned;
QVector<int> _meshesOpaqueEmissiveTangentsSpecularSkinned;
QVector<int> _meshesOpaqueEmissiveSpecularSkinned;
// Scene rendering support // Scene rendering support
static QVector<Model*> _modelsInScene; static QVector<Model*> _modelsInScene;
static gpu::Batch _sceneRenderBatch; static gpu::Batch _sceneRenderBatch;
@ -407,19 +447,19 @@ private:
void renderSetup(RenderArgs* args); void renderSetup(RenderArgs* args);
bool renderCore(float alpha, RenderMode mode, RenderArgs* args); bool renderCore(float alpha, RenderMode mode, RenderArgs* args);
int renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, 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); void setupBatchTransform(gpu::Batch& batch);
QVector<int>* pickMeshList(bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, bool isSkinned); QVector<int>* pickMeshList(bool translucent, float alphaThreshold, bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned);
int renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, int renderMeshesFromList(QVector<int>& 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, static void pickPrograms(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,
SkinLocations*& skinLocations, GLenum& specularTextureUnit); SkinLocations*& skinLocations, GLenum& specularTextureUnit, GLenum& emissiveTextureUnit);
static int renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, 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);
}; };

View file

@ -25,7 +25,7 @@ class NetworkTexture;
typedef QSharedPointer<NetworkTexture> NetworkTexturePointer; typedef QSharedPointer<NetworkTexture> 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. /// Stores cached textures, including render-to-texture targets.
class TextureCache : public ResourceCache { class TextureCache : public ResourceCache {
@ -67,7 +67,7 @@ public:
/// Returns the ID of the primary framebuffer object's specular texture. /// Returns the ID of the primary framebuffer object's specular texture.
GLuint getPrimarySpecularTextureID(); GLuint getPrimarySpecularTextureID();
/// Enables or disables draw buffers on the primary framebuffer. Note: the primary framebuffer must be bound. /// 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); void setPrimaryDrawBuffers(bool color, bool normal = false, bool specular = false);

View file

@ -41,6 +41,15 @@ bool FBXMesh::hasSpecularTexture() const {
return false; 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 FBXGeometry::getJointNames() const {
QStringList names; QStringList names;
foreach (const FBXJoint& joint, joints) { foreach (const FBXJoint& joint, joints) {
@ -1045,6 +1054,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
QHash<QString, QString> diffuseTextures; QHash<QString, QString> diffuseTextures;
QHash<QString, QString> bumpTextures; QHash<QString, QString> bumpTextures;
QHash<QString, QString> specularTextures; QHash<QString, QString> specularTextures;
QHash<QString, QString> emissiveTextures;
QHash<QString, QString> localRotations; QHash<QString, QString> localRotations;
QHash<QString, QString> xComponents; QHash<QString, QString> xComponents;
QHash<QString, QString> yComponents; QHash<QString, QString> yComponents;
@ -1417,6 +1427,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
ooChildToParent.insert(childID, parentID); ooChildToParent.insert(childID, parentID);
} }
if (connection.properties.at(0) == "OP") { if (connection.properties.at(0) == "OP") {
int counter = 0;
QByteArray type = connection.properties.at(3).toByteArray().toLower(); QByteArray type = connection.properties.at(3).toByteArray().toLower();
if (type.contains("diffuse")) { if (type.contains("diffuse")) {
diffuseTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); 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") { } else if (type == "d|z") {
zComponents.insert(getID(connection.properties, 2), getID(connection.properties, 1)); 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)); 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()) { if (!specularTextureID.isNull()) {
specularTexture = getTexture(specularTextureID, textureNames, textureFilenames, textureContent); 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++) { for (int j = 0; j < extracted.partMaterialTextures.size(); j++) {
if (extracted.partMaterialTextures.at(j).first == materialIndex) { if (extracted.partMaterialTextures.at(j).first == materialIndex) {
@ -1684,6 +1718,9 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
if (!specularTexture.filename.isNull()) { if (!specularTexture.filename.isNull()) {
part.specularTexture = specularTexture; part.specularTexture = specularTexture;
} }
if (!emissiveTexture.filename.isNull()) {
part.emissiveTexture = emissiveTexture;
}
part.materialID = material.id; part.materialID = material.id;
} }
} }

View file

@ -120,6 +120,7 @@ public:
FBXTexture diffuseTexture; FBXTexture diffuseTexture;
FBXTexture normalTexture; FBXTexture normalTexture;
FBXTexture specularTexture; FBXTexture specularTexture;
FBXTexture emissiveTexture;
QString materialID; QString materialID;
}; };
@ -147,6 +148,7 @@ public:
QVector<FBXBlendshape> blendshapes; QVector<FBXBlendshape> blendshapes;
bool hasSpecularTexture() const; bool hasSpecularTexture() const;
bool hasEmissiveTexture() const;
}; };
/// A single animation frame extracted from an FBX document. /// A single animation frame extracted from an FBX document.