From eb19b934332bd99abecfb561d8fe22476a91fa5b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 28 May 2015 17:19:30 -0700 Subject: [PATCH 1/7] render models in scene checkpoint --- .../src/EntityTreeRenderer.cpp | 41 ++- .../src/EntityTreeRenderer.h | 4 + .../src/RenderableModelEntityItem.cpp | 34 ++- .../src/RenderableModelEntityItem.h | 7 +- libraries/entities/src/EntityItem.cpp | 2 +- libraries/entities/src/EntityItem.h | 1 + libraries/render-utils/src/Model.cpp | 269 ++++++++++++++++++ libraries/render-utils/src/Model.h | 26 ++ 8 files changed, 373 insertions(+), 11 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 130f99cf4e..5f20e55298 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -489,6 +489,10 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptr_renderer = this; + + checkPendingAddToScene(renderArgs); + Model::startScene(renderArgs->_renderSide); ViewFrustum* frustum = (renderArgs->_renderMode == RenderArgs::SHADOW_RENDER_MODE) ? @@ -503,7 +507,6 @@ void EntityTreeRenderer::render(RenderArgs* renderArgs) { batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - renderArgs->_renderer = this; renderArgs->_batch = &batch; _tree->lockForRead(); @@ -1081,16 +1084,38 @@ void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) { void EntityTreeRenderer::addingEntity(const EntityItemID& entityID) { checkAndCallPreload(entityID); - - // here's where we add the entity payload to the scene auto entity = static_cast(_tree)->findEntityByID(entityID); + addEntityToScene(entity); +} + +void EntityTreeRenderer::addEntityToScene(EntityItemPointer entity) { + // here's where we add the entity payload to the scene if (entity && entity->canRenderInScene()) { - render::PendingChanges pendingChanges; - auto scene = _viewState->getMain3DScene(); - if (entity->addToScene(entity, scene, pendingChanges)) { - _entitiesInScene.insert(entity); + if (entity->readyToAddToScene()) { + render::PendingChanges pendingChanges; + auto scene = _viewState->getMain3DScene(); + if (entity->addToScene(entity, scene, pendingChanges)) { + _entitiesInScene.insert(entity); + } + scene->enqueuePendingChanges(pendingChanges); + } else { + if (!_pendingAddToScene.contains(entity)) { + _pendingAddToScene << entity; + } } - scene->enqueuePendingChanges(pendingChanges); + } +} + +void EntityTreeRenderer::checkPendingAddToScene(RenderArgs* renderArgs) { + QSet addedToScene; + foreach (auto entity, _pendingAddToScene) { + if (entity->readyToAddToScene(renderArgs)) { + addEntityToScene(entity); + addedToScene << entity; + } + } + foreach (auto addedEntity, addedToScene) { + _pendingAddToScene.remove(addedEntity); } } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 234e590b7d..bb9bff5d10 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -124,6 +124,10 @@ protected: virtual Octree* createTree() { return new EntityTree(true); } private: + void checkPendingAddToScene(RenderArgs* renderArgs); + void addEntityToScene(EntityItemPointer entity); + QSet _pendingAddToScene; + void applyZonePropertiesToScene(std::shared_ptr zone); void renderElementProxy(EntityTreeElement* entityTreeElement, RenderArgs* args); void checkAndCallPreload(const EntityItemID& entityID); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 5b56b79d5e..62a9eb8887 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -108,7 +108,35 @@ void RenderableModelEntityItem::remapTextures() { _currentTextures = _textures; } +bool RenderableModelEntityItem::readyToAddToScene(RenderArgs* renderArgs) { + if (!_model && renderArgs) { + // TODO: this getModel() appears to be about 3% of model render time. We should optimize + PerformanceTimer perfTimer("getModel"); + EntityTreeRenderer* renderer = static_cast(renderArgs->_renderer); + qDebug() << "RenderableModelEntityItem::readyToAddToScene().... renderer:" << renderer; + getModel(renderer); + } + bool ready = (bool)_model; + qDebug() << "RenderableModelEntityItem::readyToAddToScene().... id:" << getEntityItemID() + << "ready:" << ready << "renderArgs:" << renderArgs; + return ready; +} + +bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_ptr scene, + render::PendingChanges& pendingChanges) { + qDebug() << "RenderableModelEntityItem::addToScene().... id:" << getEntityItemID(); + return false; +} + +void RenderableModelEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr scene, + render::PendingChanges& pendingChanges) { + qDebug() << "RenderableModelEntityItem::removeFromScene().... id:" << getEntityItemID(); + + +} + void RenderableModelEntityItem::render(RenderArgs* args) { + qDebug() << "RenderableModelEntityItem::render().... id:" << getEntityItemID(); PerformanceTimer perfTimer("RMEIrender"); assert(getType() == EntityTypes::Model); @@ -199,6 +227,10 @@ void RenderableModelEntityItem::render(RenderArgs* args) { Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { Model* result = NULL; + + if (!renderer) { + return result; + } // make sure our renderer is setup if (!_myRenderer) { @@ -206,7 +238,7 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { } assert(_myRenderer == renderer); // you should only ever render on one renderer - if (QThread::currentThread() != _myRenderer->thread()) { + if (!_myRenderer || QThread::currentThread() != _myRenderer->thread()) { return _model; } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 335f3a4d25..55044e5d4d 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -43,7 +43,12 @@ public: virtual void somethingChangedNotification() { _needsInitialSimulation = true; } - virtual bool canRenderInScene() { return false; } // we don't yet play well with others + virtual bool canRenderInScene() { return true; } + virtual bool readyToAddToScene(RenderArgs* renderArgs = nullptr); + virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges); + virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges); + + virtual void render(RenderArgs* args); virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 6073f2150b..b911dd5964 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -973,7 +973,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) { } void EntityItem::recordCreationTime() { - assert(_created == UNKNOWN_CREATED_TIME); + //assert(_created == UNKNOWN_CREATED_TIME); _created = usecTimestampNow(); _lastEdited = _created; _lastUpdated = _created; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 5cbd29cfa8..93d2a7f035 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -158,6 +158,7 @@ public: { return 0; } virtual bool canRenderInScene() { return false; } // does your entity property render using Render Items and Payloads + virtual bool readyToAddToScene(RenderArgs* renderArgs = nullptr) { return true; } // we assume you're ready to add virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { return false; } // by default entity items don't add to scene virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index e304e6ee05..d6c8e8e588 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -765,6 +765,29 @@ void Model::renderSetup(RenderArgs* args) { } } +bool Model::addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges) { + bool somethingAdded = false; + // allow the attachments to add to scene + foreach (Model* attachment, _attachments) { + bool attachementSomethingAdded = attachment->addToScene(scene, pendingChanges); + somethingAdded = somethingAdded || attachementSomethingAdded; + } + + // TODO --- need to do something here + + return somethingAdded; +} + +void Model::removeFromScene(std::shared_ptr scene, render::PendingChanges& pendingChanges) { + // allow the attachments to remove to scene + foreach (Model* attachment, _attachments) { + attachment->removeFromScene(scene, pendingChanges); + } + + // TODO --- need to do something here + +} + bool Model::render(RenderArgs* renderArgs, float alpha) { PROFILE_RANGE(__FUNCTION__); @@ -2068,7 +2091,235 @@ bool Model::renderInScene(float alpha, RenderArgs* args) { return true; } +class TransparentMeshPart { +public: + TransparentMeshPart(Model* model, int meshIndex, int partIndex) : model(model), meshIndex(meshIndex), partIndex(partIndex) { } + typedef render::Payload Payload; + typedef Payload::DataPointer Pointer; + + Model* model; + int meshIndex; + int partIndex; +}; + +namespace render { + template <> const ItemKey payloadGetKey(const TransparentMeshPart::Pointer& payload) { + return ItemKey::Builder::transparentShape(); + } + + template <> const Item::Bound payloadGetBound(const TransparentMeshPart::Pointer& payload) { + if (payload) { + return payload->model->getPartBounds(payload->meshIndex, payload->partIndex); + } + return render::Item::Bound(); + } + template <> void payloadRender(const TransparentMeshPart::Pointer& payload, RenderArgs* args) { + if (args) { + args->_elementsTouched++; + return payload->model->renderPart(args, payload->meshIndex, payload->partIndex, true); + } + } +} + +class OpaqueMeshPart { +public: + OpaqueMeshPart(Model* model, int meshIndex, int partIndex) : model(model), meshIndex(meshIndex), partIndex(partIndex) { } + typedef render::Payload Payload; + typedef Payload::DataPointer Pointer; + + Model* model; + int meshIndex; + int partIndex; +}; + +namespace render { + template <> const ItemKey payloadGetKey(const OpaqueMeshPart::Pointer& payload) { + return ItemKey::Builder::opaqueShape(); + } + + template <> const Item::Bound payloadGetBound(const OpaqueMeshPart::Pointer& payload) { + if (payload) { + return payload->model->getPartBounds(payload->meshIndex, payload->partIndex); + } + return render::Item::Bound(); + } + template <> void payloadRender(const OpaqueMeshPart::Pointer& payload, RenderArgs* args) { + if (args) { + args->_elementsTouched++; + return payload->model->renderPart(args, payload->meshIndex, payload->partIndex, false); + } + } +} + +AABox Model::getPartBounds(int meshIndex, int partIndex) { + const FBXGeometry& geometry = _geometry->getFBXGeometry(); + const FBXMesh& mesh = geometry.meshes.at(meshIndex); + AABox partBox = mesh._mesh.evalPartBound(partIndex); + return partBox; +} + +void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool translucent) { + auto textureCache = DependencyManager::get(); + + const float DEFAULT_ALPHA_THRESHOLD = 0.5f; + + int i = meshIndex; + int j = partIndex; + gpu::Batch& batch = *(args->_batch); + auto mode = args->_renderMode; + auto alphaThreshold = DEFAULT_ALPHA_THRESHOLD; // FIX ME + const FBXGeometry& geometry = _geometry->getFBXGeometry(); + const QVector& networkMeshes = _geometry->getMeshes(); + + const NetworkMesh& networkMesh = networkMeshes.at(meshIndex); + const FBXMesh& mesh = geometry.meshes.at(meshIndex); + const MeshState& state = _meshStates.at(meshIndex); + + int vertexCount = mesh.vertices.size(); // NOTE: This seems wrong, shouldn't it be the part's vertex count? + + + bool translucentMesh = networkMesh.getTranslucentPartCount(mesh) == networkMesh.parts.size(); + bool hasTangents = !mesh.tangents.isEmpty(); + bool hasSpecular = mesh.hasSpecularTexture(); + bool hasLightmap = mesh.hasEmissiveTexture(); + bool isSkinned = state.clusterMatrices.size() > 1; + bool wireframe = isWireframe(); + + if (wireframe) { + translucentMesh = hasTangents = hasSpecular = hasLightmap = isSkinned = false; + } + + Locations* locations = nullptr; + pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, wireframe, + args, locations); + + if (state.clusterMatrices.size() > 1) { + GLBATCH(glUniformMatrix4fv)(locations->clusterMatrices, state.clusterMatrices.size(), false, + (const float*)state.clusterMatrices.constData()); + batch.setModelTransform(Transform()); + } else { + batch.setModelTransform(Transform(state.clusterMatrices[0])); + } + + if (mesh.blendshapes.isEmpty()) { + batch.setInputFormat(networkMesh._vertexFormat); + batch.setInputStream(0, *networkMesh._vertexStream); + } else { + batch.setInputFormat(networkMesh._vertexFormat); + batch.setInputBuffer(0, _blendedVertexBuffers[i], 0, sizeof(glm::vec3)); + batch.setInputBuffer(1, _blendedVertexBuffers[i], vertexCount * sizeof(glm::vec3), sizeof(glm::vec3)); + batch.setInputStream(2, *networkMesh._vertexStream); + } + + if (mesh.colors.isEmpty()) { + GLBATCH(glColor4f)(1.0f, 1.0f, 1.0f, 1.0f); + } + + qint64 offset = 0; + + const NetworkMeshPart& networkPart = networkMesh.parts.at(j); + const FBXMeshPart& part = mesh.parts.at(j); + model::MaterialPointer material = part._material; + if ((networkPart.isTranslucent() || part.opacity != 1.0f) != translucent) { + offset += (part.quadIndices.size() + part.triangleIndices.size()) * sizeof(int); + //continue; + // FIX ME!!! + } + + // apply material properties + if (mode == RenderArgs::SHADOW_RENDER_MODE) { + /// GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); + } else { + const bool wantDebug = false; + if (wantDebug) { + qCDebug(renderutils) << "Material Changed ---------------------------------------------"; + qCDebug(renderutils) << "part INDEX:" << j; + qCDebug(renderutils) << "NEW part.materialID:" << part.materialID; + } + + if (locations->materialBufferUnit >= 0) { + batch.setUniformBuffer(locations->materialBufferUnit, material->getSchemaBuffer()); + } + + Texture* diffuseMap = networkPart.diffuseTexture.data(); + if (mesh.isEye && diffuseMap) { + diffuseMap = (_dilatedTextures[i][j] = + static_cast(diffuseMap)->getDilatedTexture(_pupilDilation)).data(); + } + static bool showDiffuse = true; + if (showDiffuse && diffuseMap) { + batch.setUniformTexture(0, diffuseMap->getGPUTexture()); + + } else { + batch.setUniformTexture(0, textureCache->getWhiteTexture()); + } + + if (locations->texcoordMatrices >= 0) { + glm::mat4 texcoordTransform[2]; + if (!part.diffuseTexture.transform.isIdentity()) { + part.diffuseTexture.transform.getMatrix(texcoordTransform[0]); + } + if (!part.emissiveTexture.transform.isIdentity()) { + part.emissiveTexture.transform.getMatrix(texcoordTransform[1]); + } + GLBATCH(glUniformMatrix4fv)(locations->texcoordMatrices, 2, false, (const float*) &texcoordTransform); + } + + if (!mesh.tangents.isEmpty()) { + Texture* normalMap = networkPart.normalTexture.data(); + batch.setUniformTexture(1, !normalMap ? + textureCache->getBlueTexture() : normalMap->getGPUTexture()); + + } + + if (locations->specularTextureUnit >= 0) { + Texture* specularMap = networkPart.specularTexture.data(); + batch.setUniformTexture(locations->specularTextureUnit, !specularMap ? + textureCache->getWhiteTexture() : specularMap->getGPUTexture()); + } + + if (args) { + args->_materialSwitches++; + } + + // HACK: For unkwon reason (yet!) this code that should be assigned only if the material changes need to be called for every + // drawcall with an emissive, so let's do it for now. + if (locations->emissiveTextureUnit >= 0) { + // assert(locations->emissiveParams >= 0); // we should have the emissiveParams defined in the shader + float emissiveOffset = part.emissiveParams.x; + float emissiveScale = part.emissiveParams.y; + GLBATCH(glUniform2f)(locations->emissiveParams, emissiveOffset, emissiveScale); + + Texture* emissiveMap = networkPart.emissiveTexture.data(); + batch.setUniformTexture(locations->emissiveTextureUnit, !emissiveMap ? + textureCache->getWhiteTexture() : emissiveMap->getGPUTexture()); + } + + } + + if (part.quadIndices.size() > 0) { + batch.drawIndexed(gpu::QUADS, part.quadIndices.size(), offset); + offset += part.quadIndices.size() * sizeof(int); + } + + if (part.triangleIndices.size() > 0) { + batch.drawIndexed(gpu::TRIANGLES, part.triangleIndices.size(), offset); + offset += part.triangleIndices.size() * sizeof(int); + } + + if (args) { + const int INDICES_PER_TRIANGLE = 3; + const int INDICES_PER_QUAD = 4; + args->_trianglesRendered += part.triangleIndices.size() / INDICES_PER_TRIANGLE; + args->_quadsRendered += part.quadIndices.size() / INDICES_PER_QUAD; + } + +} + void Model::segregateMeshGroups() { + + //qDebug() << "Model::segregateMeshGroups() ------------------------------------------------"; + _renderBuckets.clear(); const FBXGeometry& geometry = _geometry->getFBXGeometry(); @@ -2086,6 +2337,7 @@ void Model::segregateMeshGroups() { const NetworkMesh& networkMesh = networkMeshes.at(i); const FBXMesh& mesh = geometry.meshes.at(i); const MeshState& state = _meshStates.at(i); + bool translucentMesh = networkMesh.getTranslucentPartCount(mesh) == networkMesh.parts.size(); bool hasTangents = !mesh.tangents.isEmpty(); @@ -2097,6 +2349,23 @@ void Model::segregateMeshGroups() { if (wireframe) { translucentMesh = hasTangents = hasSpecular = hasLightmap = isSkinned = false; } + + // Debug... + //qDebug() << "Mesh parts..." << mesh._mesh.getNumParts(); + int totalParts = mesh._mesh.getNumParts(); + for (int partIndex = 0; partIndex < totalParts; partIndex++) { + AABox boxPart = mesh._mesh.evalPartBound(partIndex); + + // this is a good place to create our renderPayloads + if (translucentMesh) { + //qDebug() << "Transparent Mesh parts[" << partIndex << "].box=" << boxPart; + _transparentRenderItems << std::shared_ptr(new TransparentMeshPart(this, i, partIndex)); + } else { + //qDebug() << "Opaque Mesh parts[" << partIndex << "].box=" << boxPart; + _opaqueRenderItems << std::shared_ptr(new OpaqueMeshPart(this, i, partIndex)); + } + } + QString materialID; diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 66a1a87d1f..a8248172be 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -45,6 +45,21 @@ class Shape; #include "RenderArgs.h" class ViewFrustum; +namespace render { + class Scene; + class PendingChanges; +} +class OpaqueMeshPart; +class TransparentMeshPart; + +inline uint qHash(const std::shared_ptr& a, uint seed) { + return qHash(a.get(), seed); +} +inline uint qHash(const std::shared_ptr& a, uint seed) { + return qHash(a.get(), seed); +} + + /// A generic 3D model displaying geometry loaded from a URL. class Model : public QObject, public PhysicsEntity { @@ -105,6 +120,10 @@ public: bool renderInScene(float alpha = 1.0f, RenderArgs* args = NULL); static void endScene(RenderArgs* args); + // new Scene/Engine rendering support + bool addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges); + void removeFromScene(std::shared_ptr scene, render::PendingChanges& pendingChanges); + /// Sets the URL of the model to render. /// \param fallback the URL of a fallback model to render if the requested model fails to load /// \param retainCurrent if true, keep rendering the current model until the new one is loaded @@ -219,6 +238,9 @@ public: BoxFace& face, QString& extraInfo, bool pickAgainstTriangles = false); bool convexHullContains(glm::vec3 point); + AABox getPartBounds(int meshIndex, int partIndex); + void renderPart(RenderArgs* args, int meshIndex, int partIndex, bool translucent); + protected: QSharedPointer _geometry; @@ -511,6 +533,10 @@ private: RenderBucketMap _renderBuckets; bool _renderCollisionHull; + + + QSet> _transparentRenderItems; + QSet> _opaqueRenderItems; }; Q_DECLARE_METATYPE(QPointer) From dc62052a3ca9fce3fb56dcf84aab40653c5c7dc0 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 29 May 2015 11:07:25 -0700 Subject: [PATCH 2/7] more hacking on models --- .../src/RenderableModelEntityItem.cpp | 25 ++- libraries/entities/src/EntityItem.cpp | 4 +- libraries/render-utils/src/Model.cpp | 156 ++++++++++-------- libraries/render-utils/src/Model.h | 5 +- 4 files changed, 118 insertions(+), 72 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 62a9eb8887..385310cfe5 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -116,7 +116,22 @@ bool RenderableModelEntityItem::readyToAddToScene(RenderArgs* renderArgs) { qDebug() << "RenderableModelEntityItem::readyToAddToScene().... renderer:" << renderer; getModel(renderer); } - bool ready = (bool)_model; + if (renderArgs && _model && _needsInitialSimulation && _model->isActive()) { + qDebug() << "RenderableModelEntityItem::readyToAddToScene().... doing initial simulation"; + _model->renderSetup(renderArgs); + _model->setScaleToFit(true, getDimensions()); + _model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); + _model->setRotation(getRotation()); + _model->setTranslation(getPosition()); + + // make sure to simulate so everything gets set up correctly for rendering + { + PerformanceTimer perfTimer("_model->simulate"); + _model->simulate(0.0f); + } + _needsInitialSimulation = false; + } + bool ready = !_needsInitialSimulation && _model && _model->readyToAddToScene(renderArgs); qDebug() << "RenderableModelEntityItem::readyToAddToScene().... id:" << getEntityItemID() << "ready:" << ready << "renderArgs:" << renderArgs; return ready; @@ -125,14 +140,18 @@ bool RenderableModelEntityItem::readyToAddToScene(RenderArgs* renderArgs) { bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { qDebug() << "RenderableModelEntityItem::addToScene().... id:" << getEntityItemID(); + if (_model) { + return _model->addToScene(scene, pendingChanges); + } return false; } void RenderableModelEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { qDebug() << "RenderableModelEntityItem::removeFromScene().... id:" << getEntityItemID(); - - + if (_model) { + _model->removeFromScene(scene, pendingChanges); + } } void RenderableModelEntityItem::render(RenderArgs* args) { diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index c5452ee23a..d04f0427f6 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -653,15 +653,15 @@ void EntityItem::adjustEditPacketForClockSkew(unsigned char* editPacketBuffer, s // lastEdited quint64 lastEditedInLocalTime; memcpy(&lastEditedInLocalTime, dataAt, sizeof(lastEditedInLocalTime)); - assert(lastEditedInLocalTime > 0); quint64 lastEditedInServerTime = lastEditedInLocalTime + clockSkew; memcpy(dataAt, &lastEditedInServerTime, sizeof(lastEditedInServerTime)); - #ifdef WANT_DEBUG + #if 1 //def WANT_DEBUG qCDebug(entities, "EntityItem::adjustEditPacketForClockSkew()..."); qCDebug(entities) << " lastEditedInLocalTime: " << lastEditedInLocalTime; qCDebug(entities) << " clockSkew: " << clockSkew; qCDebug(entities) << " lastEditedInServerTime: " << lastEditedInServerTime; #endif + //assert(lastEditedInLocalTime > (quint64)0); } float EntityItem::computeMass() const { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index d6c8e8e588..200690bb20 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -765,6 +765,68 @@ void Model::renderSetup(RenderArgs* args) { } } + +class TransparentMeshPart { +public: + TransparentMeshPart(Model* model, int meshIndex, int partIndex) : model(model), meshIndex(meshIndex), partIndex(partIndex) { } + typedef render::Payload Payload; + typedef Payload::DataPointer Pointer; + + Model* model; + int meshIndex; + int partIndex; +}; + +namespace render { + template <> const ItemKey payloadGetKey(const TransparentMeshPart::Pointer& payload) { + return ItemKey::Builder::transparentShape(); + } + + template <> const Item::Bound payloadGetBound(const TransparentMeshPart::Pointer& payload) { + if (payload) { + return payload->model->getPartBounds(payload->meshIndex, payload->partIndex); + } + return render::Item::Bound(); + } + template <> void payloadRender(const TransparentMeshPart::Pointer& payload, RenderArgs* args) { + if (args) { + args->_elementsTouched++; + return payload->model->renderPart(args, payload->meshIndex, payload->partIndex, true); + } + } +} + +class OpaqueMeshPart { +public: + OpaqueMeshPart(Model* model, int meshIndex, int partIndex) : model(model), meshIndex(meshIndex), partIndex(partIndex) { } + typedef render::Payload Payload; + typedef Payload::DataPointer Pointer; + + Model* model; + int meshIndex; + int partIndex; +}; + +namespace render { + template <> const ItemKey payloadGetKey(const OpaqueMeshPart::Pointer& payload) { + return ItemKey::Builder::opaqueShape(); + } + + template <> const Item::Bound payloadGetBound(const OpaqueMeshPart::Pointer& payload) { + if (payload) { + return payload->model->getPartBounds(payload->meshIndex, payload->partIndex); + } + return render::Item::Bound(); + } + template <> void payloadRender(const OpaqueMeshPart::Pointer& payload, RenderArgs* args) { + if (args) { + args->_elementsTouched++; + return payload->model->renderPart(args, payload->meshIndex, payload->partIndex, false); + } + } +} + + bool Model::addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges) { bool somethingAdded = false; // allow the attachments to add to scene @@ -773,7 +835,24 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan somethingAdded = somethingAdded || attachementSomethingAdded; } - // TODO --- need to do something here + foreach (auto renderItem, _transparentRenderItems) { + auto item = scene->allocateID(); + auto renderData = TransparentMeshPart::Pointer(renderItem); + auto renderPayload = render::PayloadPointer(new TransparentMeshPart::Payload(renderData)); + pendingChanges.resetItem(item, renderPayload); + _renderItems << item; + qDebug() << "Model::addToScene() added transparent item:" << item; + somethingAdded = true; + } + foreach (auto renderItem, _opaqueRenderItems) { + auto item = scene->allocateID(); + auto renderData = OpaqueMeshPart::Pointer(renderItem); + auto renderPayload = render::PayloadPointer(new OpaqueMeshPart::Payload(renderData)); + pendingChanges.resetItem(item, renderPayload); + _renderItems << item; + qDebug() << "Model::addToScene() added opaque item:" << item; + somethingAdded = true; + } return somethingAdded; } @@ -784,8 +863,10 @@ void Model::removeFromScene(std::shared_ptr scene, render::Pendin attachment->removeFromScene(scene, pendingChanges); } - // TODO --- need to do something here - + foreach (auto item, _renderItems) { + pendingChanges.removeItem(item); + } + _renderItems.clear(); } bool Model::render(RenderArgs* renderArgs, float alpha) { @@ -2091,70 +2172,13 @@ bool Model::renderInScene(float alpha, RenderArgs* args) { return true; } -class TransparentMeshPart { -public: - TransparentMeshPart(Model* model, int meshIndex, int partIndex) : model(model), meshIndex(meshIndex), partIndex(partIndex) { } - typedef render::Payload Payload; - typedef Payload::DataPointer Pointer; - - Model* model; - int meshIndex; - int partIndex; -}; - -namespace render { - template <> const ItemKey payloadGetKey(const TransparentMeshPart::Pointer& payload) { - return ItemKey::Builder::transparentShape(); - } - - template <> const Item::Bound payloadGetBound(const TransparentMeshPart::Pointer& payload) { - if (payload) { - return payload->model->getPartBounds(payload->meshIndex, payload->partIndex); - } - return render::Item::Bound(); - } - template <> void payloadRender(const TransparentMeshPart::Pointer& payload, RenderArgs* args) { - if (args) { - args->_elementsTouched++; - return payload->model->renderPart(args, payload->meshIndex, payload->partIndex, true); - } - } -} - -class OpaqueMeshPart { -public: - OpaqueMeshPart(Model* model, int meshIndex, int partIndex) : model(model), meshIndex(meshIndex), partIndex(partIndex) { } - typedef render::Payload Payload; - typedef Payload::DataPointer Pointer; - - Model* model; - int meshIndex; - int partIndex; -}; - -namespace render { - template <> const ItemKey payloadGetKey(const OpaqueMeshPart::Pointer& payload) { - return ItemKey::Builder::opaqueShape(); - } - - template <> const Item::Bound payloadGetBound(const OpaqueMeshPart::Pointer& payload) { - if (payload) { - return payload->model->getPartBounds(payload->meshIndex, payload->partIndex); - } - return render::Item::Bound(); - } - template <> void payloadRender(const OpaqueMeshPart::Pointer& payload, RenderArgs* args) { - if (args) { - args->_elementsTouched++; - return payload->model->renderPart(args, payload->meshIndex, payload->partIndex, false); - } - } -} - AABox Model::getPartBounds(int meshIndex, int partIndex) { const FBXGeometry& geometry = _geometry->getFBXGeometry(); const FBXMesh& mesh = geometry.meshes.at(meshIndex); AABox partBox = mesh._mesh.evalPartBound(partIndex); + + // FIX ME! + // TODO: needs to translate to world space, these values are in model space return partBox; } @@ -2351,17 +2375,17 @@ void Model::segregateMeshGroups() { } // Debug... - //qDebug() << "Mesh parts..." << mesh._mesh.getNumParts(); + qDebug() << "Mesh parts... for " << _url << " count:" << mesh._mesh.getNumParts(); int totalParts = mesh._mesh.getNumParts(); for (int partIndex = 0; partIndex < totalParts; partIndex++) { AABox boxPart = mesh._mesh.evalPartBound(partIndex); // this is a good place to create our renderPayloads if (translucentMesh) { - //qDebug() << "Transparent Mesh parts[" << partIndex << "].box=" << boxPart; + qDebug() << "Transparent Mesh parts[" << partIndex << "].box=" << boxPart; _transparentRenderItems << std::shared_ptr(new TransparentMeshPart(this, i, partIndex)); } else { - //qDebug() << "Opaque Mesh parts[" << partIndex << "].box=" << boxPart; + qDebug() << "Opaque Mesh parts[" << partIndex << "].box=" << boxPart; _opaqueRenderItems << std::shared_ptr(new OpaqueMeshPart(this, i, partIndex)); } } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index a8248172be..77309a79a2 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -48,6 +48,7 @@ class ViewFrustum; namespace render { class Scene; class PendingChanges; + typedef unsigned int ItemID; } class OpaqueMeshPart; class TransparentMeshPart; @@ -114,6 +115,7 @@ public: virtual void simulate(float deltaTime, bool fullUpdate = true); bool render(RenderArgs* renderArgs, float alpha = 1.0f); + void renderSetup(RenderArgs* args); // Scene rendering support static void startScene(RenderArgs::RenderSide renderSide); @@ -121,6 +123,7 @@ public: static void endScene(RenderArgs* args); // new Scene/Engine rendering support + bool readyToAddToScene(RenderArgs* renderArgs = nullptr) { return isRenderable() && isActive() && isLoadedWithTextures(); } bool addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges); void removeFromScene(std::shared_ptr scene, render::PendingChanges& pendingChanges); @@ -392,7 +395,6 @@ private: static void endSceneSplitPass(RenderArgs::RenderMode mode = RenderArgs::DEFAULT_RENDER_MODE, RenderArgs* args = NULL); // helper functions used by render() or renderInScene() - void renderSetup(RenderArgs* args); bool renderCore(RenderArgs* args, float alpha); int renderMeshes(gpu::Batch& batch, RenderArgs::RenderMode mode, bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe, RenderArgs* args = NULL, @@ -537,6 +539,7 @@ private: QSet> _transparentRenderItems; QSet> _opaqueRenderItems; + QSet _renderItems; }; Q_DECLARE_METATYPE(QPointer) From 0124f98340c80299fc99c543a3096d84f71cdcbd Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 29 May 2015 21:56:24 -0700 Subject: [PATCH 3/7] more hacking on rendering model parts --- .../src/RenderableModelEntityItem.cpp | 14 +- libraries/render-utils/src/Model.cpp | 370 ++++++++++++------ 2 files changed, 264 insertions(+), 120 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 385310cfe5..6cde6f231f 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -108,6 +108,8 @@ void RenderableModelEntityItem::remapTextures() { _currentTextures = _textures; } +// TODO: we need a solution for changes to the postion/rotation/etc of a model... +// this current code path only addresses that in this setup case... not the changing/moving case bool RenderableModelEntityItem::readyToAddToScene(RenderArgs* renderArgs) { if (!_model && renderArgs) { // TODO: this getModel() appears to be about 3% of model render time. We should optimize @@ -116,9 +118,9 @@ bool RenderableModelEntityItem::readyToAddToScene(RenderArgs* renderArgs) { qDebug() << "RenderableModelEntityItem::readyToAddToScene().... renderer:" << renderer; getModel(renderer); } - if (renderArgs && _model && _needsInitialSimulation && _model->isActive()) { + if (renderArgs && _model && _needsInitialSimulation && _model->isActive() && _model->isLoadedWithTextures()) { qDebug() << "RenderableModelEntityItem::readyToAddToScene().... doing initial simulation"; - _model->renderSetup(renderArgs); + _model->setScaleToFit(true, getDimensions()); _model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); _model->setRotation(getRotation()); @@ -130,10 +132,16 @@ bool RenderableModelEntityItem::readyToAddToScene(RenderArgs* renderArgs) { _model->simulate(0.0f); } _needsInitialSimulation = false; + + _model->renderSetup(renderArgs); } bool ready = !_needsInitialSimulation && _model && _model->readyToAddToScene(renderArgs); + + /* qDebug() << "RenderableModelEntityItem::readyToAddToScene().... id:" << getEntityItemID() - << "ready:" << ready << "renderArgs:" << renderArgs; + << "ready:" << ready << "renderArgs:" << renderArgs + << "areMeshGroupsKnown():" << (_model ? _model->areMeshGroupsKnown() : false); + */ return ready; } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 200690bb20..054d5bd8ca 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -783,13 +783,15 @@ namespace render { } template <> const Item::Bound payloadGetBound(const TransparentMeshPart::Pointer& payload) { + qDebug() << "payloadGetBound(TransparentMeshPart) url:" << payload->model->getURL(); if (payload) { - return payload->model->getPartBounds(payload->meshIndex, payload->partIndex); + //return payload->model->getPartBounds(payload->meshIndex, payload->partIndex); } return render::Item::Bound(); } template <> void payloadRender(const TransparentMeshPart::Pointer& payload, RenderArgs* args) { if (args) { + qDebug() << "payloadRender(TransparentMeshPart) url:" << payload->model->getURL(); args->_elementsTouched++; return payload->model->renderPart(args, payload->meshIndex, payload->partIndex, true); } @@ -813,13 +815,15 @@ namespace render { } template <> const Item::Bound payloadGetBound(const OpaqueMeshPart::Pointer& payload) { + qDebug() << "payloadGetBound(OpaqueMeshPart) url:" << payload->model->getURL(); if (payload) { - return payload->model->getPartBounds(payload->meshIndex, payload->partIndex); + //return payload->model->getPartBounds(payload->meshIndex, payload->partIndex); } return render::Item::Bound(); } template <> void payloadRender(const OpaqueMeshPart::Pointer& payload, RenderArgs* args) { if (args) { + qDebug() << "payloadRender(OpaqueMeshPart) url:" << payload->model->getURL(); args->_elementsTouched++; return payload->model->renderPart(args, payload->meshIndex, payload->partIndex, false); } @@ -828,6 +832,7 @@ namespace render { bool Model::addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges) { + qDebug() << "Model::addToScene() url:" << getURL(); bool somethingAdded = false; // allow the attachments to add to scene foreach (Model* attachment, _attachments) { @@ -841,7 +846,7 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan auto renderPayload = render::PayloadPointer(new TransparentMeshPart::Payload(renderData)); pendingChanges.resetItem(item, renderPayload); _renderItems << item; - qDebug() << "Model::addToScene() added transparent item:" << item; + qDebug() << "Model::addToScene() added transparent item:" << item << "url:" << getURL(); somethingAdded = true; } foreach (auto renderItem, _opaqueRenderItems) { @@ -850,7 +855,7 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan auto renderPayload = render::PayloadPointer(new OpaqueMeshPart::Payload(renderData)); pendingChanges.resetItem(item, renderPayload); _renderItems << item; - qDebug() << "Model::addToScene() added opaque item:" << item; + qDebug() << "Model::addToScene() added opaque item:" << item << "url:" << getURL(); somethingAdded = true; } @@ -858,6 +863,7 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan } void Model::removeFromScene(std::shared_ptr scene, render::PendingChanges& pendingChanges) { + qDebug() << "Model::removeFromScene() url:" << getURL(); // allow the attachments to remove to scene foreach (Model* attachment, _attachments) { attachment->removeFromScene(scene, pendingChanges); @@ -2183,14 +2189,63 @@ AABox Model::getPartBounds(int meshIndex, int partIndex) { } void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool translucent) { + //renderCore(args, 1.0f); + //return; +qDebug() << "Model::renderPart()... meshIndex:" << meshIndex << "partIndex:" << partIndex << "url:" << _url; + renderSetup(args); auto textureCache = DependencyManager::get(); - const float DEFAULT_ALPHA_THRESHOLD = 0.5f; int i = meshIndex; int j = partIndex; gpu::Batch& batch = *(args->_batch); auto mode = args->_renderMode; + + // Setup the projection matrix + /* + if (args && args->_viewFrustum) { + glm::mat4 proj; + // If for easier debug depending on the pass + if (mode == RenderArgs::SHADOW_RENDER_MODE) { + args->_viewFrustum->evalProjectionMatrix(proj); + } else { + args->_viewFrustum->evalProjectionMatrix(proj); + } + batch.setProjectionTransform(proj); + } + */ + + // Capture the view matrix once for the rendering of this model + if (_transforms.empty()) { + _transforms.push_back(Transform()); + } + + _transforms[0] = _viewState->getViewTransform(); + + // apply entity translation offset to the viewTransform in one go (it's a preTranslate because viewTransform goes from world to eye space) + _transforms[0].preTranslate(-_translation); + + batch.setViewTransform(_transforms[0]); + + + // FIXME: Do I need this? it doesn't seem to do anything. + { + GLenum buffers[3]; + int bufferCount = 0; + + if (mode != RenderArgs::SHADOW_RENDER_MODE) { + buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; + } + if (mode != RenderArgs::SHADOW_RENDER_MODE) { + buffers[bufferCount++] = GL_COLOR_ATTACHMENT1; + } + if (mode != RenderArgs::SHADOW_RENDER_MODE) { + buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; + } + GLBATCH(glDrawBuffers)(bufferCount, buffers); + } + + const float DEFAULT_ALPHA_THRESHOLD = 0.5f; // auto alphaThreshold = DEFAULT_ALPHA_THRESHOLD; // FIX ME const FBXGeometry& geometry = _geometry->getFBXGeometry(); const QVector& networkMeshes = _geometry->getMeshes(); @@ -2217,127 +2272,210 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, wireframe, args, locations); - if (state.clusterMatrices.size() > 1) { - GLBATCH(glUniformMatrix4fv)(locations->clusterMatrices, state.clusterMatrices.size(), false, - (const float*)state.clusterMatrices.constData()); - batch.setModelTransform(Transform()); - } else { - batch.setModelTransform(Transform(state.clusterMatrices[0])); - } - if (mesh.blendshapes.isEmpty()) { - batch.setInputFormat(networkMesh._vertexFormat); - batch.setInputStream(0, *networkMesh._vertexStream); - } else { - batch.setInputFormat(networkMesh._vertexFormat); - batch.setInputBuffer(0, _blendedVertexBuffers[i], 0, sizeof(glm::vec3)); - batch.setInputBuffer(1, _blendedVertexBuffers[i], vertexCount * sizeof(glm::vec3), sizeof(glm::vec3)); - batch.setInputStream(2, *networkMesh._vertexStream); - } + QString lastMaterialID; + int meshPartsRendered = 0; + updateVisibleJointStates(); - if (mesh.colors.isEmpty()) { - GLBATCH(glColor4f)(1.0f, 1.0f, 1.0f, 1.0f); - } - - qint64 offset = 0; - - const NetworkMeshPart& networkPart = networkMesh.parts.at(j); - const FBXMeshPart& part = mesh.parts.at(j); - model::MaterialPointer material = part._material; - if ((networkPart.isTranslucent() || part.opacity != 1.0f) != translucent) { - offset += (part.quadIndices.size() + part.triangleIndices.size()) * sizeof(int); - //continue; - // FIX ME!!! - } - - // apply material properties - if (mode == RenderArgs::SHADOW_RENDER_MODE) { - /// GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); - } else { - const bool wantDebug = false; - if (wantDebug) { - qCDebug(renderutils) << "Material Changed ---------------------------------------------"; - qCDebug(renderutils) << "part INDEX:" << j; - qCDebug(renderutils) << "NEW part.materialID:" << part.materialID; + // i is the "index" from the original networkMeshes QVector... + { + + // if our index is ever out of range for either meshes or networkMeshes, then skip it, and set our _meshGroupsKnown + // to false to rebuild out mesh groups. + + if (i < 0 || i >= networkMeshes.size() || i > geometry.meshes.size()) { + _meshGroupsKnown = false; // regenerate these lists next time around. + qDebug() << "if (i < 0 || i >= networkMeshes.size() || i > geometry.meshes.size()) {.... BAIL!!!"; + return; // FIXME! } + + // exit early if the translucency doesn't match what we're drawing + const NetworkMesh& networkMesh = networkMeshes.at(i); + const FBXMesh& mesh = geometry.meshes.at(i); - if (locations->materialBufferUnit >= 0) { - batch.setUniformBuffer(locations->materialBufferUnit, material->getSchemaBuffer()); + batch.setIndexBuffer(gpu::UINT32, (networkMesh._indexBuffer), 0); + int vertexCount = mesh.vertices.size(); + if (vertexCount == 0) { + // sanity check + qDebug() << "if (vertexCount == 0) {.... BAIL!!!"; + return; // FIXME! } - - Texture* diffuseMap = networkPart.diffuseTexture.data(); - if (mesh.isEye && diffuseMap) { - diffuseMap = (_dilatedTextures[i][j] = - static_cast(diffuseMap)->getDilatedTexture(_pupilDilation)).data(); - } - static bool showDiffuse = true; - if (showDiffuse && diffuseMap) { - batch.setUniformTexture(0, diffuseMap->getGPUTexture()); - + + const MeshState& state = _meshStates.at(i); + if (state.clusterMatrices.size() > 1) { + GLBATCH(glUniformMatrix4fv)(locations->clusterMatrices, state.clusterMatrices.size(), false, + (const float*)state.clusterMatrices.constData()); + batch.setModelTransform(Transform()); } else { - batch.setUniformTexture(0, textureCache->getWhiteTexture()); + batch.setModelTransform(Transform(state.clusterMatrices[0])); } - if (locations->texcoordMatrices >= 0) { - glm::mat4 texcoordTransform[2]; - if (!part.diffuseTexture.transform.isIdentity()) { - part.diffuseTexture.transform.getMatrix(texcoordTransform[0]); + if (mesh.blendshapes.isEmpty()) { + batch.setInputFormat(networkMesh._vertexFormat); + batch.setInputStream(0, *networkMesh._vertexStream); + } else { + batch.setInputFormat(networkMesh._vertexFormat); + batch.setInputBuffer(0, _blendedVertexBuffers[i], 0, sizeof(glm::vec3)); + batch.setInputBuffer(1, _blendedVertexBuffers[i], vertexCount * sizeof(glm::vec3), sizeof(glm::vec3)); + batch.setInputStream(2, *networkMesh._vertexStream); + } + + if (mesh.colors.isEmpty()) { + qDebug() << " colors empty ... meshIndex:" << meshIndex << "partIndex:" << partIndex << "url:" << _url; + GLBATCH(glColor4f)(1.0f, 1.0f, 1.0f, 1.0f); + } else { + qDebug() << " colors size:" << mesh.colors.size() << " ... meshIndex:" << meshIndex << "partIndex:" << partIndex << "url:" << _url; + } + + qint64 offset = 0; + { // j + const NetworkMeshPart& networkPart = networkMesh.parts.at(j); + const FBXMeshPart& part = mesh.parts.at(j); + model::MaterialPointer material = part._material; + + /* + if ((networkPart.isTranslucent() || part.opacity != 1.0f) != translucent) { + offset += (part.quadIndices.size() + part.triangleIndices.size()) * sizeof(int); + return; // FIXME! } - if (!part.emissiveTexture.transform.isIdentity()) { - part.emissiveTexture.transform.getMatrix(texcoordTransform[1]); + */ + + // apply material properties + if (mode == RenderArgs::SHADOW_RENDER_MODE) { + /// GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); + + } else { + if (true) { //lastMaterialID != part.materialID) { + const bool wantDebug = true; + if (wantDebug) { + qCDebug(renderutils) << "Material Changed ---------------------------------------------"; + qCDebug(renderutils) << "part INDEX:" << j; + qCDebug(renderutils) << "NEW part.materialID:" << part.materialID; + } + + if (locations->materialBufferUnit >= 0) { + batch.setUniformBuffer(locations->materialBufferUnit, material->getSchemaBuffer()); + } + + Texture* diffuseMap = networkPart.diffuseTexture.data(); + if (mesh.isEye && diffuseMap) { + diffuseMap = (_dilatedTextures[i][j] = + static_cast(diffuseMap)->getDilatedTexture(_pupilDilation)).data(); + } + static bool showDiffuse = true; + if (showDiffuse && diffuseMap) { + batch.setUniformTexture(0, diffuseMap->getGPUTexture()); + + } else { + batch.setUniformTexture(0, textureCache->getWhiteTexture()); + } + + if (locations->texcoordMatrices >= 0) { + glm::mat4 texcoordTransform[2]; + if (!part.diffuseTexture.transform.isIdentity()) { + part.diffuseTexture.transform.getMatrix(texcoordTransform[0]); + } + if (!part.emissiveTexture.transform.isIdentity()) { + part.emissiveTexture.transform.getMatrix(texcoordTransform[1]); + } + GLBATCH(glUniformMatrix4fv)(locations->texcoordMatrices, 2, false, (const float*) &texcoordTransform); + } + + if (!mesh.tangents.isEmpty()) { + Texture* normalMap = networkPart.normalTexture.data(); + batch.setUniformTexture(1, !normalMap ? + textureCache->getBlueTexture() : normalMap->getGPUTexture()); + + } + + if (locations->specularTextureUnit >= 0) { + Texture* specularMap = networkPart.specularTexture.data(); + batch.setUniformTexture(locations->specularTextureUnit, !specularMap ? + textureCache->getWhiteTexture() : specularMap->getGPUTexture()); + } + + if (args) { + args->_materialSwitches++; + } + + } + + // HACK: For unkwon reason (yet!) this code that should be assigned only if the material changes need to be called for every + // drawcall with an emissive, so let's do it for now. + if (locations->emissiveTextureUnit >= 0) { + // assert(locations->emissiveParams >= 0); // we should have the emissiveParams defined in the shader + float emissiveOffset = part.emissiveParams.x; + float emissiveScale = part.emissiveParams.y; + GLBATCH(glUniform2f)(locations->emissiveParams, emissiveOffset, emissiveScale); + + Texture* emissiveMap = networkPart.emissiveTexture.data(); + batch.setUniformTexture(locations->emissiveTextureUnit, !emissiveMap ? + textureCache->getWhiteTexture() : emissiveMap->getGPUTexture()); + } + + lastMaterialID = part.materialID; + } + + meshPartsRendered++; + + if (part.quadIndices.size() > 0) { + qDebug() << "batch.drawIndexed(gpu::QUADS) size:" << part.quadIndices.size(); + batch.drawIndexed(gpu::QUADS, part.quadIndices.size(), offset); + offset += part.quadIndices.size() * sizeof(int); + } + + if (part.triangleIndices.size() > 0) { + qDebug() << "batch.drawIndexed(gpu::TRIANGLES) size:" << part.triangleIndices.size(); + batch.drawIndexed(gpu::TRIANGLES, part.triangleIndices.size(), offset); + offset += part.triangleIndices.size() * sizeof(int); + } + + if (args) { + const int INDICES_PER_TRIANGLE = 3; + const int INDICES_PER_QUAD = 4; + args->_trianglesRendered += part.triangleIndices.size() / INDICES_PER_TRIANGLE; + args->_quadsRendered += part.quadIndices.size() / INDICES_PER_QUAD; } - GLBATCH(glUniformMatrix4fv)(locations->texcoordMatrices, 2, false, (const float*) &texcoordTransform); } - - if (!mesh.tangents.isEmpty()) { - Texture* normalMap = networkPart.normalTexture.data(); - batch.setUniformTexture(1, !normalMap ? - textureCache->getBlueTexture() : normalMap->getGPUTexture()); - - } - - if (locations->specularTextureUnit >= 0) { - Texture* specularMap = networkPart.specularTexture.data(); - batch.setUniformTexture(locations->specularTextureUnit, !specularMap ? - textureCache->getWhiteTexture() : specularMap->getGPUTexture()); - } - - if (args) { - args->_materialSwitches++; - } - - // HACK: For unkwon reason (yet!) this code that should be assigned only if the material changes need to be called for every - // drawcall with an emissive, so let's do it for now. - if (locations->emissiveTextureUnit >= 0) { - // assert(locations->emissiveParams >= 0); // we should have the emissiveParams defined in the shader - float emissiveOffset = part.emissiveParams.x; - float emissiveScale = part.emissiveParams.y; - GLBATCH(glUniform2f)(locations->emissiveParams, emissiveOffset, emissiveScale); - - Texture* emissiveMap = networkPart.emissiveTexture.data(); - batch.setUniformTexture(locations->emissiveTextureUnit, !emissiveMap ? - textureCache->getWhiteTexture() : emissiveMap->getGPUTexture()); - } - } - if (part.quadIndices.size() > 0) { - batch.drawIndexed(gpu::QUADS, part.quadIndices.size(), offset); - offset += part.quadIndices.size() * sizeof(int); - } - - if (part.triangleIndices.size() > 0) { - batch.drawIndexed(gpu::TRIANGLES, part.triangleIndices.size(), offset); - offset += part.triangleIndices.size() * sizeof(int); - } - - if (args) { - const int INDICES_PER_TRIANGLE = 3; - const int INDICES_PER_QUAD = 4; - args->_trianglesRendered += part.triangleIndices.size() / INDICES_PER_TRIANGLE; - args->_quadsRendered += part.quadIndices.size() / INDICES_PER_QUAD; + + // NOTE: these don't seem to do anything + /* + GLBATCH(glDepthMask)(true); + GLBATCH(glDepthFunc)(GL_LESS); + GLBATCH(glDisable)(GL_CULL_FACE); + + if (mode == RenderArgs::SHADOW_RENDER_MODE) { + GLBATCH(glCullFace)(GL_BACK); } + GLBATCH(glActiveTexture)(GL_TEXTURE0 + 1); + GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); + GLBATCH(glActiveTexture)(GL_TEXTURE0 + 2); + GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); + GLBATCH(glActiveTexture)(GL_TEXTURE0 + 3); + GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); + GLBATCH(glActiveTexture)(GL_TEXTURE0); + GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); + + // deactivate vertex arrays after drawing + GLBATCH(glDisableClientState)(GL_NORMAL_ARRAY); + GLBATCH(glDisableClientState)(GL_VERTEX_ARRAY); + GLBATCH(glDisableClientState)(GL_TEXTURE_COORD_ARRAY); + GLBATCH(glDisableClientState)(GL_COLOR_ARRAY); + GLBATCH(glDisableVertexAttribArray)(gpu::Stream::TANGENT); + GLBATCH(glDisableVertexAttribArray)(gpu::Stream::SKIN_CLUSTER_INDEX); + GLBATCH(glDisableVertexAttribArray)(gpu::Stream::SKIN_CLUSTER_WEIGHT); + + // bind with 0 to switch back to normal operation + GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, 0); + GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, 0); + GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); + */ + + // Back to no program + GLBATCH(glUseProgram)(0); // NOTE: We need this or else the avatar will end up with the texture of the last entity } void Model::segregateMeshGroups() { @@ -2375,17 +2513,15 @@ void Model::segregateMeshGroups() { } // Debug... - qDebug() << "Mesh parts... for " << _url << " count:" << mesh._mesh.getNumParts(); - int totalParts = mesh._mesh.getNumParts(); + qDebug() << "Mesh parts... for " << _url << " count:" << mesh.parts.size(); + int totalParts = mesh.parts.size(); for (int partIndex = 0; partIndex < totalParts; partIndex++) { - AABox boxPart = mesh._mesh.evalPartBound(partIndex); - // this is a good place to create our renderPayloads if (translucentMesh) { - qDebug() << "Transparent Mesh parts[" << partIndex << "].box=" << boxPart; + qDebug() << "Transparent Mesh parts[" << partIndex << "]"; _transparentRenderItems << std::shared_ptr(new TransparentMeshPart(this, i, partIndex)); } else { - qDebug() << "Opaque Mesh parts[" << partIndex << "].box=" << boxPart; + qDebug() << "Opaque Mesh parts[" << partIndex << "]"; _opaqueRenderItems << std::shared_ptr(new OpaqueMeshPart(this, i, partIndex)); } } From 34fd1bd470faa3f39ce76cfdf2e0388d1d8406b6 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 30 May 2015 08:45:02 -0700 Subject: [PATCH 4/7] added debugging --- libraries/render-utils/src/Model.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 054d5bd8ca..1f397b40e8 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -2364,25 +2364,31 @@ qDebug() << "Model::renderPart()... meshIndex:" << meshIndex << "partIndex:" << } static bool showDiffuse = true; if (showDiffuse && diffuseMap) { + qCDebug(renderutils) << " batch.setUniformTexture(0, diffuseMap->getGPUTexture());"; batch.setUniformTexture(0, diffuseMap->getGPUTexture()); } else { + qCDebug(renderutils) << " batch.setUniformTexture(0, textureCache->getWhiteTexture());"; batch.setUniformTexture(0, textureCache->getWhiteTexture()); } if (locations->texcoordMatrices >= 0) { glm::mat4 texcoordTransform[2]; if (!part.diffuseTexture.transform.isIdentity()) { + qCDebug(renderutils) << " part.diffuseTexture.transform.getMatrix(texcoordTransform[0]);"; part.diffuseTexture.transform.getMatrix(texcoordTransform[0]); } if (!part.emissiveTexture.transform.isIdentity()) { + qCDebug(renderutils) << " part.emissiveTexture.transform.getMatrix(texcoordTransform[1]);"; part.emissiveTexture.transform.getMatrix(texcoordTransform[1]); } + qCDebug(renderutils) << " GLBATCH(glUniformMatrix4fv)(locations->texcoordMatrices, 2, false, (const float*) &texcoordTransform);"; GLBATCH(glUniformMatrix4fv)(locations->texcoordMatrices, 2, false, (const float*) &texcoordTransform); } if (!mesh.tangents.isEmpty()) { Texture* normalMap = networkPart.normalTexture.data(); + qCDebug(renderutils) << " batch.setUniformTexture(1, !normalMap ? textureCache->getBlueTexture() : normalMap->getGPUTexture());"; batch.setUniformTexture(1, !normalMap ? textureCache->getBlueTexture() : normalMap->getGPUTexture()); @@ -2390,6 +2396,7 @@ qDebug() << "Model::renderPart()... meshIndex:" << meshIndex << "partIndex:" << if (locations->specularTextureUnit >= 0) { Texture* specularMap = networkPart.specularTexture.data(); + qCDebug(renderutils) << " batch.setUniformTexture(locations->specularTextureUnit, !specularMap ? textureCache->getWhiteTexture() : specularMap->getGPUTexture());"; batch.setUniformTexture(locations->specularTextureUnit, !specularMap ? textureCache->getWhiteTexture() : specularMap->getGPUTexture()); } @@ -2409,7 +2416,8 @@ qDebug() << "Model::renderPart()... meshIndex:" << meshIndex << "partIndex:" << GLBATCH(glUniform2f)(locations->emissiveParams, emissiveOffset, emissiveScale); Texture* emissiveMap = networkPart.emissiveTexture.data(); - batch.setUniformTexture(locations->emissiveTextureUnit, !emissiveMap ? + qCDebug(renderutils) << " batch.setUniformTexture(locations->emissiveTextureUnit, !emissiveMap ? textureCache->getWhiteTexture() : emissiveMap->getGPUTexture());"; + batch.setUniformTexture(locations->emissiveTextureUnit, !emissiveMap ? textureCache->getWhiteTexture() : emissiveMap->getGPUTexture()); } From 1b8572640b6a615b564ff65a22afbe0fa4c2fe13 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 1 Jun 2015 09:07:32 -0700 Subject: [PATCH 5/7] more hacking sams tweaks --- interface/src/Application.cpp | 2 +- .../src/EntityTreeRenderer.cpp | 2 +- libraries/gpu/src/gpu/Context.cpp | 8 +- libraries/gpu/src/gpu/Context.h | 12 +- libraries/gpu/src/gpu/GLBackend.cpp | 17 ++ libraries/gpu/src/gpu/GLBackend.h | 4 +- .../src/DeferredLightingEffect.cpp | 4 +- libraries/render-utils/src/Model.cpp | 167 +++++++------- libraries/render/src/render/DrawTask.cpp | 216 ++++++++++++------ 9 files changed, 267 insertions(+), 165 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index da386cf696..e8e7606862 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -842,7 +842,7 @@ void Application::paintGL() { _glWidget->makeCurrent(); auto lodManager = DependencyManager::get(); - gpu::Context context; + gpu::Context context(new gpu::GLBackend()); RenderArgs renderArgs(&context, nullptr, getViewFrustum(), lodManager->getOctreeSizeScale(), lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 5f20e55298..af73c1cc02 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -524,7 +524,7 @@ void EntityTreeRenderer::render(RenderArgs* renderArgs) { _tree->unlock(); glPushMatrix(); - renderArgs->_context->enqueueBatch(batch); + renderArgs->_context->render(batch); glPopMatrix(); renderArgs->_batch = nullptr; diff --git a/libraries/gpu/src/gpu/Context.cpp b/libraries/gpu/src/gpu/Context.cpp index 78a6a6f607..c888003b29 100644 --- a/libraries/gpu/src/gpu/Context.cpp +++ b/libraries/gpu/src/gpu/Context.cpp @@ -15,7 +15,8 @@ using namespace gpu; -Context::Context() { +Context::Context(Backend* backend) : + _backend(backend) { } Context::Context(const Context& context) { @@ -31,6 +32,7 @@ bool Context::makeProgram(Shader& shader, const Shader::BindingSet& bindings) { return false; } -void Context::enqueueBatch(Batch& batch) { - GLBackend::renderBatch(batch, true); +void Context::render(Batch& batch) { + _backend->render(batch); + // GLBackend::renderBatch(batch, true); } diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index 7ffb22f1c8..97ecf6b846 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -31,6 +31,9 @@ class Batch; class Backend { public: + virtual~ Backend() {}; + virtual void render(Batch& batch) = 0; + class TransformObject { public: Mat4 _model; @@ -107,15 +110,14 @@ protected: class Context { public: - Context(); - Context(const Context& context); + Context(Backend* backend); ~Context(); - void enqueueBatch(Batch& batch); - + void render(Batch& batch); protected: + Context(const Context& context); // This function can only be called by "static Shader::makeProgram()" // makeProgramShader(...) make a program shader ready to be used in a Batch. @@ -123,6 +125,8 @@ protected: // If the shader passed is not a program, nothing happens. static bool makeProgram(Shader& shader, const Shader::BindingSet& bindings = Shader::BindingSet()); + std::unique_ptr _backend; + friend class Shader; }; diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 0dde9699f2..c26564a338 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -442,6 +442,8 @@ void Batch::_glUniform1f(GLint location, GLfloat v0) { } void GLBackend::do_glUniform1f(Batch& batch, uint32 paramOffset) { if (_pipeline._program == 0) { + // We should call updatePipeline() to bind the program but we are not doing that + // because these uniform setters are deprecated and we don;t want to create side effect return; } glUniform1f( @@ -460,6 +462,11 @@ void Batch::_glUniform2f(GLint location, GLfloat v0, GLfloat v1) { DO_IT_NOW(_glUniform2f, 1); } void GLBackend::do_glUniform2f(Batch& batch, uint32 paramOffset) { + if (_pipeline._program == 0) { + // We should call updatePipeline() to bind the program but we are not doing that + // because these uniform setters are deprecated and we don;t want to create side effect + return; + } glUniform2f( batch._params[paramOffset + 2]._int, batch._params[paramOffset + 1]._float, @@ -478,6 +485,11 @@ void Batch::_glUniform4fv(GLint location, GLsizei count, const GLfloat* value) { DO_IT_NOW(_glUniform4fv, 3); } void GLBackend::do_glUniform4fv(Batch& batch, uint32 paramOffset) { + if (_pipeline._program == 0) { + // We should call updatePipeline() to bind the program but we are not doing that + // because these uniform setters are deprecated and we don;t want to create side effect + return; + } glUniform4fv( batch._params[paramOffset + 2]._int, batch._params[paramOffset + 1]._uint, @@ -498,6 +510,11 @@ void Batch::_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpo DO_IT_NOW(_glUniformMatrix4fv, 4); } void GLBackend::do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset) { + if (_pipeline._program == 0) { + // We should call updatePipeline() to bind the program but we are not doing that + // because these uniform setters are deprecated and we don;t want to create side effect + return; + } glUniformMatrix4fv( batch._params[paramOffset + 3]._int, batch._params[paramOffset + 2]._uint, diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 6c70502458..da0fe77b24 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -26,9 +26,9 @@ public: explicit GLBackend(bool syncCache); GLBackend(); - ~GLBackend(); + virtual ~GLBackend(); - void render(Batch& batch); + virtual void render(Batch& batch); // Render Batch create a local Context and execute the batch with it // WARNING: diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 202c6c6a02..4398c1c3cc 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -107,7 +107,7 @@ void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) { } void DeferredLightingEffect::bindSimpleProgram(gpu::Batch& batch, bool textured) { - DependencyManager::get()->setPrimaryDrawBuffers(batch, true, true, true); + // DependencyManager::get()->setPrimaryDrawBuffers(batch, true, true, true); if (textured) { batch.setPipeline(_simpleProgramTextured); @@ -117,7 +117,7 @@ void DeferredLightingEffect::bindSimpleProgram(gpu::Batch& batch, bool textured) } void DeferredLightingEffect::releaseSimpleProgram(gpu::Batch& batch) { - DependencyManager::get()->setPrimaryDrawBuffers(batch, true, false, false); + // DependencyManager::get()->setPrimaryDrawBuffers(batch, true, false, false); } void DeferredLightingEffect::renderSolidSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec4& color) { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 1f397b40e8..894e929897 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -783,7 +783,7 @@ namespace render { } template <> const Item::Bound payloadGetBound(const TransparentMeshPart::Pointer& payload) { - qDebug() << "payloadGetBound(TransparentMeshPart) url:" << payload->model->getURL(); + //qDebug() << "payloadGetBound(TransparentMeshPart) url:" << payload->model->getURL(); if (payload) { //return payload->model->getPartBounds(payload->meshIndex, payload->partIndex); } @@ -791,7 +791,7 @@ namespace render { } template <> void payloadRender(const TransparentMeshPart::Pointer& payload, RenderArgs* args) { if (args) { - qDebug() << "payloadRender(TransparentMeshPart) url:" << payload->model->getURL(); + // qDebug() << "payloadRender(TransparentMeshPart) url:" << payload->model->getURL(); args->_elementsTouched++; return payload->model->renderPart(args, payload->meshIndex, payload->partIndex, true); } @@ -815,7 +815,7 @@ namespace render { } template <> const Item::Bound payloadGetBound(const OpaqueMeshPart::Pointer& payload) { - qDebug() << "payloadGetBound(OpaqueMeshPart) url:" << payload->model->getURL(); + // qDebug() << "payloadGetBound(OpaqueMeshPart) url:" << payload->model->getURL(); if (payload) { //return payload->model->getPartBounds(payload->meshIndex, payload->partIndex); } @@ -823,7 +823,7 @@ namespace render { } template <> void payloadRender(const OpaqueMeshPart::Pointer& payload, RenderArgs* args) { if (args) { - qDebug() << "payloadRender(OpaqueMeshPart) url:" << payload->model->getURL(); + // qDebug() << "payloadRender(OpaqueMeshPart) url:" << payload->model->getURL(); args->_elementsTouched++; return payload->model->renderPart(args, payload->meshIndex, payload->partIndex, false); } @@ -1957,9 +1957,12 @@ void Model::setupBatchTransform(gpu::Batch& batch, RenderArgs* args) { } void Model::endScene(RenderArgs* args) { + // Now that we migrated everything to the new RENDER/SCENE no more work to do! + return; PROFILE_RANGE(__FUNCTION__); + #if (GPU_TRANSFORM_PROFILE == GPU_LEGACY) // with legacy transform profile, we still to protect that transform stack... glPushMatrix(); @@ -1972,6 +1975,7 @@ void Model::endScene(RenderArgs* args) { renderSide = args->_renderSide; } + gpu::GLBackend backend; backend.syncCache(); // force sync with gl state here @@ -2191,7 +2195,7 @@ AABox Model::getPartBounds(int meshIndex, int partIndex) { void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool translucent) { //renderCore(args, 1.0f); //return; -qDebug() << "Model::renderPart()... meshIndex:" << meshIndex << "partIndex:" << partIndex << "url:" << _url; +//qDebug() << "Model::renderPart()... meshIndex:" << meshIndex << "partIndex:" << partIndex << "url:" << _url; renderSetup(args); auto textureCache = DependencyManager::get(); @@ -2229,7 +2233,7 @@ qDebug() << "Model::renderPart()... meshIndex:" << meshIndex << "partIndex:" << // FIXME: Do I need this? it doesn't seem to do anything. - { + /* { GLenum buffers[3]; int bufferCount = 0; @@ -2243,7 +2247,7 @@ qDebug() << "Model::renderPart()... meshIndex:" << meshIndex << "partIndex:" << buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; } GLBATCH(glDrawBuffers)(bufferCount, buffers); - } + }*/ const float DEFAULT_ALPHA_THRESHOLD = 0.5f; // auto alphaThreshold = DEFAULT_ALPHA_THRESHOLD; // FIX ME @@ -2285,7 +2289,7 @@ qDebug() << "Model::renderPart()... meshIndex:" << meshIndex << "partIndex:" << if (i < 0 || i >= networkMeshes.size() || i > geometry.meshes.size()) { _meshGroupsKnown = false; // regenerate these lists next time around. - qDebug() << "if (i < 0 || i >= networkMeshes.size() || i > geometry.meshes.size()) {.... BAIL!!!"; + // qDebug() << "if (i < 0 || i >= networkMeshes.size() || i > geometry.meshes.size()) {.... BAIL!!!"; return; // FIXME! } @@ -2297,7 +2301,7 @@ qDebug() << "Model::renderPart()... meshIndex:" << meshIndex << "partIndex:" << int vertexCount = mesh.vertices.size(); if (vertexCount == 0) { // sanity check - qDebug() << "if (vertexCount == 0) {.... BAIL!!!"; + // qDebug() << "if (vertexCount == 0) {.... BAIL!!!"; return; // FIXME! } @@ -2321,10 +2325,10 @@ qDebug() << "Model::renderPart()... meshIndex:" << meshIndex << "partIndex:" << } if (mesh.colors.isEmpty()) { - qDebug() << " colors empty ... meshIndex:" << meshIndex << "partIndex:" << partIndex << "url:" << _url; + // qDebug() << " colors empty ... meshIndex:" << meshIndex << "partIndex:" << partIndex << "url:" << _url; GLBATCH(glColor4f)(1.0f, 1.0f, 1.0f, 1.0f); } else { - qDebug() << " colors size:" << mesh.colors.size() << " ... meshIndex:" << meshIndex << "partIndex:" << partIndex << "url:" << _url; + // qDebug() << " colors size:" << mesh.colors.size() << " ... meshIndex:" << meshIndex << "partIndex:" << partIndex << "url:" << _url; } qint64 offset = 0; @@ -2333,6 +2337,7 @@ qDebug() << "Model::renderPart()... meshIndex:" << meshIndex << "partIndex:" << const FBXMeshPart& part = mesh.parts.at(j); model::MaterialPointer material = part._material; + if (material != nullptr) { /* if ((networkPart.isTranslucent() || part.opacity != 1.0f) != translucent) { offset += (part.quadIndices.size() + part.triangleIndices.size()) * sizeof(int); @@ -2340,86 +2345,88 @@ qDebug() << "Model::renderPart()... meshIndex:" << meshIndex << "partIndex:" << } */ - // apply material properties - if (mode == RenderArgs::SHADOW_RENDER_MODE) { - /// GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); + // apply material properties + if (mode == RenderArgs::SHADOW_RENDER_MODE) { + /// GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); - } else { - if (true) { //lastMaterialID != part.materialID) { - const bool wantDebug = true; - if (wantDebug) { - qCDebug(renderutils) << "Material Changed ---------------------------------------------"; - qCDebug(renderutils) << "part INDEX:" << j; - qCDebug(renderutils) << "NEW part.materialID:" << part.materialID; - } + } else { + if (true) { //lastMaterialID != part.materialID) { + const bool wantDebug = false; + if (wantDebug) { + qCDebug(renderutils) << "Material Changed ---------------------------------------------"; + qCDebug(renderutils) << "part INDEX:" << j; + qCDebug(renderutils) << "NEW part.materialID:" << part.materialID; + } - if (locations->materialBufferUnit >= 0) { - batch.setUniformBuffer(locations->materialBufferUnit, material->getSchemaBuffer()); - } + if (locations->materialBufferUnit >= 0) { + batch.setUniformBuffer(locations->materialBufferUnit, material->getSchemaBuffer()); + } - Texture* diffuseMap = networkPart.diffuseTexture.data(); - if (mesh.isEye && diffuseMap) { - diffuseMap = (_dilatedTextures[i][j] = - static_cast(diffuseMap)->getDilatedTexture(_pupilDilation)).data(); - } - static bool showDiffuse = true; - if (showDiffuse && diffuseMap) { - qCDebug(renderutils) << " batch.setUniformTexture(0, diffuseMap->getGPUTexture());"; - batch.setUniformTexture(0, diffuseMap->getGPUTexture()); + Texture* diffuseMap = networkPart.diffuseTexture.data(); + if (mesh.isEye && diffuseMap) { + diffuseMap = (_dilatedTextures[i][j] = + static_cast(diffuseMap)->getDilatedTexture(_pupilDilation)).data(); + } + static bool showDiffuse = true; + if (showDiffuse && diffuseMap) { + // qCDebug(renderutils) << " batch.setUniformTexture(0, diffuseMap->getGPUTexture());"; + batch.setUniformTexture(0, diffuseMap->getGPUTexture()); - } else { - qCDebug(renderutils) << " batch.setUniformTexture(0, textureCache->getWhiteTexture());"; - batch.setUniformTexture(0, textureCache->getWhiteTexture()); - } - - if (locations->texcoordMatrices >= 0) { - glm::mat4 texcoordTransform[2]; - if (!part.diffuseTexture.transform.isIdentity()) { - qCDebug(renderutils) << " part.diffuseTexture.transform.getMatrix(texcoordTransform[0]);"; - part.diffuseTexture.transform.getMatrix(texcoordTransform[0]); + } else { + // qCDebug(renderutils) << " batch.setUniformTexture(0, textureCache->getWhiteTexture());"; + batch.setUniformTexture(0, textureCache->getWhiteTexture()); } - if (!part.emissiveTexture.transform.isIdentity()) { - qCDebug(renderutils) << " part.emissiveTexture.transform.getMatrix(texcoordTransform[1]);"; - part.emissiveTexture.transform.getMatrix(texcoordTransform[1]); + + if (locations->texcoordMatrices >= 0) { + glm::mat4 texcoordTransform[2]; + if (!part.diffuseTexture.transform.isIdentity()) { + // qCDebug(renderutils) << " part.diffuseTexture.transform.getMatrix(texcoordTransform[0]);"; + part.diffuseTexture.transform.getMatrix(texcoordTransform[0]); + } + if (!part.emissiveTexture.transform.isIdentity()) { + // qCDebug(renderutils) << " part.emissiveTexture.transform.getMatrix(texcoordTransform[1]);"; + part.emissiveTexture.transform.getMatrix(texcoordTransform[1]); + } + // qCDebug(renderutils) << " GLBATCH(glUniformMatrix4fv)(locations->texcoordMatrices, 2, false, (const float*) &texcoordTransform);"; + GLBATCH(glUniformMatrix4fv)(locations->texcoordMatrices, 2, false, (const float*) &texcoordTransform); } - qCDebug(renderutils) << " GLBATCH(glUniformMatrix4fv)(locations->texcoordMatrices, 2, false, (const float*) &texcoordTransform);"; - GLBATCH(glUniformMatrix4fv)(locations->texcoordMatrices, 2, false, (const float*) &texcoordTransform); - } - if (!mesh.tangents.isEmpty()) { - Texture* normalMap = networkPart.normalTexture.data(); - qCDebug(renderutils) << " batch.setUniformTexture(1, !normalMap ? textureCache->getBlueTexture() : normalMap->getGPUTexture());"; - batch.setUniformTexture(1, !normalMap ? - textureCache->getBlueTexture() : normalMap->getGPUTexture()); + if (!mesh.tangents.isEmpty()) { + Texture* normalMap = networkPart.normalTexture.data(); + // qCDebug(renderutils) << " batch.setUniformTexture(1, !normalMap ? textureCache->getBlueTexture() : normalMap->getGPUTexture());"; + batch.setUniformTexture(1, !normalMap ? + textureCache->getBlueTexture() : normalMap->getGPUTexture()); - } + } - if (locations->specularTextureUnit >= 0) { - Texture* specularMap = networkPart.specularTexture.data(); - qCDebug(renderutils) << " batch.setUniformTexture(locations->specularTextureUnit, !specularMap ? textureCache->getWhiteTexture() : specularMap->getGPUTexture());"; - batch.setUniformTexture(locations->specularTextureUnit, !specularMap ? - textureCache->getWhiteTexture() : specularMap->getGPUTexture()); + if (locations->specularTextureUnit >= 0) { + Texture* specularMap = networkPart.specularTexture.data(); + // qCDebug(renderutils) << " batch.setUniformTexture(locations->specularTextureUnit, !specularMap ? textureCache->getWhiteTexture() : specularMap->getGPUTexture());"; + batch.setUniformTexture(locations->specularTextureUnit, !specularMap ? + textureCache->getWhiteTexture() : specularMap->getGPUTexture()); + } + + if (args) { + args->_materialSwitches++; + } + } - if (args) { - args->_materialSwitches++; + // HACK: For unkwon reason (yet!) this code that should be assigned only if the material changes need to be called for every + // drawcall with an emissive, so let's do it for now. + if (locations->emissiveTextureUnit >= 0) { + // assert(locations->emissiveParams >= 0); // we should have the emissiveParams defined in the shader + float emissiveOffset = part.emissiveParams.x; + float emissiveScale = part.emissiveParams.y; + GLBATCH(glUniform2f)(locations->emissiveParams, emissiveOffset, emissiveScale); + + Texture* emissiveMap = networkPart.emissiveTexture.data(); + // qCDebug(renderutils) << " batch.setUniformTexture(locations->emissiveTextureUnit, !emissiveMap ? textureCache->getWhiteTexture() : emissiveMap->getGPUTexture());"; + batch.setUniformTexture(locations->emissiveTextureUnit, !emissiveMap ? + textureCache->getWhiteTexture() : emissiveMap->getGPUTexture()); } - } - // HACK: For unkwon reason (yet!) this code that should be assigned only if the material changes need to be called for every - // drawcall with an emissive, so let's do it for now. - if (locations->emissiveTextureUnit >= 0) { - // assert(locations->emissiveParams >= 0); // we should have the emissiveParams defined in the shader - float emissiveOffset = part.emissiveParams.x; - float emissiveScale = part.emissiveParams.y; - GLBATCH(glUniform2f)(locations->emissiveParams, emissiveOffset, emissiveScale); - - Texture* emissiveMap = networkPart.emissiveTexture.data(); - qCDebug(renderutils) << " batch.setUniformTexture(locations->emissiveTextureUnit, !emissiveMap ? textureCache->getWhiteTexture() : emissiveMap->getGPUTexture());"; - batch.setUniformTexture(locations->emissiveTextureUnit, !emissiveMap ? - textureCache->getWhiteTexture() : emissiveMap->getGPUTexture()); - } lastMaterialID = part.materialID; } @@ -2427,13 +2434,13 @@ qDebug() << "Model::renderPart()... meshIndex:" << meshIndex << "partIndex:" << meshPartsRendered++; if (part.quadIndices.size() > 0) { - qDebug() << "batch.drawIndexed(gpu::QUADS) size:" << part.quadIndices.size(); + // qDebug() << "batch.drawIndexed(gpu::QUADS) size:" << part.quadIndices.size(); batch.drawIndexed(gpu::QUADS, part.quadIndices.size(), offset); offset += part.quadIndices.size() * sizeof(int); } if (part.triangleIndices.size() > 0) { - qDebug() << "batch.drawIndexed(gpu::TRIANGLES) size:" << part.triangleIndices.size(); + // qDebug() << "batch.drawIndexed(gpu::TRIANGLES) size:" << part.triangleIndices.size(); batch.drawIndexed(gpu::TRIANGLES, part.triangleIndices.size(), offset); offset += part.triangleIndices.size() * sizeof(int); } @@ -2483,7 +2490,7 @@ qDebug() << "Model::renderPart()... meshIndex:" << meshIndex << "partIndex:" << */ // Back to no program - GLBATCH(glUseProgram)(0); // NOTE: We need this or else the avatar will end up with the texture of the last entity + // GLBATCH(glUseProgram)(0); // NOTE: We need this or else the avatar will end up with the texture of the last entity } void Model::segregateMeshGroups() { diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index d8d3a14390..9e66ec0938 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -55,73 +55,6 @@ void DrawSceneTask::run(const SceneContextPointer& sceneContext, const RenderCon Job::~Job() { } -template <> void render::jobRun(const DrawOpaque& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - assert(renderContext->args); - assert(renderContext->args->_viewFrustum); - - // render opaques - auto& scene = sceneContext->_scene; - auto& items = scene->getMasterBucket().at(ItemFilter::Builder::opaqueShape()); - - ItemIDs inItems; - inItems.reserve(items.size()); - for (auto id : items) { - inItems.push_back(id); - } - - ItemIDs culledItems; - cullItems(sceneContext, renderContext, inItems, culledItems); - - ItemIDs sortedItems; - depthSortItems(sceneContext, renderContext, true, culledItems, sortedItems); // Sort Front to back opaque items! - - renderItems(sceneContext, renderContext, sortedItems); -} - - -template <> void render::jobRun(const DrawTransparent& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - assert(renderContext->args); - assert(renderContext->args->_viewFrustum); - - // render transparents - auto& scene = sceneContext->_scene; - auto& items = scene->getMasterBucket().at(ItemFilter::Builder::transparentShape()); - - ItemIDs inItems; - inItems.reserve(items.size()); - for (auto id : items) { - inItems.push_back(id); - } - - ItemIDs culledItems; - cullItems(sceneContext, renderContext, inItems, culledItems); - - ItemIDs sortedItems; - depthSortItems(sceneContext, renderContext, false, culledItems, sortedItems); // Sort Back to front transparent items! - - renderItems(sceneContext, renderContext, sortedItems); -} - -template <> void render::jobRun(const DrawLight& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - assert(renderContext->args); - assert(renderContext->args->_viewFrustum); - - // render lights - auto& scene = sceneContext->_scene; - auto& items = scene->getMasterBucket().at(ItemFilter::Builder::light()); - - - ItemIDs inItems; - inItems.reserve(items.size()); - for (auto id : items) { - inItems.push_back(id); - } - - ItemIDs culledItems; - cullItems(sceneContext, renderContext, inItems, culledItems); - renderItems(sceneContext, renderContext, culledItems); -} - /* bool LODManager::shouldRenderMesh(float largestDimension, float distanceToCamera) { const float octreeToMeshRatio = 4.0f; // must be this many times closer to a mesh than a voxel to see it. @@ -263,16 +196,155 @@ void render::depthSortItems(const SceneContextPointer& sceneContext, const Rende void render::renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDs& inItems) { auto& scene = sceneContext->_scene; RenderArgs* args = renderContext->args; - gpu::Batch theBatch; - args->_batch = &theBatch; - // render for (auto id : inItems) { auto item = scene->getItem(id); item.render(args); } +} - args->_context->enqueueBatch((*args->_batch)); +void addClearStateCommands(gpu::Batch& batch) { + batch._glDepthMask(true); + batch._glDepthFunc(GL_LESS); + batch._glDisable(GL_CULL_FACE); + + batch._glActiveTexture(GL_TEXTURE0 + 1); + batch._glBindTexture(GL_TEXTURE_2D, 0); + batch._glActiveTexture(GL_TEXTURE0 + 2); + batch._glBindTexture(GL_TEXTURE_2D, 0); + batch._glActiveTexture(GL_TEXTURE0 + 3); + batch._glBindTexture(GL_TEXTURE_2D, 0); + batch._glActiveTexture(GL_TEXTURE0); + batch._glBindTexture(GL_TEXTURE_2D, 0); + + + // deactivate vertex arrays after drawing + batch._glDisableClientState(GL_NORMAL_ARRAY); + batch._glDisableClientState(GL_VERTEX_ARRAY); + batch._glDisableClientState(GL_TEXTURE_COORD_ARRAY); + batch._glDisableClientState(GL_COLOR_ARRAY); + batch._glDisableVertexAttribArray(gpu::Stream::TANGENT); + batch._glDisableVertexAttribArray(gpu::Stream::SKIN_CLUSTER_INDEX); + batch._glDisableVertexAttribArray(gpu::Stream::SKIN_CLUSTER_WEIGHT); + + // bind with 0 to switch back to normal operation + batch._glBindBuffer(GL_ARRAY_BUFFER, 0); + batch._glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + batch._glBindTexture(GL_TEXTURE_2D, 0); + + // Back to no program + batch._glUseProgram(0); +} + + +template <> void render::jobRun(const DrawOpaque& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); + + // render opaques + auto& scene = sceneContext->_scene; + auto& items = scene->getMasterBucket().at(ItemFilter::Builder::opaqueShape()); + + ItemIDs inItems; + inItems.reserve(items.size()); + for (auto id : items) { + inItems.push_back(id); + } + + ItemIDs culledItems; + cullItems(sceneContext, renderContext, inItems, culledItems); + + ItemIDs sortedItems; + depthSortItems(sceneContext, renderContext, true, culledItems, sortedItems); // Sort Front to back opaque items! + + RenderArgs* args = renderContext->args; + gpu::Batch theBatch; + args->_batch = &theBatch; + + glm::mat4 proj; + args->_viewFrustum->evalProjectionMatrix(proj); + theBatch.setProjectionTransform(proj); + + renderContext->args->_renderMode = RenderArgs::NORMAL_RENDER_MODE; + { + GLenum buffers[3]; + int bufferCount = 0; + buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; + buffers[bufferCount++] = GL_COLOR_ATTACHMENT1; + buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; + theBatch._glDrawBuffers(bufferCount, buffers); + } + + renderItems(sceneContext, renderContext, sortedItems); + + addClearStateCommands((*args->_batch)); + args->_context->render((*args->_batch)); args->_batch = nullptr; -} \ No newline at end of file +} + + +template <> void render::jobRun(const DrawTransparent& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); + + // render transparents + auto& scene = sceneContext->_scene; + auto& items = scene->getMasterBucket().at(ItemFilter::Builder::transparentShape()); + + ItemIDs inItems; + inItems.reserve(items.size()); + for (auto id : items) { + inItems.push_back(id); + } + + ItemIDs culledItems; + cullItems(sceneContext, renderContext, inItems, culledItems); + + ItemIDs sortedItems; + depthSortItems(sceneContext, renderContext, false, culledItems, sortedItems); // Sort Back to front transparent items! + + RenderArgs* args = renderContext->args; + gpu::Batch theBatch; + args->_batch = &theBatch; + + renderContext->args->_renderMode = RenderArgs::NORMAL_RENDER_MODE; + { + GLenum buffers[3]; + int bufferCount = 0; + buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; + theBatch._glDrawBuffers(bufferCount, buffers); + } + + renderItems(sceneContext, renderContext, sortedItems); + + addClearStateCommands((*args->_batch)); + args->_context->render((*args->_batch)); + args->_batch = nullptr; +} + +template <> void render::jobRun(const DrawLight& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); + + // render lights + auto& scene = sceneContext->_scene; + auto& items = scene->getMasterBucket().at(ItemFilter::Builder::light()); + + + ItemIDs inItems; + inItems.reserve(items.size()); + for (auto id : items) { + inItems.push_back(id); + } + + ItemIDs culledItems; + cullItems(sceneContext, renderContext, inItems, culledItems); + + RenderArgs* args = renderContext->args; + gpu::Batch theBatch; + args->_batch = &theBatch; + renderItems(sceneContext, renderContext, culledItems); + args->_context->render((*args->_batch)); + args->_batch = nullptr; +} From 4b46fc3ad9b84ad8d3df5192f9a4539302156f4c Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 1 Jun 2015 11:11:27 -0700 Subject: [PATCH 6/7] cleanup Model::renderPart() --- interface/src/Application.cpp | 10 +- .../src/RenderableModelEntityItem.cpp | 12 - libraries/render-utils/src/Model.cpp | 363 ++++++------------ 3 files changed, 123 insertions(+), 262 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e8e7606862..24d0a61999 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3180,12 +3180,12 @@ namespace render { if (args->_renderMode != CAMERA_MODE_MIRROR && Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { PerformanceTimer perfTimer("worldBox"); renderWorldBox(); + + // FIXME: there's currently a bug in the new render engine, if this origin dot is rendered out of view it will + // screw up the state of textures on models so they all end up rendering in the incorrect tint/color/texture + float originSphereRadius = 0.05f; + DependencyManager::get()->renderSphere(originSphereRadius, 15, 15, glm::vec4(1.0f, 0.0f, 0.0f, 1.0f)); } - - // never the less - float originSphereRadius = 0.05f; - DependencyManager::get()->renderSphere(originSphereRadius, 15, 15, glm::vec4(1.0f, 0.0f, 0.0f, 1.0f)); - } } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 6cde6f231f..462ff94f5f 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -115,12 +115,9 @@ bool RenderableModelEntityItem::readyToAddToScene(RenderArgs* renderArgs) { // TODO: this getModel() appears to be about 3% of model render time. We should optimize PerformanceTimer perfTimer("getModel"); EntityTreeRenderer* renderer = static_cast(renderArgs->_renderer); - qDebug() << "RenderableModelEntityItem::readyToAddToScene().... renderer:" << renderer; getModel(renderer); } if (renderArgs && _model && _needsInitialSimulation && _model->isActive() && _model->isLoadedWithTextures()) { - qDebug() << "RenderableModelEntityItem::readyToAddToScene().... doing initial simulation"; - _model->setScaleToFit(true, getDimensions()); _model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); _model->setRotation(getRotation()); @@ -136,18 +133,11 @@ bool RenderableModelEntityItem::readyToAddToScene(RenderArgs* renderArgs) { _model->renderSetup(renderArgs); } bool ready = !_needsInitialSimulation && _model && _model->readyToAddToScene(renderArgs); - - /* - qDebug() << "RenderableModelEntityItem::readyToAddToScene().... id:" << getEntityItemID() - << "ready:" << ready << "renderArgs:" << renderArgs - << "areMeshGroupsKnown():" << (_model ? _model->areMeshGroupsKnown() : false); - */ return ready; } bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { - qDebug() << "RenderableModelEntityItem::addToScene().... id:" << getEntityItemID(); if (_model) { return _model->addToScene(scene, pendingChanges); } @@ -156,14 +146,12 @@ bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_p void RenderableModelEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { - qDebug() << "RenderableModelEntityItem::removeFromScene().... id:" << getEntityItemID(); if (_model) { _model->removeFromScene(scene, pendingChanges); } } void RenderableModelEntityItem::render(RenderArgs* args) { - qDebug() << "RenderableModelEntityItem::render().... id:" << getEntityItemID(); PerformanceTimer perfTimer("RMEIrender"); assert(getType() == EntityTypes::Model); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 894e929897..cb6421329f 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -783,7 +783,6 @@ namespace render { } template <> const Item::Bound payloadGetBound(const TransparentMeshPart::Pointer& payload) { - //qDebug() << "payloadGetBound(TransparentMeshPart) url:" << payload->model->getURL(); if (payload) { //return payload->model->getPartBounds(payload->meshIndex, payload->partIndex); } @@ -791,7 +790,6 @@ namespace render { } template <> void payloadRender(const TransparentMeshPart::Pointer& payload, RenderArgs* args) { if (args) { - // qDebug() << "payloadRender(TransparentMeshPart) url:" << payload->model->getURL(); args->_elementsTouched++; return payload->model->renderPart(args, payload->meshIndex, payload->partIndex, true); } @@ -815,7 +813,6 @@ namespace render { } template <> const Item::Bound payloadGetBound(const OpaqueMeshPart::Pointer& payload) { - // qDebug() << "payloadGetBound(OpaqueMeshPart) url:" << payload->model->getURL(); if (payload) { //return payload->model->getPartBounds(payload->meshIndex, payload->partIndex); } @@ -823,7 +820,6 @@ namespace render { } template <> void payloadRender(const OpaqueMeshPart::Pointer& payload, RenderArgs* args) { if (args) { - // qDebug() << "payloadRender(OpaqueMeshPart) url:" << payload->model->getURL(); args->_elementsTouched++; return payload->model->renderPart(args, payload->meshIndex, payload->partIndex, false); } @@ -832,7 +828,6 @@ namespace render { bool Model::addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges) { - qDebug() << "Model::addToScene() url:" << getURL(); bool somethingAdded = false; // allow the attachments to add to scene foreach (Model* attachment, _attachments) { @@ -846,7 +841,6 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan auto renderPayload = render::PayloadPointer(new TransparentMeshPart::Payload(renderData)); pendingChanges.resetItem(item, renderPayload); _renderItems << item; - qDebug() << "Model::addToScene() added transparent item:" << item << "url:" << getURL(); somethingAdded = true; } foreach (auto renderItem, _opaqueRenderItems) { @@ -855,7 +849,6 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan auto renderPayload = render::PayloadPointer(new OpaqueMeshPart::Payload(renderData)); pendingChanges.resetItem(item, renderPayload); _renderItems << item; - qDebug() << "Model::addToScene() added opaque item:" << item << "url:" << getURL(); somethingAdded = true; } @@ -863,7 +856,6 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan } void Model::removeFromScene(std::shared_ptr scene, render::PendingChanges& pendingChanges) { - qDebug() << "Model::removeFromScene() url:" << getURL(); // allow the attachments to remove to scene foreach (Model* attachment, _attachments) { attachment->removeFromScene(scene, pendingChanges); @@ -2188,37 +2180,20 @@ AABox Model::getPartBounds(int meshIndex, int partIndex) { AABox partBox = mesh._mesh.evalPartBound(partIndex); // FIX ME! - // TODO: needs to translate to world space, these values are in model space + // 1) needs to translate to world space, these values are in model space + // 2) mesh._mesh.parts doesn't always have the correct values in it... so we + // need to just use mesh.parts or find/fix whatever is causing mesh._mesh + // to not contain data return partBox; } void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool translucent) { - //renderCore(args, 1.0f); - //return; -//qDebug() << "Model::renderPart()... meshIndex:" << meshIndex << "partIndex:" << partIndex << "url:" << _url; renderSetup(args); auto textureCache = DependencyManager::get(); - - int i = meshIndex; - int j = partIndex; gpu::Batch& batch = *(args->_batch); auto mode = args->_renderMode; - // Setup the projection matrix - /* - if (args && args->_viewFrustum) { - glm::mat4 proj; - // If for easier debug depending on the pass - if (mode == RenderArgs::SHADOW_RENDER_MODE) { - args->_viewFrustum->evalProjectionMatrix(proj); - } else { - args->_viewFrustum->evalProjectionMatrix(proj); - } - batch.setProjectionTransform(proj); - } - */ - // Capture the view matrix once for the rendering of this model if (_transforms.empty()) { _transforms.push_back(Transform()); @@ -2232,23 +2207,6 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran batch.setViewTransform(_transforms[0]); - // FIXME: Do I need this? it doesn't seem to do anything. - /* { - GLenum buffers[3]; - int bufferCount = 0; - - if (mode != RenderArgs::SHADOW_RENDER_MODE) { - buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; - } - if (mode != RenderArgs::SHADOW_RENDER_MODE) { - buffers[bufferCount++] = GL_COLOR_ATTACHMENT1; - } - if (mode != RenderArgs::SHADOW_RENDER_MODE) { - buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; - } - GLBATCH(glDrawBuffers)(bufferCount, buffers); - }*/ - const float DEFAULT_ALPHA_THRESHOLD = 0.5f; // auto alphaThreshold = DEFAULT_ALPHA_THRESHOLD; // FIX ME const FBXGeometry& geometry = _geometry->getFBXGeometry(); @@ -2258,9 +2216,6 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran const FBXMesh& mesh = geometry.meshes.at(meshIndex); const MeshState& state = _meshStates.at(meshIndex); - int vertexCount = mesh.vertices.size(); // NOTE: This seems wrong, shouldn't it be the part's vertex count? - - bool translucentMesh = networkMesh.getTranslucentPartCount(mesh) == networkMesh.parts.size(); bool hasTangents = !mesh.tangents.isEmpty(); bool hasSpecular = mesh.hasSpecularTexture(); @@ -2277,226 +2232,147 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran args, locations); - QString lastMaterialID; int meshPartsRendered = 0; updateVisibleJointStates(); - // i is the "index" from the original networkMeshes QVector... - { + // if our index is ever out of range for either meshes or networkMeshes, then skip it, and set our _meshGroupsKnown + // to false to rebuild out mesh groups. - // if our index is ever out of range for either meshes or networkMeshes, then skip it, and set our _meshGroupsKnown - // to false to rebuild out mesh groups. - - if (i < 0 || i >= networkMeshes.size() || i > geometry.meshes.size()) { - _meshGroupsKnown = false; // regenerate these lists next time around. - // qDebug() << "if (i < 0 || i >= networkMeshes.size() || i > geometry.meshes.size()) {.... BAIL!!!"; - return; // FIXME! - } - - // exit early if the translucency doesn't match what we're drawing - const NetworkMesh& networkMesh = networkMeshes.at(i); - const FBXMesh& mesh = geometry.meshes.at(i); + if (meshIndex < 0 || meshIndex >= networkMeshes.size() || meshIndex > geometry.meshes.size()) { + _meshGroupsKnown = false; // regenerate these lists next time around. + return; // FIXME! + } + + batch.setIndexBuffer(gpu::UINT32, (networkMesh._indexBuffer), 0); + int vertexCount = mesh.vertices.size(); + if (vertexCount == 0) { + // sanity check + return; // FIXME! + } + + if (state.clusterMatrices.size() > 1) { + GLBATCH(glUniformMatrix4fv)(locations->clusterMatrices, state.clusterMatrices.size(), false, + (const float*)state.clusterMatrices.constData()); + batch.setModelTransform(Transform()); + } else { + batch.setModelTransform(Transform(state.clusterMatrices[0])); + } - batch.setIndexBuffer(gpu::UINT32, (networkMesh._indexBuffer), 0); - int vertexCount = mesh.vertices.size(); - if (vertexCount == 0) { - // sanity check - // qDebug() << "if (vertexCount == 0) {.... BAIL!!!"; - return; // FIXME! - } - - const MeshState& state = _meshStates.at(i); - if (state.clusterMatrices.size() > 1) { - GLBATCH(glUniformMatrix4fv)(locations->clusterMatrices, state.clusterMatrices.size(), false, - (const float*)state.clusterMatrices.constData()); - batch.setModelTransform(Transform()); - } else { - batch.setModelTransform(Transform(state.clusterMatrices[0])); - } + if (mesh.blendshapes.isEmpty()) { + batch.setInputFormat(networkMesh._vertexFormat); + batch.setInputStream(0, *networkMesh._vertexStream); + } else { + batch.setInputFormat(networkMesh._vertexFormat); + batch.setInputBuffer(0, _blendedVertexBuffers[meshIndex], 0, sizeof(glm::vec3)); + batch.setInputBuffer(1, _blendedVertexBuffers[meshIndex], vertexCount * sizeof(glm::vec3), sizeof(glm::vec3)); + batch.setInputStream(2, *networkMesh._vertexStream); + } - if (mesh.blendshapes.isEmpty()) { - batch.setInputFormat(networkMesh._vertexFormat); - batch.setInputStream(0, *networkMesh._vertexStream); - } else { - batch.setInputFormat(networkMesh._vertexFormat); - batch.setInputBuffer(0, _blendedVertexBuffers[i], 0, sizeof(glm::vec3)); - batch.setInputBuffer(1, _blendedVertexBuffers[i], vertexCount * sizeof(glm::vec3), sizeof(glm::vec3)); - batch.setInputStream(2, *networkMesh._vertexStream); - } + if (mesh.colors.isEmpty()) { + GLBATCH(glColor4f)(1.0f, 1.0f, 1.0f, 1.0f); + } - if (mesh.colors.isEmpty()) { - // qDebug() << " colors empty ... meshIndex:" << meshIndex << "partIndex:" << partIndex << "url:" << _url; - GLBATCH(glColor4f)(1.0f, 1.0f, 1.0f, 1.0f); - } else { - // qDebug() << " colors size:" << mesh.colors.size() << " ... meshIndex:" << meshIndex << "partIndex:" << partIndex << "url:" << _url; - } + qint64 offset = 0; - qint64 offset = 0; - { // j - const NetworkMeshPart& networkPart = networkMesh.parts.at(j); - const FBXMeshPart& part = mesh.parts.at(j); - model::MaterialPointer material = part._material; - - if (material != nullptr) { - /* - if ((networkPart.isTranslucent() || part.opacity != 1.0f) != translucent) { - offset += (part.quadIndices.size() + part.triangleIndices.size()) * sizeof(int); - return; // FIXME! + const NetworkMeshPart& networkPart = networkMesh.parts.at(partIndex); + const FBXMeshPart& part = mesh.parts.at(partIndex); + model::MaterialPointer material = part._material; + + if (material == nullptr) { + qCDebug(renderutils) << "WARNING: material == nullptr!!!"; + } + + if (material != nullptr) { + + // apply material properties + if (mode != RenderArgs::SHADOW_RENDER_MODE) { + #ifdef WANT_DEBUG + qCDebug(renderutils) << "Material Changed ---------------------------------------------"; + qCDebug(renderutils) << "part INDEX:" << partIndex; + qCDebug(renderutils) << "NEW part.materialID:" << part.materialID; + #endif //def WANT_DEBUG + + if (locations->materialBufferUnit >= 0) { + batch.setUniformBuffer(locations->materialBufferUnit, material->getSchemaBuffer()); } - */ - // apply material properties - if (mode == RenderArgs::SHADOW_RENDER_MODE) { - /// GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); - - } else { - if (true) { //lastMaterialID != part.materialID) { - const bool wantDebug = false; - if (wantDebug) { - qCDebug(renderutils) << "Material Changed ---------------------------------------------"; - qCDebug(renderutils) << "part INDEX:" << j; - qCDebug(renderutils) << "NEW part.materialID:" << part.materialID; - } + Texture* diffuseMap = networkPart.diffuseTexture.data(); + if (mesh.isEye && diffuseMap) { + diffuseMap = (_dilatedTextures[meshIndex][partIndex] = + static_cast(diffuseMap)->getDilatedTexture(_pupilDilation)).data(); + } + static bool showDiffuse = true; + if (showDiffuse && diffuseMap) { + batch.setUniformTexture(0, diffuseMap->getGPUTexture()); + + } else { + batch.setUniformTexture(0, textureCache->getWhiteTexture()); + } - if (locations->materialBufferUnit >= 0) { - batch.setUniformBuffer(locations->materialBufferUnit, material->getSchemaBuffer()); - } - - Texture* diffuseMap = networkPart.diffuseTexture.data(); - if (mesh.isEye && diffuseMap) { - diffuseMap = (_dilatedTextures[i][j] = - static_cast(diffuseMap)->getDilatedTexture(_pupilDilation)).data(); - } - static bool showDiffuse = true; - if (showDiffuse && diffuseMap) { - // qCDebug(renderutils) << " batch.setUniformTexture(0, diffuseMap->getGPUTexture());"; - batch.setUniformTexture(0, diffuseMap->getGPUTexture()); - - } else { - // qCDebug(renderutils) << " batch.setUniformTexture(0, textureCache->getWhiteTexture());"; - batch.setUniformTexture(0, textureCache->getWhiteTexture()); - } - - if (locations->texcoordMatrices >= 0) { - glm::mat4 texcoordTransform[2]; - if (!part.diffuseTexture.transform.isIdentity()) { - // qCDebug(renderutils) << " part.diffuseTexture.transform.getMatrix(texcoordTransform[0]);"; - part.diffuseTexture.transform.getMatrix(texcoordTransform[0]); - } - if (!part.emissiveTexture.transform.isIdentity()) { - // qCDebug(renderutils) << " part.emissiveTexture.transform.getMatrix(texcoordTransform[1]);"; - part.emissiveTexture.transform.getMatrix(texcoordTransform[1]); - } - // qCDebug(renderutils) << " GLBATCH(glUniformMatrix4fv)(locations->texcoordMatrices, 2, false, (const float*) &texcoordTransform);"; - GLBATCH(glUniformMatrix4fv)(locations->texcoordMatrices, 2, false, (const float*) &texcoordTransform); - } - - if (!mesh.tangents.isEmpty()) { - Texture* normalMap = networkPart.normalTexture.data(); - // qCDebug(renderutils) << " batch.setUniformTexture(1, !normalMap ? textureCache->getBlueTexture() : normalMap->getGPUTexture());"; - batch.setUniformTexture(1, !normalMap ? - textureCache->getBlueTexture() : normalMap->getGPUTexture()); - - } - - if (locations->specularTextureUnit >= 0) { - Texture* specularMap = networkPart.specularTexture.data(); - // qCDebug(renderutils) << " batch.setUniformTexture(locations->specularTextureUnit, !specularMap ? textureCache->getWhiteTexture() : specularMap->getGPUTexture());"; - batch.setUniformTexture(locations->specularTextureUnit, !specularMap ? - textureCache->getWhiteTexture() : specularMap->getGPUTexture()); - } - - if (args) { - args->_materialSwitches++; - } - - } - - // HACK: For unkwon reason (yet!) this code that should be assigned only if the material changes need to be called for every - // drawcall with an emissive, so let's do it for now. - if (locations->emissiveTextureUnit >= 0) { - // assert(locations->emissiveParams >= 0); // we should have the emissiveParams defined in the shader - float emissiveOffset = part.emissiveParams.x; - float emissiveScale = part.emissiveParams.y; - GLBATCH(glUniform2f)(locations->emissiveParams, emissiveOffset, emissiveScale); - - Texture* emissiveMap = networkPart.emissiveTexture.data(); - // qCDebug(renderutils) << " batch.setUniformTexture(locations->emissiveTextureUnit, !emissiveMap ? textureCache->getWhiteTexture() : emissiveMap->getGPUTexture());"; - batch.setUniformTexture(locations->emissiveTextureUnit, !emissiveMap ? - textureCache->getWhiteTexture() : emissiveMap->getGPUTexture()); - } + if (locations->texcoordMatrices >= 0) { + glm::mat4 texcoordTransform[2]; + if (!part.diffuseTexture.transform.isIdentity()) { + part.diffuseTexture.transform.getMatrix(texcoordTransform[0]); } - - - lastMaterialID = part.materialID; - } - - meshPartsRendered++; - - if (part.quadIndices.size() > 0) { - // qDebug() << "batch.drawIndexed(gpu::QUADS) size:" << part.quadIndices.size(); - batch.drawIndexed(gpu::QUADS, part.quadIndices.size(), offset); - offset += part.quadIndices.size() * sizeof(int); + if (!part.emissiveTexture.transform.isIdentity()) { + part.emissiveTexture.transform.getMatrix(texcoordTransform[1]); + } + GLBATCH(glUniformMatrix4fv)(locations->texcoordMatrices, 2, false, (const float*) &texcoordTransform); } - if (part.triangleIndices.size() > 0) { - // qDebug() << "batch.drawIndexed(gpu::TRIANGLES) size:" << part.triangleIndices.size(); - batch.drawIndexed(gpu::TRIANGLES, part.triangleIndices.size(), offset); - offset += part.triangleIndices.size() * sizeof(int); + if (!mesh.tangents.isEmpty()) { + Texture* normalMap = networkPart.normalTexture.data(); + batch.setUniformTexture(1, !normalMap ? + textureCache->getBlueTexture() : normalMap->getGPUTexture()); + + } + + if (locations->specularTextureUnit >= 0) { + Texture* specularMap = networkPart.specularTexture.data(); + batch.setUniformTexture(locations->specularTextureUnit, !specularMap ? + textureCache->getWhiteTexture() : specularMap->getGPUTexture()); } if (args) { - const int INDICES_PER_TRIANGLE = 3; - const int INDICES_PER_QUAD = 4; - args->_trianglesRendered += part.triangleIndices.size() / INDICES_PER_TRIANGLE; - args->_quadsRendered += part.quadIndices.size() / INDICES_PER_QUAD; + args->_materialSwitches++; + } + + // HACK: For unknown reason (yet!) this code that should be assigned only if the material changes need to be called for every + // drawcall with an emissive, so let's do it for now. + if (locations->emissiveTextureUnit >= 0) { + // assert(locations->emissiveParams >= 0); // we should have the emissiveParams defined in the shader + float emissiveOffset = part.emissiveParams.x; + float emissiveScale = part.emissiveParams.y; + GLBATCH(glUniform2f)(locations->emissiveParams, emissiveOffset, emissiveScale); + + Texture* emissiveMap = networkPart.emissiveTexture.data(); + batch.setUniformTexture(locations->emissiveTextureUnit, !emissiveMap ? + textureCache->getWhiteTexture() : emissiveMap->getGPUTexture()); } } } + meshPartsRendered++; - // NOTE: these don't seem to do anything - /* - GLBATCH(glDepthMask)(true); - GLBATCH(glDepthFunc)(GL_LESS); - GLBATCH(glDisable)(GL_CULL_FACE); - - if (mode == RenderArgs::SHADOW_RENDER_MODE) { - GLBATCH(glCullFace)(GL_BACK); + if (part.quadIndices.size() > 0) { + batch.drawIndexed(gpu::QUADS, part.quadIndices.size(), offset); + offset += part.quadIndices.size() * sizeof(int); } - GLBATCH(glActiveTexture)(GL_TEXTURE0 + 1); - GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); - GLBATCH(glActiveTexture)(GL_TEXTURE0 + 2); - GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); - GLBATCH(glActiveTexture)(GL_TEXTURE0 + 3); - GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); - GLBATCH(glActiveTexture)(GL_TEXTURE0); - GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); - - // deactivate vertex arrays after drawing - GLBATCH(glDisableClientState)(GL_NORMAL_ARRAY); - GLBATCH(glDisableClientState)(GL_VERTEX_ARRAY); - GLBATCH(glDisableClientState)(GL_TEXTURE_COORD_ARRAY); - GLBATCH(glDisableClientState)(GL_COLOR_ARRAY); - GLBATCH(glDisableVertexAttribArray)(gpu::Stream::TANGENT); - GLBATCH(glDisableVertexAttribArray)(gpu::Stream::SKIN_CLUSTER_INDEX); - GLBATCH(glDisableVertexAttribArray)(gpu::Stream::SKIN_CLUSTER_WEIGHT); - - // bind with 0 to switch back to normal operation - GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, 0); - GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, 0); - GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); - */ - - // Back to no program - // GLBATCH(glUseProgram)(0); // NOTE: We need this or else the avatar will end up with the texture of the last entity + if (part.triangleIndices.size() > 0) { + batch.drawIndexed(gpu::TRIANGLES, part.triangleIndices.size(), offset); + offset += part.triangleIndices.size() * sizeof(int); + } + + if (args) { + const int INDICES_PER_TRIANGLE = 3; + const int INDICES_PER_QUAD = 4; + args->_trianglesRendered += part.triangleIndices.size() / INDICES_PER_TRIANGLE; + args->_quadsRendered += part.quadIndices.size() / INDICES_PER_QUAD; + } } void Model::segregateMeshGroups() { - - //qDebug() << "Model::segregateMeshGroups() ------------------------------------------------"; - _renderBuckets.clear(); const FBXGeometry& geometry = _geometry->getFBXGeometry(); @@ -2528,15 +2404,12 @@ void Model::segregateMeshGroups() { } // Debug... - qDebug() << "Mesh parts... for " << _url << " count:" << mesh.parts.size(); int totalParts = mesh.parts.size(); for (int partIndex = 0; partIndex < totalParts; partIndex++) { // this is a good place to create our renderPayloads if (translucentMesh) { - qDebug() << "Transparent Mesh parts[" << partIndex << "]"; _transparentRenderItems << std::shared_ptr(new TransparentMeshPart(this, i, partIndex)); } else { - qDebug() << "Opaque Mesh parts[" << partIndex << "]"; _opaqueRenderItems << std::shared_ptr(new OpaqueMeshPart(this, i, partIndex)); } } From ea31fdcc26a63ebf09d685c03af209110ade3cc4 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 1 Jun 2015 11:53:40 -0700 Subject: [PATCH 7/7] hacking on transparency --- libraries/render-utils/src/Model.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index cb6421329f..f17ad64ed4 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -791,6 +791,7 @@ namespace render { template <> void payloadRender(const TransparentMeshPart::Pointer& payload, RenderArgs* args) { if (args) { args->_elementsTouched++; + //qDebug() << "would be TransparentMeshPart: " << payload->meshIndex << "," << payload->partIndex; return payload->model->renderPart(args, payload->meshIndex, payload->partIndex, true); } } @@ -2189,6 +2190,13 @@ AABox Model::getPartBounds(int meshIndex, int partIndex) { void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool translucent) { renderSetup(args); + + /* + if (translucent) { + renderCore(args, 1.0f); + return; + } + */ auto textureCache = DependencyManager::get(); gpu::Batch& batch = *(args->_batch); @@ -2207,8 +2215,9 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran batch.setViewTransform(_transforms[0]); - const float DEFAULT_ALPHA_THRESHOLD = 0.5f; // - auto alphaThreshold = DEFAULT_ALPHA_THRESHOLD; // FIX ME + const float OPAQUE_ALPHA_THRESHOLD = 0.5f; + const float TRANSPARENT_ALPHA_THRESHOLD = 0.0f; + auto alphaThreshold = translucent ? TRANSPARENT_ALPHA_THRESHOLD : OPAQUE_ALPHA_THRESHOLD; // FIX ME const FBXGeometry& geometry = _geometry->getFBXGeometry(); const QVector& networkMeshes = _geometry->getMeshes(); @@ -2216,7 +2225,7 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran const FBXMesh& mesh = geometry.meshes.at(meshIndex); const MeshState& state = _meshStates.at(meshIndex); - bool translucentMesh = networkMesh.getTranslucentPartCount(mesh) == networkMesh.parts.size(); + bool translucentMesh = translucent; // networkMesh.getTranslucentPartCount(mesh) == networkMesh.parts.size(); bool hasTangents = !mesh.tangents.isEmpty(); bool hasSpecular = mesh.hasSpecularTexture(); bool hasLightmap = mesh.hasEmissiveTexture();