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
// 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.

View file

@ -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);
}
}
}

View file

@ -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<QObject>& 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<QPointer<QObject>, 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<QObject>& 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());

View file

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

View file

@ -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<NetworkMesh>& 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<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__);
// 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;
} 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<int>* 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<int>* whichList = model->pickMeshList(translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned);
QVector<int>* whichList = model->pickMeshList(translucent, alphaThreshold, hasEmissive, hasTangents, hasSpecular, isSkinned);
if (whichList) {
QVector<int>& 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<int>* whichList = pickMeshList(translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned);
QVector<int>* 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<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__);
bool dontCullOutOfViewMeshParts = Menu::getInstance()->isOptionChecked(MenuOption::DontCullOutOfViewMeshParts);
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());
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<int>& 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)();
}

View file

@ -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<AABox> _calculatedMeshBoxes;
@ -376,6 +396,16 @@ private:
QMap<QString, int> _unsortedMeshesOpaqueTangentsSpecularSkinned;
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> _meshesTranslucentTangents;
QVector<int> _meshesTranslucentTangentsSpecular;
@ -396,6 +426,16 @@ private:
QVector<int> _meshesOpaqueTangentsSpecularSkinned;
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
static QVector<Model*> _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<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,
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);
};

View file

@ -25,7 +25,7 @@ class NetworkTexture;
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.
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);

View file

@ -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<QString, QString> diffuseTextures;
QHash<QString, QString> bumpTextures;
QHash<QString, QString> specularTextures;
QHash<QString, QString> emissiveTextures;
QHash<QString, QString> localRotations;
QHash<QString, QString> xComponents;
QHash<QString, QString> 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;
}
}

View file

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