diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index f8f0f7904a..65e193dec6 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -290,7 +290,6 @@ void Agent::executeScript() { packetReceiver.registerListener(PacketType::BulkAvatarData, avatarHashMap.data(), "processAvatarDataPacket"); packetReceiver.registerListener(PacketType::KillAvatar, avatarHashMap.data(), "processKillAvatar"); packetReceiver.registerListener(PacketType::AvatarIdentity, avatarHashMap.data(), "processAvatarIdentityPacket"); - packetReceiver.registerListener(PacketType::AvatarBillboard, avatarHashMap.data(), "processAvatarBillboardPacket"); // register ourselves to the script engine _scriptEngine->registerGlobalObject("Agent", this); @@ -341,15 +340,12 @@ void Agent::setIsAvatar(bool isAvatar) { if (_isAvatar && !_avatarIdentityTimer) { // set up the avatar timers _avatarIdentityTimer = new QTimer(this); - _avatarBillboardTimer = new QTimer(this); // connect our slot connect(_avatarIdentityTimer, &QTimer::timeout, this, &Agent::sendAvatarIdentityPacket); - connect(_avatarBillboardTimer, &QTimer::timeout, this, &Agent::sendAvatarBillboardPacket); // start the timers _avatarIdentityTimer->start(AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS); - _avatarBillboardTimer->start(AVATAR_BILLBOARD_PACKET_SEND_INTERVAL_MSECS); } if (!_isAvatar) { @@ -359,12 +355,6 @@ void Agent::setIsAvatar(bool isAvatar) { delete _avatarIdentityTimer; _avatarIdentityTimer = nullptr; } - - if (_avatarBillboardTimer) { - _avatarBillboardTimer->stop(); - delete _avatarBillboardTimer; - _avatarBillboardTimer = nullptr; - } } } @@ -375,14 +365,6 @@ void Agent::sendAvatarIdentityPacket() { } } -void Agent::sendAvatarBillboardPacket() { - if (_isAvatar) { - auto scriptedAvatar = DependencyManager::get(); - scriptedAvatar->sendBillboardPacket(); - } -} - - void Agent::processAgentAvatarAndAudio(float deltaTime) { if (!_scriptEngine->isFinished() && _isAvatar) { auto scriptedAvatar = DependencyManager::get(); @@ -491,7 +473,7 @@ void Agent::processAgentAvatarAndAudio(float deltaTime) { } void Agent::aboutToFinish() { - setIsAvatar(false);// will stop timers for sending billboards and identity packets + setIsAvatar(false);// will stop timers for sending identity packets if (_scriptEngine) { _scriptEngine->stop(); diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h index 2b0d22385d..63d4cfa4d6 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -82,7 +82,6 @@ private: void setAvatarSound(SharedSoundPointer avatarSound) { _avatarSound = avatarSound; } void sendAvatarIdentityPacket(); - void sendAvatarBillboardPacket(); QString _scriptContents; QTimer* _scriptRequestTimeout { nullptr }; @@ -92,7 +91,6 @@ private: int _numAvatarSoundSentBytes = 0; bool _isAvatar = false; QTimer* _avatarIdentityTimer = nullptr; - QTimer* _avatarBillboardTimer = nullptr; QHash _outgoingScriptAudioSequenceNumbers; }; diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 36a12e7b6a..10694eb5d4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -864,10 +864,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : if (action == controller::toInt(controller::Action::RETICLE_CLICK)) { auto reticlePos = getApplicationCompositor().getReticlePosition(); - QPoint globalPos(reticlePos.x, reticlePos.y); - - // FIXME - it would be nice if this was self contained in the _compositor or Reticle class - auto localPos = isHMDMode() ? globalPos : _glWidget->mapFromGlobal(globalPos); + QPoint localPos(reticlePos.x, reticlePos.y); // both hmd and desktop already handle this in our coordinates. if (state) { QMouseEvent mousePress(QEvent::MouseButtonPress, localPos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); sendEvent(_glWidget, &mousePress); @@ -888,15 +885,15 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : } else if (action == controller::toInt(controller::Action::UI_NAV_SELECT)) { if (!offscreenUi->navigationFocused()) { auto reticlePosition = getApplicationCompositor().getReticlePosition(); - offscreenUi->toggleMenu(_glWidget->mapFromGlobal(QPoint(reticlePosition.x, reticlePosition.y))); + offscreenUi->toggleMenu(QPoint(reticlePosition.x, reticlePosition.y)); } } else if (action == controller::toInt(controller::Action::CONTEXT_MENU)) { auto reticlePosition = getApplicationCompositor().getReticlePosition(); - offscreenUi->toggleMenu(_glWidget->mapFromGlobal(QPoint(reticlePosition.x, reticlePosition.y))); + offscreenUi->toggleMenu(QPoint(reticlePosition.x, reticlePosition.y)); } else if (action == controller::toInt(controller::Action::UI_NAV_SELECT)) { if (!offscreenUi->navigationFocused()) { auto reticlePosition = getApplicationCompositor().getReticlePosition(); - offscreenUi->toggleMenu(_glWidget->mapFromGlobal(QPoint(reticlePosition.x, reticlePosition.y))); + offscreenUi->toggleMenu(QPoint(reticlePosition.x, reticlePosition.y)); } } else if (action == controller::toInt(controller::Action::RETICLE_X)) { auto oldPos = getApplicationCompositor().getReticlePosition(); @@ -1071,6 +1068,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : // in the queue, which can be pretty damn frequent. Hence the idle function has a bunch // of logic to abort early if it's being called too often. _idleTimer->start(0); + + // After all of the constructor is completed, then set firstRun to false. + Setting::Handle firstRun{ Settings::firstRun, true }; + firstRun.set(false); } @@ -1088,11 +1089,6 @@ void Application::checkChangeCursor() { _cursorNeedsChanging = false; } - - - // After all of the constructor is completed, then set firstRun to false. - Setting::Handle firstRun{ Settings::firstRun, true }; - firstRun.set(false); } void Application::showCursor(const QCursor& cursor) { @@ -1160,10 +1156,16 @@ void Application::cleanupBeforeQuit() { getEntities()->shutdown(); // tell the entities system we're shutting down, so it will stop running scripts + // Clear any queued processing (I/O, FBX/OBJ/Texture parsing) + QThreadPool::globalInstance()->clear(); + DependencyManager::get()->saveScripts(); DependencyManager::get()->shutdownScripting(); // stop all currently running global scripts DependencyManager::destroy(); + // Cleanup all overlays after the scripts, as scripts might add more + _overlays.cleanupAllOverlays(); + // first stop all timers directly or by invokeMethod // depending on what thread they run in locationUpdateTimer.stop(); @@ -2269,7 +2271,7 @@ void Application::keyReleaseEvent(QKeyEvent* event) { if (event->key() == Qt::Key_Alt && _altPressed && hasFocus()) { auto offscreenUi = DependencyManager::get(); auto reticlePosition = getApplicationCompositor().getReticlePosition(); - offscreenUi->toggleMenu(_glWidget->mapFromGlobal(QPoint(reticlePosition.x, reticlePosition.y))); + offscreenUi->toggleMenu(QPoint(reticlePosition.x, reticlePosition.y)); } _keysPressed.remove(event->key()); @@ -2738,15 +2740,7 @@ void Application::setLowVelocityFilter(bool lowVelocityFilter) { } ivec2 Application::getMouse() const { - auto reticlePosition = getApplicationCompositor().getReticlePosition(); - - // in the HMD, the reticlePosition is the mouse position - if (isHMDMode()) { - return reticlePosition; - } - - // in desktop mode, we need to map from global to widget space - return toGlm(_glWidget->mapFromGlobal(QPoint(reticlePosition.x, reticlePosition.y))); + return getApplicationCompositor().getReticlePosition(); } FaceTracker* Application::getActiveFaceTracker() { diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 41bcc0332a..ddadcb3909 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -73,7 +73,6 @@ AvatarManager::AvatarManager(QObject* parent) : packetReceiver.registerListener(PacketType::BulkAvatarData, this, "processAvatarDataPacket"); packetReceiver.registerListener(PacketType::KillAvatar, this, "processKillAvatar"); packetReceiver.registerListener(PacketType::AvatarIdentity, this, "processAvatarIdentityPacket"); - packetReceiver.registerListener(PacketType::AvatarBillboard, this, "processAvatarBillboardPacket"); } AvatarManager::~AvatarManager() { diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 871943fec8..e1f1b7bca8 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -686,7 +686,11 @@ void MyAvatar::saveData() { settings.setValue("leanScale", _leanScale); settings.setValue("scale", _targetScale); - settings.setValue("fullAvatarURL", _fullAvatarURLFromPreferences); + settings.setValue("fullAvatarURL", + _fullAvatarURLFromPreferences == AvatarData::defaultFullAvatarModelUrl() ? + "" : + _fullAvatarURLFromPreferences.toString()); + settings.setValue("fullAvatarModelName", _fullAvatarModelName); settings.setValue("animGraphURL", _animGraphUrl); diff --git a/interface/src/ui/overlays/Image3DOverlay.cpp b/interface/src/ui/overlays/Image3DOverlay.cpp index fe2fc5ddcd..fd0d2bcedf 100644 --- a/interface/src/ui/overlays/Image3DOverlay.cpp +++ b/interface/src/ui/overlays/Image3DOverlay.cpp @@ -104,7 +104,7 @@ void Image3DOverlay::render(RenderArgs* args) { const render::ShapeKey Image3DOverlay::getShapeKey() { auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias(); if (_emissive) { - builder.withEmissive(); + builder.withUnlit(); } if (getAlpha() != 1.0f) { builder.withTranslucent(); diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 1179fbaa50..9ff7f6268f 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -36,15 +36,8 @@ #include -Overlays::Overlays() : _nextOverlayID(1) { - connect(qApp, &Application::beforeAboutToQuit, [=] { - cleanupAllOverlays(); - }); -} - -Overlays::~Overlays() { -} - +Overlays::Overlays() : + _nextOverlayID(1) {} void Overlays::cleanupAllOverlays() { { diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 25ba00fdf0..f47f8de153 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -62,7 +62,6 @@ class Overlays : public QObject { public: Overlays(); - ~Overlays(); void init(); void update(float deltatime); @@ -73,6 +72,8 @@ public: Overlay::Pointer getOverlay(unsigned int id) const; OverlayPanel::Pointer getPanel(unsigned int id) const { return _panels[id]; } + void cleanupAllOverlays(); + public slots: /// adds an overlay with the specific properties unsigned int addOverlay(const QString& type, const QVariant& properties); @@ -145,7 +146,6 @@ signals: private: void cleanupOverlaysToDelete(); - void cleanupAllOverlays(); QMap _overlaysHUD; QMap _overlaysWorld; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index fd13f8c370..9c556dc42b 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -58,7 +58,6 @@ AvatarData::AvatarData() : _headData(NULL), _displayNameTargetAlpha(1.0f), _displayNameAlpha(1.0f), - _billboard(), _errorLogExpiry(0), _owningAvatarMixer(), _targetVelocity(0.0f), @@ -990,7 +989,7 @@ QByteArray AvatarData::identityByteArray() { QByteArray identityData; QDataStream identityStream(&identityData, QIODevice::Append); QUrl emptyURL(""); - const QUrl& urlToSend = (_skeletonModelURL == AvatarData::defaultFullAvatarModelUrl()) ? emptyURL : _skeletonModelURL; + const QUrl& urlToSend = _skeletonModelURL.scheme() == "file" ? emptyURL : _skeletonModelURL; QUrl unusedModelURL; // legacy faceModel support @@ -999,13 +998,6 @@ QByteArray AvatarData::identityByteArray() { return identityData; } -bool AvatarData::hasBillboardChangedAfterParsing(const QByteArray& data) { - if (data == _billboard) { - return false; - } - _billboard = data; - return true; -} void AvatarData::setSkeletonModelURL(const QUrl& skeletonModelURL) { const QUrl& expanded = skeletonModelURL.isEmpty() ? AvatarData::defaultFullAvatarModelUrl() : skeletonModelURL; @@ -1103,33 +1095,6 @@ void AvatarData::detachAll(const QString& modelURL, const QString& jointName) { setAttachmentData(attachmentData); } -void AvatarData::setBillboard(const QByteArray& billboard) { - _billboard = billboard; - - qCDebug(avatars) << "Changing billboard for avatar."; -} - -void AvatarData::setBillboardFromURL(const QString &billboardURL) { - _billboardURL = billboardURL; - - - qCDebug(avatars) << "Changing billboard for avatar to PNG at" << qPrintable(billboardURL); - - QNetworkRequest billboardRequest; - billboardRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); - billboardRequest.setUrl(QUrl(billboardURL)); - - QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); - QNetworkReply* networkReply = networkAccessManager.get(billboardRequest); - connect(networkReply, SIGNAL(finished()), this, SLOT(setBillboardFromNetworkReply())); -} - -void AvatarData::setBillboardFromNetworkReply() { - QNetworkReply* networkReply = static_cast(sender()); - setBillboard(networkReply->readAll()); - networkReply->deleteLater(); -} - void AvatarData::setJointMappingsFromNetworkReply() { QNetworkReply* networkReply = static_cast(sender()); @@ -1204,21 +1169,6 @@ void AvatarData::sendIdentityPacket() { }); } -void AvatarData::sendBillboardPacket() { - if (!_billboard.isEmpty()) { - auto nodeList = DependencyManager::get(); - - // This makes sure the billboard won't be too large to send. - // Once more protocol changes are done and we can send blocks of data we can support sending > MTU sized billboards. - if (_billboard.size() <= NLPacket::maxPayloadSize(PacketType::AvatarBillboard)) { - auto billboardPacket = NLPacket::create(PacketType::AvatarBillboard, _billboard.size()); - billboardPacket->write(_billboard); - - nodeList->broadcastToNodes(std::move(billboardPacket), NodeSet() << NodeType::AvatarMixer); - } - } -} - void AvatarData::updateJointMappings() { _jointIndices.clear(); _jointNames.clear(); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 900da38ffa..a7b97ef4c0 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -107,7 +107,6 @@ static const float MIN_AVATAR_SCALE = .005f; const float MAX_AUDIO_LOUDNESS = 1000.0f; // close enough for mouth animation const int AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS = 1000; -const int AVATAR_BILLBOARD_PACKET_SEND_INTERVAL_MSECS = 5000; // See also static AvatarData::defaultFullAvatarModelUrl(). const QString DEFAULT_FULL_AVATAR_MODEL_NAME = QString("Default"); @@ -160,7 +159,6 @@ class AvatarData : public QObject, public SpatiallyNestable { Q_PROPERTY(QString displayName READ getDisplayName WRITE setDisplayName) Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript WRITE setSkeletonModelURLFromScript) Q_PROPERTY(QVector attachmentData READ getAttachmentData WRITE setAttachmentData) - Q_PROPERTY(QString billboardURL READ getBillboardURL WRITE setBillboardFromURL) Q_PROPERTY(QStringList jointNames READ getJointNames) @@ -285,8 +283,6 @@ public: bool hasIdentityChangedAfterParsing(const QByteArray& data); QByteArray identityByteArray(); - bool hasBillboardChangedAfterParsing(const QByteArray& data); - const QUrl& getSkeletonModelURL() const { return _skeletonModelURL; } const QString& getDisplayName() const { return _displayName; } virtual void setSkeletonModelURL(const QUrl& skeletonModelURL); @@ -304,12 +300,6 @@ public: Q_INVOKABLE void detachOne(const QString& modelURL, const QString& jointName = QString()); Q_INVOKABLE void detachAll(const QString& modelURL, const QString& jointName = QString()); - virtual void setBillboard(const QByteArray& billboard); - const QByteArray& getBillboard() const { return _billboard; } - - void setBillboardFromURL(const QString& billboardURL); - const QString& getBillboardURL() { return _billboardURL; } - QString getSkeletonModelURLFromScript() const { return _skeletonModelURL.toString(); } void setSkeletonModelURLFromScript(const QString& skeletonModelString) { setSkeletonModelURL(QUrl(skeletonModelString)); } @@ -336,9 +326,7 @@ public: public slots: void sendAvatarDataPacket(); void sendIdentityPacket(); - void sendBillboardPacket(); - void setBillboardFromNetworkReply(); void setJointMappingsFromNetworkReply(); void setSessionUUID(const QUuid& sessionUUID) { setID(sessionUUID); } @@ -377,9 +365,6 @@ protected: float _displayNameTargetAlpha; float _displayNameAlpha; - QByteArray _billboard; - QString _billboardURL; - QHash _jointIndices; ///< 1-based, since zero is returned for missing keys QStringList _jointNames; ///< in order of depth-first traversal diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index 75fb5e6028..f14e2b0ad3 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -136,17 +136,6 @@ void AvatarHashMap::processAvatarIdentityPacket(QSharedPointer } } -void AvatarHashMap::processAvatarBillboardPacket(QSharedPointer message, SharedNodePointer sendingNode) { - QUuid sessionUUID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); - - auto avatar = newOrExistingAvatar(sessionUUID, sendingNode); - - QByteArray billboard = message->read(message->getBytesLeftToRead()); - if (avatar->getBillboard() != billboard) { - avatar->setBillboard(billboard); - } -} - void AvatarHashMap::processKillAvatar(QSharedPointer message, SharedNodePointer sendingNode) { // read the node id QUuid sessionUUID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); diff --git a/libraries/avatars/src/AvatarHashMap.h b/libraries/avatars/src/AvatarHashMap.h index ee1197367c..5f58074427 100644 --- a/libraries/avatars/src/AvatarHashMap.h +++ b/libraries/avatars/src/AvatarHashMap.h @@ -53,7 +53,6 @@ private slots: void processAvatarDataPacket(QSharedPointer message, SharedNodePointer sendingNode); void processAvatarIdentityPacket(QSharedPointer message, SharedNodePointer sendingNode); - void processAvatarBillboardPacket(QSharedPointer message, SharedNodePointer sendingNode); void processKillAvatar(QSharedPointer message, SharedNodePointer sendingNode); protected: diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index a199c6b10e..86c3f5ff35 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -267,7 +267,7 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { if (numBytes == 0) { return; } - memcpy(particleBuffer->editData(), particlePrimitives->data(), numBytes); + particleBuffer->setData(numBytes, (const gpu::Byte*)particlePrimitives->data()); // Update transform and bounds payload.setModelTransform(transform); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 891e1dca3b..f0244d0e3f 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -210,7 +210,7 @@ void RenderableWebEntityItem::render(RenderArgs* args) { } DependencyManager::get()->bindSimpleProgram(batch, textured, culled, emissive); - DependencyManager::get()->renderQuad(batch, topLeft, bottomRight, texMin, texMax, glm::vec4(1.0f)); + DependencyManager::get()->renderQuad(batch, topLeft, bottomRight, texMin, texMax, glm::vec4(1.0f, 1.0f, 1.0f, 0.0f)); } void RenderableWebEntityItem::setSourceUrl(const QString& value) { diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 2df388e1d4..65cae5343a 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -892,7 +892,10 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS properties = true; propertyName = "P"; index = 4; + } else if (subobject.name == "ShadingModel") { + material.shadingModel = subobject.properties.at(0).toString(); } + if (properties) { std::vector unknowns; foreach(const FBXNode& property, subobject.children) { @@ -988,7 +991,6 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS QString propname = subobject.name.data(); int unknown = 0; if ( (propname == "Version") - ||(propname == "ShadingModel") ||(propname == "Multilayer")) { } else { unknown++; @@ -1130,7 +1132,6 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS ambientTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); } else if (type.contains("tex_ao_map")) { occlusionTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); - } else if (type == "lcl rotation") { localRotations.insert(getID(connection.properties, 2), getID(connection.properties, 1)); } else if (type == "lcl translation") { @@ -1331,7 +1332,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS } // NOTE: shapeVertices are in joint-frame - QVector shapeVertices; + std::vector shapeVertices; shapeVertices.resize(geometry.joints.size()); // find our special joints @@ -1522,7 +1523,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS float clusterScale = extractUniformScale(fbxCluster.inverseBindMatrix); glm::mat4 meshToJoint = glm::inverse(joint.bindTransform) * modelTransform; - ShapeVertices& points = shapeVertices[jointIndex]; + ShapeVertices& points = shapeVertices.at(jointIndex); float totalWeight = 0.0f; for (int j = 0; j < cluster.indices.size(); j++) { @@ -1584,7 +1585,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS // transform cluster vertices to joint-frame and save for later float clusterScale = extractUniformScale(firstFBXCluster.inverseBindMatrix); glm::mat4 meshToJoint = glm::inverse(joint.bindTransform) * modelTransform; - ShapeVertices& points = shapeVertices[jointIndex]; + ShapeVertices& points = shapeVertices.at(jointIndex); foreach (const glm::vec3& vertex, extracted.mesh.vertices) { const glm::mat4 vertexTransform = meshToJoint * glm::translate(vertex); points.push_back(extractTranslation(vertexTransform) * clusterScale); @@ -1625,7 +1626,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS FBXJoint& joint = geometry.joints[i]; // NOTE: points are in joint-frame - ShapeVertices& points = shapeVertices[i]; + ShapeVertices& points = shapeVertices.at(i); if (points.size() > 0) { // compute average point glm::vec3 avgPoint = glm::vec3(0.0f); diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index c1952fc550..6ba1c5786b 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -154,6 +154,7 @@ public: QString materialID; QString name; + QString shadingModel; model::MaterialPointer _material; FBXTexture normalTexture; diff --git a/libraries/fbx/src/FBXReader_Material.cpp b/libraries/fbx/src/FBXReader_Material.cpp index 11c6dad2f2..22a577072d 100644 --- a/libraries/fbx/src/FBXReader_Material.cpp +++ b/libraries/fbx/src/FBXReader_Material.cpp @@ -72,6 +72,10 @@ void FBXReader::consolidateFBXMaterials() { // foreach (const QString& materialID, materials) { for (QHash::iterator it = _fbxMaterials.begin(); it != _fbxMaterials.end(); it++) { FBXMaterial& material = (*it); + + // Maya is the exporting the shading model and we aretrying to use it + bool isMaterialLambert = (material.shadingModel.toLower() == "lambert"); + // the pure material associated with this part bool detectDifferentUVs = false; FBXTexture diffuseTexture; @@ -171,6 +175,13 @@ void FBXReader::consolidateFBXMaterials() { emissiveTexture = getTexture(emissiveTextureID); detectDifferentUVs |= (emissiveTexture.texcoordSet != 0) || (!emissiveTexture.transform.isIdentity()); material.emissiveTexture = emissiveTexture; + + if (isMaterialLambert) { + // If the emissiveTextureID comes from the Texture bound to Emissive when material is lambert, we know it s exported from maya + // And the EMissiveColor is forced to 0.5 by Maya which is bad + // So we need to force it to 1.0 + material.emissiveColor = vec3(1.0); + } } FBXTexture occlusionTexture; @@ -198,7 +209,7 @@ void FBXReader::consolidateFBXMaterials() { material._material = std::make_shared(); // Emissive color is the mix of emissiveColor with emissiveFactor - auto emissive = material.emissiveColor * material.emissiveFactor; + auto emissive = material.emissiveColor * (isMaterialLambert ? 1.0f : material.emissiveFactor); // In lambert there is not emissiveFactor material._material->setEmissive(emissive); // Final diffuse color is the mix of diffuseColor with diffuseFactor @@ -212,6 +223,18 @@ void FBXReader::consolidateFBXMaterials() { material._material->setRoughness(model::Material::shininessToRoughness(material.shininess)); float metallic = std::max(material.specularColor.x, std::max(material.specularColor.y, material.specularColor.z)); material._material->setMetallic(metallic); + + if (isMaterialLambert) { + if (!material._material->getKey().isAlbedo()) { + // switch emissive to material albedo as we tag the material to unlit + material._material->setUnlit(true); + material._material->setAlbedo(emissive); + + if (!material.emissiveTexture.isNull()) { + material.albedoTexture = material.emissiveTexture; + } + } + } } if (material.opacity <= 0.0f) { diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index aa8edc3f68..38121555ed 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -624,7 +624,6 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, return geometryPtr; } - void fbxDebugDump(const FBXGeometry& fbxgeo) { qCDebug(modelformat) << "---------------- fbxGeometry ----------------"; qCDebug(modelformat) << " hasSkeletonJoints =" << fbxgeo.hasSkeletonJoints; diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index d9ead354ea..672a29538b 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -65,15 +65,22 @@ public: class GLBuffer : public GPUObject { public: - Stamp _stamp; - GLuint _buffer; - GLuint _size; + const GLuint _buffer; + const GLuint _size; + const Stamp _stamp; - GLBuffer(); + GLBuffer(const Buffer& buffer, GLBuffer* original = nullptr); ~GLBuffer(); - void setSize(GLuint size); + void transfer(); + + private: + bool getNextTransferBlock(GLintptr& outOffset, GLsizeiptr& outSize, size_t& currentPage) const; + + // The owning texture + const Buffer& _gpuBuffer; }; + static GLBuffer* syncGPUObject(const Buffer& buffer); static GLuint getBufferID(const Buffer& buffer); diff --git a/libraries/gpu/src/gpu/GLBackendBuffer.cpp b/libraries/gpu/src/gpu/GLBackendBuffer.cpp index 080d743104..7098fd1feb 100755 --- a/libraries/gpu/src/gpu/GLBackendBuffer.cpp +++ b/libraries/gpu/src/gpu/GLBackendBuffer.cpp @@ -12,12 +12,40 @@ using namespace gpu; -GLBackend::GLBuffer::GLBuffer() : - _stamp(0), - _buffer(0), - _size(0) -{ +GLuint allocateSingleBuffer() { + GLuint result; + glGenBuffers(1, &result); + (void)CHECK_GL_ERROR(); + return result; +} + +GLBackend::GLBuffer::GLBuffer(const Buffer& buffer, GLBuffer* original) : + _buffer(allocateSingleBuffer()), + _size((GLuint)buffer._sysmem.getSize()), + _stamp(buffer._sysmem.getStamp()), + _gpuBuffer(buffer) { + glBindBuffer(GL_ARRAY_BUFFER, _buffer); + if (GLEW_VERSION_4_4 || GLEW_ARB_buffer_storage) { + glBufferStorage(GL_ARRAY_BUFFER, _size, nullptr, GL_DYNAMIC_STORAGE_BIT); + (void)CHECK_GL_ERROR(); + } else { + glBufferData(GL_ARRAY_BUFFER, _size, nullptr, GL_DYNAMIC_DRAW); + (void)CHECK_GL_ERROR(); + } + glBindBuffer(GL_ARRAY_BUFFER, 0); + + if (original) { + glBindBuffer(GL_COPY_WRITE_BUFFER, _buffer); + glBindBuffer(GL_COPY_READ_BUFFER, original->_buffer); + glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, original->_size); + glBindBuffer(GL_COPY_WRITE_BUFFER, 0); + glBindBuffer(GL_COPY_READ_BUFFER, 0); + (void)CHECK_GL_ERROR(); + } + + Backend::setGPUObject(buffer, this); Backend::incrementBufferGPUCount(); + Backend::updateBufferGPUMemoryUsage(0, _size); } GLBackend::GLBuffer::~GLBuffer() { @@ -28,37 +56,56 @@ GLBackend::GLBuffer::~GLBuffer() { Backend::decrementBufferGPUCount(); } -void GLBackend::GLBuffer::setSize(GLuint size) { - Backend::updateBufferGPUMemoryUsage(_size, size); - _size = size; +void GLBackend::GLBuffer::transfer() { + glBindBuffer(GL_ARRAY_BUFFER, _buffer); + (void)CHECK_GL_ERROR(); + GLintptr offset; + GLsizeiptr size; + size_t currentPage { 0 }; + auto data = _gpuBuffer.getSysmem().readData(); + while (getNextTransferBlock(offset, size, currentPage)) { + glBufferSubData(GL_ARRAY_BUFFER, offset, size, data + offset); + (void)CHECK_GL_ERROR(); + } + glBindBuffer(GL_ARRAY_BUFFER, 0); + (void)CHECK_GL_ERROR(); + _gpuBuffer._flags &= ~Buffer::DIRTY; +} + +bool GLBackend::GLBuffer::getNextTransferBlock(GLintptr& outOffset, GLsizeiptr& outSize, size_t& currentPage) const { + size_t pageCount = _gpuBuffer._pages.size(); + // Advance to the first dirty page + while (currentPage < pageCount && (0 == (Buffer::DIRTY & _gpuBuffer._pages[currentPage]))) { + ++currentPage; + } + + // If we got to the end, we're done + if (currentPage >= pageCount) { + return false; + } + + // Advance to the next clean page + outOffset = static_cast(currentPage * _gpuBuffer._pageSize); + while (currentPage < pageCount && (0 != (Buffer::DIRTY & _gpuBuffer._pages[currentPage]))) { + _gpuBuffer._pages[currentPage] &= ~Buffer::DIRTY; + ++currentPage; + } + outSize = static_cast((currentPage * _gpuBuffer._pageSize) - outOffset); + return true; } GLBackend::GLBuffer* GLBackend::syncGPUObject(const Buffer& buffer) { GLBuffer* object = Backend::getGPUObject(buffer); - if (object && (object->_stamp == buffer.getSysmem().getStamp())) { - return object; + // Has the storage size changed? + if (!object || object->_stamp != buffer.getSysmem().getStamp()) { + object = new GLBuffer(buffer, object); } - // need to have a gpu object? - if (!object) { - object = new GLBuffer(); - glGenBuffers(1, &object->_buffer); - (void) CHECK_GL_ERROR(); - Backend::setGPUObject(buffer, object); + if (0 != (buffer._flags & Buffer::DIRTY)) { + object->transfer(); } - // Now let's update the content of the bo with the sysmem version - // TODO: in the future, be smarter about when to actually upload the glBO version based on the data that did change - //if () { - glBindBuffer(GL_ARRAY_BUFFER, object->_buffer); - glBufferData(GL_ARRAY_BUFFER, buffer.getSysmem().getSize(), buffer.getSysmem().readData(), GL_DYNAMIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - object->_stamp = buffer.getSysmem().getStamp(); - object->setSize((GLuint)buffer.getSysmem().getSize()); - //} - (void) CHECK_GL_ERROR(); - return object; } diff --git a/libraries/gpu/src/gpu/GLBackendOutput.cpp b/libraries/gpu/src/gpu/GLBackendOutput.cpp index 545d0a8cdb..d40c5f9b97 100755 --- a/libraries/gpu/src/gpu/GLBackendOutput.cpp +++ b/libraries/gpu/src/gpu/GLBackendOutput.cpp @@ -209,6 +209,8 @@ void GLBackend::resetOutputStage() { _output._drawFBO = 0; glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); } + + glEnable(GL_FRAMEBUFFER_SRGB); } void GLBackend::do_setFramebuffer(Batch& batch, size_t paramOffset) { diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index 609451bd13..24b9544168 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -535,13 +535,12 @@ void GLBackend::syncSampler(const Sampler& sampler, Texture::Type type, const GL GLint minFilter; GLint magFilter; }; - static const GLFilterMode filterModes[] = { + static const GLFilterMode filterModes[Sampler::NUM_FILTERS] = { { GL_NEAREST, GL_NEAREST }, //FILTER_MIN_MAG_POINT, { GL_NEAREST, GL_LINEAR }, //FILTER_MIN_POINT_MAG_LINEAR, { GL_LINEAR, GL_NEAREST }, //FILTER_MIN_LINEAR_MAG_POINT, { GL_LINEAR, GL_LINEAR }, //FILTER_MIN_MAG_LINEAR, - { GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST }, //FILTER_MIN_MAG_MIP_POINT, { GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST }, //FILTER_MIN_MAG_MIP_POINT, { GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST }, //FILTER_MIN_MAG_POINT_MIP_LINEAR, { GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR }, //FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT, @@ -557,7 +556,7 @@ void GLBackend::syncSampler(const Sampler& sampler, Texture::Type type, const GL glTexParameteri(object->_target, GL_TEXTURE_MIN_FILTER, fm.minFilter); glTexParameteri(object->_target, GL_TEXTURE_MAG_FILTER, fm.magFilter); - static const GLenum comparisonFuncs[] = { + static const GLenum comparisonFuncs[NUM_COMPARISON_FUNCS] = { GL_NEVER, GL_LESS, GL_EQUAL, @@ -574,7 +573,7 @@ void GLBackend::syncSampler(const Sampler& sampler, Texture::Type type, const GL glTexParameteri(object->_target, GL_TEXTURE_COMPARE_MODE, GL_NONE); } - static const GLenum wrapModes[] = { + static const GLenum wrapModes[Sampler::NUM_WRAP_MODES] = { GL_REPEAT, // WRAP_REPEAT, GL_MIRRORED_REPEAT, // WRAP_MIRROR, GL_CLAMP_TO_EDGE, // WRAP_CLAMP, diff --git a/libraries/gpu/src/gpu/Resource.cpp b/libraries/gpu/src/gpu/Resource.cpp index deb17300c3..7dbe662cbc 100644 --- a/libraries/gpu/src/gpu/Resource.cpp +++ b/libraries/gpu/src/gpu/Resource.cpp @@ -109,40 +109,18 @@ void Resource::Sysmem::deallocateMemory(Byte* dataAllocated, Size size) { } } -Resource::Sysmem::Sysmem() : - _stamp(0), - _size(0), - _data(NULL) -{ -} +Resource::Sysmem::Sysmem() {} -Resource::Sysmem::Sysmem(Size size, const Byte* bytes) : - _stamp(0), - _size(0), - _data(NULL) -{ - if (size > 0) { - _size = allocateMemory(&_data, size); - if (_size >= size) { - if (bytes) { - memcpy(_data, bytes, size); - } - } +Resource::Sysmem::Sysmem(Size size, const Byte* bytes) { + if (size > 0 && bytes) { + setData(_size, bytes); } } -Resource::Sysmem::Sysmem(const Sysmem& sysmem) : - _stamp(0), - _size(0), - _data(NULL) -{ +Resource::Sysmem::Sysmem(const Sysmem& sysmem) { if (sysmem.getSize() > 0) { - _size = allocateMemory(&_data, sysmem.getSize()); - if (_size >= sysmem.getSize()) { - if (sysmem.readData()) { - memcpy(_data, sysmem.readData(), sysmem.getSize()); - } - } + allocate(sysmem._size); + setData(_size, sysmem._data); } } @@ -208,7 +186,6 @@ Resource::Size Resource::Sysmem::setData( Size size, const Byte* bytes ) { if (allocate(size) == size) { if (size && bytes) { memcpy( _data, bytes, _size ); - _stamp++; } } return _size; @@ -217,7 +194,6 @@ Resource::Size Resource::Sysmem::setData( Size size, const Byte* bytes ) { Resource::Size Resource::Sysmem::setSubData( Size offset, Size size, const Byte* bytes) { if (size && ((offset + size) <= getSize()) && bytes) { memcpy( _data + offset, bytes, size ); - _stamp++; return size; } return 0; @@ -264,65 +240,105 @@ Buffer::Size Buffer::getBufferGPUMemoryUsage() { return Context::getBufferGPUMemoryUsage(); } -Buffer::Buffer() : - Resource(), - _sysmem(new Sysmem()) { +Buffer::Buffer(Size pageSize) : + _pageSize(pageSize) { _bufferCPUCount++; - } -Buffer::Buffer(Size size, const Byte* bytes) : - Resource(), - _sysmem(new Sysmem(size, bytes)) { - _bufferCPUCount++; - Buffer::updateBufferCPUMemoryUsage(0, _sysmem->getSize()); +Buffer::Buffer(Size size, const Byte* bytes, Size pageSize) : Buffer(pageSize) { + setData(size, bytes); } -Buffer::Buffer(const Buffer& buf) : - Resource(), - _sysmem(new Sysmem(buf.getSysmem())) { - _bufferCPUCount++; - Buffer::updateBufferCPUMemoryUsage(0, _sysmem->getSize()); +Buffer::Buffer(const Buffer& buf) : Buffer(buf._pageSize) { + setData(buf.getSize(), buf.getData()); } Buffer& Buffer::operator=(const Buffer& buf) { - (*_sysmem) = buf.getSysmem(); + const_cast(_pageSize) = buf._pageSize; + setData(buf.getSize(), buf.getData()); return (*this); } Buffer::~Buffer() { _bufferCPUCount--; - - if (_sysmem) { - Buffer::updateBufferCPUMemoryUsage(_sysmem->getSize(), 0); - delete _sysmem; - _sysmem = NULL; - } + Buffer::updateBufferCPUMemoryUsage(_sysmem.getSize(), 0); } Buffer::Size Buffer::resize(Size size) { + _end = size; auto prevSize = editSysmem().getSize(); - auto newSize = editSysmem().resize(size); - Buffer::updateBufferCPUMemoryUsage(prevSize, newSize); - return newSize; + if (prevSize < size) { + auto newPages = getRequiredPageCount(); + auto newSize = newPages * _pageSize; + editSysmem().resize(newSize); + // All new pages start off as clean, because they haven't been populated by data + _pages.resize(newPages, 0); + Buffer::updateBufferCPUMemoryUsage(prevSize, newSize); + } + return _end; } +void Buffer::markDirty(Size offset, Size bytes) { + if (!bytes) { + return; + } + _flags |= DIRTY; + // Find the starting page + Size startPage = (offset / _pageSize); + // Non-zero byte count, so at least one page is dirty + Size pageCount = 1; + // How much of the page is after the offset? + Size remainder = _pageSize - (offset % _pageSize); + // If there are more bytes than page space remaining, we need to increase the page count + if (bytes > remainder) { + // Get rid of the amount that will fit in the current page + bytes -= remainder; + + pageCount += (bytes / _pageSize); + if (bytes % _pageSize) { + ++pageCount; + } + } + + // Mark the pages dirty + for (Size i = 0; i < pageCount; ++i) { + _pages[i + startPage] |= DIRTY; + } +} + + Buffer::Size Buffer::setData(Size size, const Byte* data) { - auto prevSize = editSysmem().getSize(); - auto newSize = editSysmem().setData(size, data); - Buffer::updateBufferCPUMemoryUsage(prevSize, newSize); - return newSize; + resize(size); + setSubData(0, size, data); + return _end; } Buffer::Size Buffer::setSubData(Size offset, Size size, const Byte* data) { - return editSysmem().setSubData( offset, size, data); + auto changedBytes = editSysmem().setSubData(offset, size, data); + if (changedBytes) { + markDirty(offset, changedBytes); + } + return changedBytes; } Buffer::Size Buffer::append(Size size, const Byte* data) { - auto prevSize = editSysmem().getSize(); - auto newSize = editSysmem().append( size, data); - Buffer::updateBufferCPUMemoryUsage(prevSize, newSize); - return newSize; + auto offset = _end; + resize(_end + size); + setSubData(offset, size, data); + return _end; +} + +Buffer::Size Buffer::getSize() const { + Q_ASSERT(getSysmem().getSize() >= _end); + return _end; +} + +Buffer::Size Buffer::getRequiredPageCount() const { + Size result = _end / _pageSize; + if (_end % _pageSize) { + ++result; + } + return result; } const Element BufferView::DEFAULT_ELEMENT = Element( gpu::SCALAR, gpu::UINT8, gpu::RAW ); diff --git a/libraries/gpu/src/gpu/Resource.h b/libraries/gpu/src/gpu/Resource.h index 570aff00fc..70292f215b 100644 --- a/libraries/gpu/src/gpu/Resource.h +++ b/libraries/gpu/src/gpu/Resource.h @@ -88,10 +88,10 @@ protected: // Access the byte array. // The edit version allow to map data. const Byte* readData() const { return _data; } - Byte* editData() { _stamp++; return _data; } + Byte* editData() { return _data; } template< typename T > const T* read() const { return reinterpret_cast< T* > ( _data ); } - template< typename T > T* edit() { _stamp++; return reinterpret_cast< T* > ( _data ); } + template< typename T > T* edit() { return reinterpret_cast< T* > ( _data ); } // Access the current version of the sysmem, used to compare if copies are in sync Stamp getStamp() const { return _stamp; } @@ -102,9 +102,9 @@ protected: bool isAvailable() const { return (_data != 0); } private: - Stamp _stamp; - Size _size; - Byte* _data; + Stamp _stamp { 0 }; + Size _size { 0 }; + Byte* _data { nullptr }; }; }; @@ -115,22 +115,28 @@ class Buffer : public Resource { static void updateBufferCPUMemoryUsage(Size prevObjectSize, Size newObjectSize); public: + enum Flag { + DIRTY = 0x01, + }; + + // Currently only one flag... 'dirty' + using PageFlags = std::vector; + static const Size DEFAULT_PAGE_SIZE = 4096; static uint32_t getBufferCPUCount(); static Size getBufferCPUMemoryUsage(); static uint32_t getBufferGPUCount(); static Size getBufferGPUMemoryUsage(); - Buffer(); - Buffer(Size size, const Byte* bytes); + Buffer(Size pageSize = DEFAULT_PAGE_SIZE); + Buffer(Size size, const Byte* bytes, Size pageSize = DEFAULT_PAGE_SIZE); Buffer(const Buffer& buf); // deep copy of the sysmem buffer Buffer& operator=(const Buffer& buf); // deep copy of the sysmem buffer ~Buffer(); // The size in bytes of data stored in the buffer - Size getSize() const { return getSysmem().getSize(); } + Size getSize() const; const Byte* getData() const { return getSysmem().readData(); } - Byte* editData() { return editSysmem().editData(); } - + // Resize the buffer // Keep previous data [0 to min(pSize, mSize)] Size resize(Size pSize); @@ -143,6 +149,23 @@ public: // \return the number of bytes copied Size setSubData(Size offset, Size size, const Byte* data); + template + Size setSubData(Size index, const T& t) { + Size offset = index * sizeof(T); + Size size = sizeof(T); + return setSubData(offset, size, reinterpret_cast(&t)); + } + + template + Size setSubData(Size index, const std::vector& t) { + if (t.empty()) { + return 0; + } + Size offset = index * sizeof(T); + Size size = t.size() * sizeof(T); + return setSubData(offset, size, reinterpret_cast(&t[0])); + } + // Append new data at the end of the current buffer // do a resize( size + getSize) and copy the new data // \return the number of bytes copied @@ -155,18 +178,38 @@ public: template Size append(const std::vector& t) { + if (t.empty()) { + return _end; + } return append(sizeof(T) * t.size(), reinterpret_cast(&t[0])); } - // Access the sysmem object. - const Sysmem& getSysmem() const { assert(_sysmem); return (*_sysmem); } - Sysmem& editSysmem() { assert(_sysmem); return (*_sysmem); } - const GPUObjectPointer gpuObject {}; protected: + void markDirty(Size offset, Size bytes); - Sysmem* _sysmem = NULL; + template + void markDirty(Size index, Size count = 1) { + markDirty(sizeof(T) * index, sizeof(T) * count); + } + + // Access the sysmem object, limited to ourselves and GPUObject derived classes + const Sysmem& getSysmem() const { return _sysmem; } + Sysmem& editSysmem() { return _sysmem; } + Byte* editData() { return editSysmem().editData(); } + + Size getRequiredPageCount() const; + + Size _end { 0 }; + mutable uint8_t _flags; + mutable PageFlags _pages; + const Size _pageSize; + Sysmem _sysmem; + + // FIXME find a more generic way to do this. + friend class GLBackend; + friend class BufferView; }; typedef std::shared_ptr BufferPointer; @@ -290,8 +333,14 @@ public: int _stride; }; +#if 0 + // Direct memory access to the buffer contents is incompatible with the paging memory scheme template Iterator begin() { return Iterator(&edit(0), _stride); } template Iterator end() { return Iterator(&edit(getNum()), _stride); } +#else + template Iterator begin() const { return Iterator(&get(), _stride); } + template Iterator end() const { return Iterator(&get(getNum()), _stride); } +#endif template Iterator cbegin() const { return Iterator(&get(), _stride); } template Iterator cend() const { return Iterator(&get(getNum()), _stride); } @@ -328,6 +377,7 @@ public: qDebug() << "Accessing buffer outside the BufferView range, element size = " << sizeof(T) << " when bufferView size = " << _size; } #endif + _buffer->markDirty(_offset, sizeof(T)); T* t = (reinterpret_cast (_buffer->editData() + _offset)); return *(t); } @@ -361,6 +411,7 @@ public: qDebug() << "Accessing buffer outside the BufferView range, index = " << index << " number elements = " << getNum(); } #endif + _buffer->markDirty(elementOffset, sizeof(T)); return *(reinterpret_cast (_buffer->editData() + elementOffset)); } }; diff --git a/libraries/model/src/model/Material.cpp b/libraries/model/src/model/Material.cpp index d700a191c4..53478be536 100755 --- a/libraries/model/src/model/Material.cpp +++ b/libraries/model/src/model/Material.cpp @@ -74,6 +74,11 @@ void Material::setOpacity(float opacity) { _schemaBuffer.edit()._opacity = opacity; } +void Material::setUnlit(bool value) { + _key.setUnlit(value); + _schemaBuffer.edit()._key = (uint32)_key._flags.to_ulong(); +} + void Material::setAlbedo(const Color& albedo, bool isSRGB) { _key.setAlbedo(glm::any(glm::greaterThan(albedo, Color(0.0f)))); _schemaBuffer.edit()._key = (uint32)_key._flags.to_ulong(); @@ -93,6 +98,7 @@ void Material::setFresnel(const Color& fresnel, bool isSRGB) { } void Material::setMetallic(float metallic) { + metallic = glm::clamp(metallic, 0.0f, 1.0f); _key.setMetallic(metallic > 0.0f); _schemaBuffer.edit()._key = (uint32)_key._flags.to_ulong(); _schemaBuffer.edit()._metallic = metallic; diff --git a/libraries/model/src/model/Material.h b/libraries/model/src/model/Material.h index cf6b48f257..8dd9dd7960 100755 --- a/libraries/model/src/model/Material.h +++ b/libraries/model/src/model/Material.h @@ -28,14 +28,15 @@ class MaterialKey { public: enum FlagBit { EMISSIVE_VAL_BIT = 0, + UNLIT_VAL_BIT, ALBEDO_VAL_BIT, METALLIC_VAL_BIT, GLOSSY_VAL_BIT, OPACITY_VAL_BIT, - OPACITY_MASK_MAP_BIT, // OPacity Map and Opacity MASK map are mutually exclusive + OPACITY_MASK_MAP_BIT, // Opacity Map and Opacity MASK map are mutually exclusive OPACITY_TRANSLUCENT_MAP_BIT, - // THe map bits must be in the smae sequence as the enum names for the map channels + // THe map bits must be in the same sequence as the enum names for the map channels EMISSIVE_MAP_BIT, ALBEDO_MAP_BIT, METALLIC_MAP_BIT, @@ -74,9 +75,12 @@ public: MaterialKey build() const { return MaterialKey(_flags); } Builder& withEmissive() { _flags.set(EMISSIVE_VAL_BIT); return (*this); } + Builder& withUnlit() { _flags.set(UNLIT_VAL_BIT); return (*this); } + Builder& withAlbedo() { _flags.set(ALBEDO_VAL_BIT); return (*this); } Builder& withMetallic() { _flags.set(METALLIC_VAL_BIT); return (*this); } Builder& withGlossy() { _flags.set(GLOSSY_VAL_BIT); return (*this); } + Builder& withTranslucentFactor() { _flags.set(OPACITY_VAL_BIT); return (*this); } Builder& withEmissiveMap() { _flags.set(EMISSIVE_MAP_BIT); return (*this); } @@ -98,6 +102,9 @@ public: void setEmissive(bool value) { _flags.set(EMISSIVE_VAL_BIT, value); } bool isEmissive() const { return _flags[EMISSIVE_VAL_BIT]; } + void setUnlit(bool value) { _flags.set(UNLIT_VAL_BIT, value); } + bool isUnlit() const { return _flags[UNLIT_VAL_BIT]; } + void setEmissiveMap(bool value) { _flags.set(EMISSIVE_MAP_BIT, value); } bool isEmissiveMap() const { return _flags[EMISSIVE_MAP_BIT]; } @@ -172,6 +179,9 @@ public: Builder& withoutEmissiveMap() { _value.reset(MaterialKey::EMISSIVE_MAP_BIT); _mask.set(MaterialKey::EMISSIVE_MAP_BIT); return (*this); } Builder& withEmissiveMap() { _value.set(MaterialKey::EMISSIVE_MAP_BIT); _mask.set(MaterialKey::EMISSIVE_MAP_BIT); return (*this); } + Builder& withoutUnlit() { _value.reset(MaterialKey::UNLIT_VAL_BIT); _mask.set(MaterialKey::UNLIT_VAL_BIT); return (*this); } + Builder& withUnlit() { _value.set(MaterialKey::UNLIT_VAL_BIT); _mask.set(MaterialKey::UNLIT_VAL_BIT); return (*this); } + Builder& withoutAlbedo() { _value.reset(MaterialKey::ALBEDO_VAL_BIT); _mask.set(MaterialKey::ALBEDO_VAL_BIT); return (*this); } Builder& withAlbedo() { _value.set(MaterialKey::ALBEDO_VAL_BIT); _mask.set(MaterialKey::ALBEDO_VAL_BIT); return (*this); } @@ -250,6 +260,9 @@ public: void setOpacity(float opacity); float getOpacity() const { return _schemaBuffer.get()._opacity; } + void setUnlit(bool value); + bool isUnlit() const { return _key.isUnlit(); } + void setAlbedo(const Color& albedo, bool isSRGB = true); Color getAlbedo(bool SRGB = true) const { return (SRGB ? ColorUtils::tosRGBVec3(_schemaBuffer.get()._albedo) : _schemaBuffer.get()._albedo); } diff --git a/libraries/model/src/model/Material.slh b/libraries/model/src/model/Material.slh index 28f9769a8b..4a6139c664 100644 --- a/libraries/model/src/model/Material.slh +++ b/libraries/model/src/model/Material.slh @@ -40,20 +40,21 @@ float getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); } int getMaterialKey(Material m) { return floatBitsToInt(m._spareKey.w); } const int EMISSIVE_VAL_BIT = 0x00000001; -const int ALBEDO_VAL_BIT = 0x00000002; -const int METALLIC_VAL_BIT = 0x00000004; -const int GLOSSY_VAL_BIT = 0x00000008; -const int OPACITY_VAL_BIT = 0x00000010; -const int OPACITY_MASK_MAP_BIT = 0x00000020; -const int OPACITY_TRANSLUCENT_MAP_BIT = 0x00000040; +const int UNLIT_VAL_BIT = 0x00000002; +const int ALBEDO_VAL_BIT = 0x00000004; +const int METALLIC_VAL_BIT = 0x00000008; +const int GLOSSY_VAL_BIT = 0x00000010; +const int OPACITY_VAL_BIT = 0x00000020; +const int OPACITY_MASK_MAP_BIT = 0x00000040; +const int OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080; -const int EMISSIVE_MAP_BIT = 0x00000080; -const int ALBEDO_MAP_BIT = 0x00000100; -const int METALLIC_MAP_BIT = 0x00000200; -const int ROUGHNESS_MAP_BIT = 0x00000400; -const int NORMAL_MAP_BIT = 0x00000800; -const int OCCLUSION_MAP_BIT = 0x00001000; -const int LIGHTMAP_MAP_BIT = 0x00002000; +const int EMISSIVE_MAP_BIT = 0x00000100; +const int ALBEDO_MAP_BIT = 0x00000200; +const int METALLIC_MAP_BIT = 0x00000400; +const int ROUGHNESS_MAP_BIT = 0x00000800; +const int NORMAL_MAP_BIT = 0x00001000; +const int OCCLUSION_MAP_BIT = 0x00002000; +const int LIGHTMAP_MAP_BIT = 0x00004000; <@endif@> diff --git a/libraries/render-utils/src/AnimDebugDraw.cpp b/libraries/render-utils/src/AnimDebugDraw.cpp index 220b673591..11c43eaee4 100644 --- a/libraries/render-utils/src/AnimDebugDraw.cpp +++ b/libraries/render-utils/src/AnimDebugDraw.cpp @@ -118,29 +118,18 @@ AnimDebugDraw::AnimDebugDraw() : // HACK: add red, green and blue axis at (1,1,1) _animDebugDrawData->_vertexBuffer->resize(sizeof(Vertex) * 6); - Vertex* data = (Vertex*)_animDebugDrawData->_vertexBuffer->editData(); - - data[0].pos = glm::vec3(1.0, 1.0f, 1.0f); - data[0].rgba = toRGBA(255, 0, 0, 255); - data[1].pos = glm::vec3(2.0, 1.0f, 1.0f); - data[1].rgba = toRGBA(255, 0, 0, 255); - - data[2].pos = glm::vec3(1.0, 1.0f, 1.0f); - data[2].rgba = toRGBA(0, 255, 0, 255); - data[3].pos = glm::vec3(1.0, 2.0f, 1.0f); - data[3].rgba = toRGBA(0, 255, 0, 255); - - data[4].pos = glm::vec3(1.0, 1.0f, 1.0f); - data[4].rgba = toRGBA(0, 0, 255, 255); - data[5].pos = glm::vec3(1.0, 1.0f, 2.0f); - data[5].rgba = toRGBA(0, 0, 255, 255); - - _animDebugDrawData->_indexBuffer->resize(sizeof(uint16_t) * 6); - uint16_t* indices = (uint16_t*)_animDebugDrawData->_indexBuffer->editData(); - for (int i = 0; i < 6; i++) { - indices[i] = i; - } - + + static std::vector vertices({ + Vertex { glm::vec3(1.0, 1.0f, 1.0f), toRGBA(255, 0, 0, 255) }, + Vertex { glm::vec3(2.0, 1.0f, 1.0f), toRGBA(255, 0, 0, 255) }, + Vertex { glm::vec3(1.0, 1.0f, 1.0f), toRGBA(0, 255, 0, 255) }, + Vertex { glm::vec3(1.0, 2.0f, 1.0f), toRGBA(0, 255, 0, 255) }, + Vertex { glm::vec3(1.0, 1.0f, 1.0f), toRGBA(0, 0, 255, 255) }, + Vertex { glm::vec3(1.0, 1.0f, 2.0f), toRGBA(0, 0, 255, 255) }, + }); + static std::vector indices({ 0, 1, 2, 3, 4, 5 }); + _animDebugDrawData->_vertexBuffer->setSubData(0, vertices); + _animDebugDrawData->_indexBuffer->setSubData(0, indices); } AnimDebugDraw::~AnimDebugDraw() { @@ -356,9 +345,13 @@ void AnimDebugDraw::update() { numVerts += (int)DebugDraw::getInstance().getRays().size() * VERTICES_PER_RAY; // allocate verts! - data._vertexBuffer->resize(sizeof(Vertex) * numVerts); - Vertex* verts = (Vertex*)data._vertexBuffer->editData(); - Vertex* v = verts; + std::vector vertices; + vertices.resize(numVerts); + //Vertex* verts = (Vertex*)data._vertexBuffer->editData(); + Vertex* v = nullptr; + if (numVerts) { + v = &vertices[0]; + } // draw absolute poses for (auto& iter : _absolutePoses) { @@ -381,6 +374,8 @@ void AnimDebugDraw::update() { } } } + data._vertexBuffer->resize(sizeof(Vertex) * numVerts); + data._vertexBuffer->setSubData(0, vertices); // draw markers from shared DebugDraw singleton for (auto& iter : markerMap) { @@ -408,20 +403,19 @@ void AnimDebugDraw::update() { } DebugDraw::getInstance().clearRays(); - assert(numVerts == (v - verts)); + assert((!numVerts && !v) || (numVerts == (v - &vertices[0]))); render::Item::Bound theBound; for (int i = 0; i < numVerts; i++) { - theBound += verts[i].pos; + theBound += vertices[i].pos; } data._bound = theBound; data._isVisible = (numVerts > 0); data._indexBuffer->resize(sizeof(uint16_t) * numVerts); - uint16_t* indices = (uint16_t*)data._indexBuffer->editData(); for (int i = 0; i < numVerts; i++) { - indices[i] = i; + data._indexBuffer->setSubData(i, (uint16_t)i);; } }); scene->enqueuePendingChanges(pendingChanges); diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index 12d3774ffd..6dfec30b16 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -90,14 +90,21 @@ static const std::string DEFAULT_OCCLUSION_SHADER{ static const std::string DEFAULT_EMISSIVE_SHADER{ "vec4 getFragmentColor() {" " DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);" - " return (frag.mode != LIGHT_MAPPED ? vec4(pow(frag.emissive, vec3(1.0 / 2.2)), 1.0) : vec4(vec3(0.0), 1.0));" + " return (frag.mode == FRAG_MODE_SHADED ? vec4(pow(frag.emissive, vec3(1.0 / 2.2)), 1.0) : vec4(vec3(0.0), 1.0));" + " }" +}; + +static const std::string DEFAULT_UNLIT_SHADER{ + "vec4 getFragmentColor() {" + " DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);" + " return (frag.mode == FRAG_MODE_UNLIT ? vec4(pow(frag.diffuse, vec3(1.0 / 2.2)), 1.0) : vec4(vec3(0.0), 1.0));" " }" }; static const std::string DEFAULT_LIGHTMAP_SHADER{ "vec4 getFragmentColor() {" " DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);" - " return (frag.mode == LIGHT_MAPPED ? vec4(frag.emissive, 1.0) : vec4(vec3(0.0), 1.0));" + " return (frag.mode == FRAG_MODE_LIGHTMAPPED ? vec4(pow(frag.emissive, vec3(1.0 / 2.2)), 1.0) : vec4(vec3(0.0), 1.0));" " }" }; @@ -184,6 +191,8 @@ std::string DebugDeferredBuffer::getShaderSourceCode(Mode mode, std::string cust return DEFAULT_DEPTH_SHADER; case EmissiveMode: return DEFAULT_EMISSIVE_SHADER; + case UnlitMode: + return DEFAULT_UNLIT_SHADER; case OcclusionMode: return DEFAULT_OCCLUSION_SHADER; case LightmapMode: diff --git a/libraries/render-utils/src/DebugDeferredBuffer.h b/libraries/render-utils/src/DebugDeferredBuffer.h index f00dd58f0e..521dc13e0a 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.h +++ b/libraries/render-utils/src/DebugDeferredBuffer.h @@ -53,6 +53,7 @@ protected: RoughnessMode, MetallicMode, EmissiveMode, + UnlitMode, OcclusionMode, LightmapMode, LightingMode, diff --git a/libraries/render-utils/src/DeferredBuffer.slh b/libraries/render-utils/src/DeferredBuffer.slh index 5a3c941ce3..aed89b30d0 100755 --- a/libraries/render-utils/src/DeferredBuffer.slh +++ b/libraries/render-utils/src/DeferredBuffer.slh @@ -11,135 +11,44 @@ <@if not DEFERRED_BUFFER_SLH@> <@def DEFERRED_BUFFER_SLH@> +// Unpack the metallic-mode value +const float FRAG_PACK_SHADED_NON_METALLIC = 0.0; +const float FRAG_PACK_SHADED_METALLIC = 0.1; +const float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC); -// the albedo texture -uniform sampler2D albedoMap; +const float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2; +const float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3; +const float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC); -// the normal texture -uniform sampler2D normalMap; +const float FRAG_PACK_UNLIT = 0.5; -// the specular texture -uniform sampler2D specularMap; +const int FRAG_MODE_UNLIT = 0; +const int FRAG_MODE_SHADED = 1; +const int FRAG_MODE_LIGHTMAPPED = 2; -// the depth texture -uniform sampler2D depthMap; - -// the obscurance texture -uniform sampler2D obscuranceMap; - -// the lighting texture -uniform sampler2D lightingMap; - - -struct DeferredTransform { - mat4 projection; - mat4 viewInverse; - float stereoSide; - vec3 _spareABC; -}; - -layout(std140) uniform deferredTransformBuffer { - DeferredTransform _deferredTransform; -}; -DeferredTransform getDeferredTransform() { - return _deferredTransform; -} - -bool getStereoMode(DeferredTransform deferredTransform) { - return (deferredTransform.stereoSide != 0.0); -} -float getStereoSide(DeferredTransform deferredTransform) { - return (deferredTransform.stereoSide); -} - -vec4 evalEyePositionFromZ(DeferredTransform deferredTransform, float depthVal, vec2 texcoord) { - vec3 nPos = vec3(texcoord.xy * 2.0f - 1.0f, depthVal * 2.0f - 1.0f); - - // compute the view space position using the depth - // basically manually pick the proj matrix components to do the inverse - float Ze = -deferredTransform.projection[3][2] / (nPos.z + deferredTransform.projection[2][2]); - float Xe = (-Ze * nPos.x - Ze * deferredTransform.projection[2][0] - deferredTransform.projection[3][0]) / deferredTransform.projection[0][0]; - float Ye = (-Ze * nPos.y - Ze * deferredTransform.projection[2][1] - deferredTransform.projection[3][1]) / deferredTransform.projection[1][1]; - return vec4(Xe, Ye, Ze, 1.0f); -} - -struct DeferredFragment { - vec4 normalVal; - vec4 diffuseVal; - vec4 specularVal; - vec4 position; - vec3 normal; - float metallic; - vec3 diffuse; - float obscurance; - vec3 specular; - float roughness; - vec3 emissive; - int mode; - float depthVal; -}; - -const int LIGHT_MAPPED = 1; - -vec4 unpackDeferredPosition(DeferredTransform deferredTransform, float depthValue, vec2 texcoord) { - if (getStereoMode(deferredTransform)) { - if (texcoord.x > 0.5) { - texcoord.x -= 0.5; - } - texcoord.x *= 2.0; +void unpackModeMetallic(float rawValue, out int mode, out float metallic) { + if (rawValue <= FRAG_PACK_SHADED_METALLIC) { + mode = FRAG_MODE_SHADED; + metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0); + } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) { + mode = FRAG_MODE_LIGHTMAPPED; + metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0); + } else if (rawValue >= FRAG_PACK_UNLIT) { + mode = FRAG_MODE_UNLIT; + metallic = 0.0; } - return evalEyePositionFromZ(deferredTransform, depthValue, texcoord); } -DeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) { - - DeferredFragment frag; - frag.depthVal = -1; - frag.normalVal = texture(normalMap, texcoord); - frag.diffuseVal = texture(albedoMap, texcoord); - frag.specularVal = texture(specularMap, texcoord); - frag.obscurance = texture(obscuranceMap, texcoord).x; - - // Unpack the normal from the map - frag.normal = normalize(frag.normalVal.xyz * 2.0 - vec3(1.0)); - - frag.mode = 0; - frag.emissive = frag.specularVal.xyz; - if (frag.normalVal.a < 0.5) { - frag.mode = 0; - frag.roughness = 2.0 * frag.normalVal.a; - } else { - frag.mode = LIGHT_MAPPED; - frag.roughness = 2.0 * frag.normalVal.a - 1.0; - } - - frag.metallic = frag.diffuseVal.a; - frag.diffuse = frag.diffuseVal.xyz; - if (frag.metallic <= 0.5) { - frag.metallic = 0.0; - frag.specular = vec3(0.03); // Default Di-electric fresnel value - } else { - frag.specular = vec3(frag.diffuseVal.xyz); - frag.metallic = 1.0; - } - frag.obscurance = min(frag.specularVal.w, frag.obscurance); - - return frag; +float packShadedMetallic(float metallic) { + return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic); } -DeferredFragment unpackDeferredFragment(DeferredTransform deferredTransform, vec2 texcoord) { - - float depthValue = texture(depthMap, texcoord).r; - - DeferredFragment frag = unpackDeferredFragmentNoPosition(texcoord); - - frag.depthVal = depthValue; - frag.position = unpackDeferredPosition(deferredTransform, frag.depthVal, texcoord); - - return frag; +float packLightmappedMetallic(float metallic) { + return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic); } - - +float packUnlit() { + return FRAG_PACK_UNLIT; +} <@endif@> diff --git a/libraries/render-utils/src/DeferredBufferRead.slh b/libraries/render-utils/src/DeferredBufferRead.slh new file mode 100644 index 0000000000..fa166300ae --- /dev/null +++ b/libraries/render-utils/src/DeferredBufferRead.slh @@ -0,0 +1,140 @@ + +<@if not DEFERRED_BUFFER_READ_SLH@> +<@def DEFERRED_BUFFER_READ_SLH@> + +<@include DeferredBuffer.slh@> + +// the albedo texture +uniform sampler2D albedoMap; + +// the normal texture +uniform sampler2D normalMap; + +// the specular texture +uniform sampler2D specularMap; + +// the depth texture +uniform sampler2D depthMap; + +// the obscurance texture +uniform sampler2D obscuranceMap; + +// the lighting texture +uniform sampler2D lightingMap; + + +struct DeferredTransform { + mat4 projection; + mat4 viewInverse; + float stereoSide; + vec3 _spareABC; +}; + +layout(std140) uniform deferredTransformBuffer { + DeferredTransform _deferredTransform; +}; +DeferredTransform getDeferredTransform() { + return _deferredTransform; +} + +bool getStereoMode(DeferredTransform deferredTransform) { + return (deferredTransform.stereoSide != 0.0); +} +float getStereoSide(DeferredTransform deferredTransform) { + return (deferredTransform.stereoSide); +} + +vec4 evalEyePositionFromZ(DeferredTransform deferredTransform, float depthVal, vec2 texcoord) { + vec3 nPos = vec3(texcoord.xy * 2.0f - 1.0f, depthVal * 2.0f - 1.0f); + + // compute the view space position using the depth + // basically manually pick the proj matrix components to do the inverse + float Ze = -deferredTransform.projection[3][2] / (nPos.z + deferredTransform.projection[2][2]); + float Xe = (-Ze * nPos.x - Ze * deferredTransform.projection[2][0] - deferredTransform.projection[3][0]) / deferredTransform.projection[0][0]; + float Ye = (-Ze * nPos.y - Ze * deferredTransform.projection[2][1] - deferredTransform.projection[3][1]) / deferredTransform.projection[1][1]; + return vec4(Xe, Ye, Ze, 1.0f); +} + +struct DeferredFragment { + vec4 normalVal; + vec4 diffuseVal; + vec4 specularVal; + vec4 position; + vec3 normal; + float metallic; + vec3 diffuse; + float obscurance; + vec3 specular; + float roughness; + vec3 emissive; + int mode; + float depthVal; +}; + +vec4 unpackDeferredPosition(DeferredTransform deferredTransform, float depthValue, vec2 texcoord) { + if (getStereoMode(deferredTransform)) { + if (texcoord.x > 0.5) { + texcoord.x -= 0.5; + } + texcoord.x *= 2.0; + } + return evalEyePositionFromZ(deferredTransform, depthValue, texcoord); +} + +DeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) { + + DeferredFragment frag; + frag.depthVal = -1; + frag.normalVal = texture(normalMap, texcoord); + frag.diffuseVal = texture(albedoMap, texcoord); + frag.specularVal = texture(specularMap, texcoord); + frag.obscurance = texture(obscuranceMap, texcoord).x; + + // Unpack the normal from the map + frag.normal = normalize(frag.normalVal.xyz * 2.0 - vec3(1.0)); + frag.roughness = 2.0 * frag.normalVal.a; + + // Diffuse color and unpack the mode and the metallicness + frag.diffuse = frag.diffuseVal.xyz; + unpackModeMetallic(frag.diffuseVal.w, frag.mode, frag.metallic); + + + if (frag.metallic <= 0.5) { + frag.metallic = 0.0; + frag.specular = vec3(0.03); // Default Di-electric fresnel value + } else { + frag.specular = vec3(frag.diffuseVal.xyz); + frag.metallic = 1.0; + } + + frag.emissive = frag.specularVal.xyz; + frag.obscurance = min(frag.specularVal.w, frag.obscurance); + + return frag; +} + +DeferredFragment unpackDeferredFragment(DeferredTransform deferredTransform, vec2 texcoord) { + + float depthValue = texture(depthMap, texcoord).r; + + DeferredFragment frag = unpackDeferredFragmentNoPosition(texcoord); + + frag.depthVal = depthValue; + frag.position = unpackDeferredPosition(deferredTransform, frag.depthVal, texcoord); + + return frag; +} + + + + +<@endif@> diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh index 24a2f0d8a5..2be38fbea3 100755 --- a/libraries/render-utils/src/DeferredBufferWrite.slh +++ b/libraries/render-utils/src/DeferredBufferWrite.slh @@ -11,6 +11,8 @@ <@if not DEFERRED_BUFFER_WRITE_SLH@> <@def DEFERRED_BUFFER_WRITE_SLH@> +<@include DeferredBuffer.slh@> + layout(location = 0) out vec4 _fragColor0; layout(location = 1) out vec4 _fragColor1; layout(location = 2) out vec4 _fragColor2; @@ -48,13 +50,12 @@ const vec3 DEFAULT_EMISSIVE = vec3(0.0); const float DEFAULT_OCCLUSION = 1.0; const vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE; - void packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion) { if (alpha != 1.0) { discard; } - _fragColor0 = vec4(albedo, metallic); - _fragColor1 = vec4(bestFitNormal(normal), 0.5 * clamp(roughness, 0.0, 1.0)); + _fragColor0 = vec4(albedo, packShadedMetallic(metallic)); + _fragColor1 = vec4(bestFitNormal(normal), clamp(roughness, 0.0, 1.0)); _fragColor2 = vec4(emissive, occlusion); } @@ -63,19 +64,25 @@ void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float r if (alpha != 1.0) { discard; } - _fragColor0 = vec4(albedo, metallic); - _fragColor1 = vec4(bestFitNormal(normal), 0.5 + 0.5 * clamp(roughness, 0.0, 1.0)); + _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic)); + _fragColor1 = vec4(bestFitNormal(normal), clamp(roughness, 0.0, 1.0)); _fragColor2 = vec4(emissive, 1.0); } +void packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) { + if (alpha != 1.0) { + discard; + } + _fragColor0 = vec4(color, packUnlit()); + _fragColor1 = vec4(bestFitNormal(normal), 1.0); + //_fragColor2 = vec4(vec3(0.0), 1.0); // If unlit, do not worry about the emissive color target +} + void packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) { if (alpha <= 0.0) { discard; - } - + } _fragColor0 = vec4(albedo.rgb, alpha); - // _fragColor1 = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); - // _fragColor2 = vec4(fresnel, roughness); } <@endif@> diff --git a/libraries/render-utils/src/FramebufferCache.cpp b/libraries/render-utils/src/FramebufferCache.cpp index 22bfbfd869..3223ee5535 100644 --- a/libraries/render-utils/src/FramebufferCache.cpp +++ b/libraries/render-utils/src/FramebufferCache.cpp @@ -59,7 +59,8 @@ void FramebufferCache::createPrimaryFramebuffer() { _deferredFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); _deferredFramebufferDepthColor = gpu::FramebufferPointer(gpu::Framebuffer::create()); - auto colorFormat = gpu::Element::COLOR_RGBA_32; + // auto colorFormat = gpu::Element::COLOR_RGBA_32; + auto colorFormat = gpu::Element::COLOR_SRGBA_32; auto width = _frameBufferSize.width(); auto height = _frameBufferSize.height(); @@ -95,10 +96,7 @@ void FramebufferCache::createPrimaryFramebuffer() { auto smoothSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR); - // FIXME: Decide on the proper one, let s stick to R11G11B10 for now - //_lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, width, height, defaultSampler)); _lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::R11G11B10), width, height, defaultSampler)); - //_lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC4, gpu::HALF, gpu::RGBA), width, height, defaultSampler)); _lightingFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); _lightingFramebuffer->setRenderBuffer(0, _lightingTexture); _lightingFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); @@ -212,7 +210,7 @@ gpu::TexturePointer FramebufferCache::getLightingTexture() { gpu::FramebufferPointer FramebufferCache::getFramebuffer() { if (_cachedFramebuffers.isEmpty()) { - _cachedFramebuffers.push_back(gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, _frameBufferSize.width(), _frameBufferSize.height()))); + _cachedFramebuffers.push_back(gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_SRGBA_32, _frameBufferSize.width(), _frameBufferSize.height()))); } gpu::FramebufferPointer result = _cachedFramebuffers.front(); _cachedFramebuffers.pop_front(); diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 550baa6946..15bf44744c 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -31,7 +31,7 @@ #include "simple_vert.h" #include "simple_textured_frag.h" -#include "simple_textured_emisive_frag.h" +#include "simple_textured_unlit_frag.h" #include "grid_frag.h" @@ -1687,7 +1687,7 @@ public: enum FlagBit { IS_TEXTURED_FLAG = 0, IS_CULLED_FLAG, - IS_EMISSIVE_FLAG, + IS_UNLIT_FLAG, HAS_DEPTH_BIAS_FLAG, NUM_FLAGS, @@ -1696,7 +1696,7 @@ public: enum Flag { IS_TEXTURED = (1 << IS_TEXTURED_FLAG), IS_CULLED = (1 << IS_CULLED_FLAG), - IS_EMISSIVE = (1 << IS_EMISSIVE_FLAG), + IS_UNLIT = (1 << IS_UNLIT_FLAG), HAS_DEPTH_BIAS = (1 << HAS_DEPTH_BIAS_FLAG), }; typedef unsigned short Flags; @@ -1705,7 +1705,7 @@ public: bool isTextured() const { return isFlag(IS_TEXTURED); } bool isCulled() const { return isFlag(IS_CULLED); } - bool isEmissive() const { return isFlag(IS_EMISSIVE); } + bool isUnlit() const { return isFlag(IS_UNLIT); } bool hasDepthBias() const { return isFlag(HAS_DEPTH_BIAS); } Flags _flags = 0; @@ -1715,9 +1715,9 @@ public: SimpleProgramKey(bool textured = false, bool culled = true, - bool emissive = false, bool depthBias = false) { + bool unlit = false, bool depthBias = false) { _flags = (textured ? IS_TEXTURED : 0) | (culled ? IS_CULLED : 0) | - (emissive ? IS_EMISSIVE : 0) | (depthBias ? HAS_DEPTH_BIAS : 0); + (unlit ? IS_UNLIT : 0) | (depthBias ? HAS_DEPTH_BIAS : 0); } SimpleProgramKey(int bitmask) : _flags(bitmask) {} @@ -1731,8 +1731,8 @@ inline bool operator==(const SimpleProgramKey& a, const SimpleProgramKey& b) { return a.getRaw() == b.getRaw(); } -void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool culled, bool emissive, bool depthBiased) { - batch.setPipeline(getSimplePipeline(textured, culled, emissive, depthBiased)); +void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool culled, bool unlit, bool depthBiased) { + batch.setPipeline(getSimplePipeline(textured, culled, unlit, depthBiased)); // If not textured, set a default albedo map if (!textured) { @@ -1744,23 +1744,23 @@ void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool cul DependencyManager::get()->getNormalFittingTexture()); } -gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool culled, bool emissive, bool depthBiased) { - SimpleProgramKey config{textured, culled, emissive, depthBiased}; +gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool culled, bool unlit, bool depthBiased) { + SimpleProgramKey config{ textured, culled, unlit, depthBiased }; // Compile the shaders static std::once_flag once; std::call_once(once, [&]() { auto VS = gpu::Shader::createVertex(std::string(simple_vert)); auto PS = gpu::Shader::createPixel(std::string(simple_textured_frag)); - auto PSEmissive = gpu::Shader::createPixel(std::string(simple_textured_emisive_frag)); + auto PSUnlit = gpu::Shader::createPixel(std::string(simple_textured_unlit_frag)); _simpleShader = gpu::Shader::createProgram(VS, PS); - _emissiveShader = gpu::Shader::createProgram(VS, PSEmissive); + _unlitShader = gpu::Shader::createProgram(VS, PSUnlit); gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), render::ShapePipeline::Slot::MAP::NORMAL_FITTING)); gpu::Shader::makeProgram(*_simpleShader, slotBindings); - gpu::Shader::makeProgram(*_emissiveShader, slotBindings); + gpu::Shader::makeProgram(*_unlitShader, slotBindings); }); // If the pipeline already exists, return it @@ -1785,7 +1785,7 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool culled gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); - gpu::ShaderPointer program = (config.isEmissive()) ? _emissiveShader : _simpleShader; + gpu::ShaderPointer program = (config.isUnlit()) ? _unlitShader : _simpleShader; gpu::PipelinePointer pipeline = gpu::Pipeline::create(program, state); _simplePrograms.insert(config, pipeline); return pipeline; diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index b69ebf8531..c4531aa102 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -153,10 +153,10 @@ public: // Bind the pipeline and get the state to render static geometry void bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool culled = true, - bool emissive = false, bool depthBias = false); + bool unlit = false, bool depthBias = false); // Get the pipeline to render static geometry gpu::PipelinePointer getSimplePipeline(bool textured = false, bool culled = true, - bool emissive = false, bool depthBias = false); + bool unlit = false, bool depthBias = false); render::ShapePipelinePointer getShapePipeline() { return GeometryCache::_simplePipeline; } // Static (instanced) geometry @@ -393,7 +393,7 @@ private: QHash > _networkGeometry; gpu::ShaderPointer _simpleShader; - gpu::ShaderPointer _emissiveShader; + gpu::ShaderPointer _unlitShader; static render::ShapePipelinePointer _simplePipeline; QHash _simplePrograms; }; diff --git a/libraries/render-utils/src/MaterialTextures.slh b/libraries/render-utils/src/MaterialTextures.slh index 512b7a533c..f9b1c76104 100644 --- a/libraries/render-utils/src/MaterialTextures.slh +++ b/libraries/render-utils/src/MaterialTextures.slh @@ -157,7 +157,7 @@ vec3 fetchLightmapMap(vec2 uv) { } <@endfunc@> -<@func $discardTransparent(opacity)@> +<@func discardTransparent(opacity)@> { if (<$opacity$> < 1.0) { discard; diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 03c1ac9eda..08c8dc23b4 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -144,6 +144,11 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat auto materialKey = _drawMaterial->getKey(); auto textureMaps = _drawMaterial->getTextureMaps(); + int numUnlit = 0; + if (materialKey.isUnlit()) { + numUnlit++; + } + // Albedo if (materialKey.isAlbedoMap()) { auto albedoMap = textureMaps[model::MaterialKey::ALBEDO_MAP]; @@ -414,6 +419,7 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { bool hasTangents = drawMaterialKey.isNormalMap() && !mesh.tangents.isEmpty(); bool hasSpecular = drawMaterialKey.isMetallicMap(); bool hasLightmap = drawMaterialKey.isLightmapMap(); + bool isUnlit = drawMaterialKey.isUnlit(); bool isSkinned = _isSkinned; bool wireframe = _model->isWireframe(); @@ -435,6 +441,9 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { if (hasLightmap) { builder.withLightmap(); } + if (isUnlit) { + builder.withUnlit(); + } if (isSkinned) { builder.withSkinned(); } diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index ada5a66c39..16681fd363 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -27,7 +27,7 @@ #include "skin_model_normal_map_vert.h" #include "model_frag.h" -#include "model_emissive_frag.h" +#include "model_unlit_frag.h" #include "model_shadow_frag.h" #include "model_normal_map_frag.h" #include "model_normal_specular_map_frag.h" @@ -37,13 +37,13 @@ #include "model_lightmap_normal_specular_map_frag.h" #include "model_lightmap_specular_map_frag.h" #include "model_translucent_frag.h" -#include "model_translucent_emissive_frag.h" +#include "model_translucent_unlit_frag.h" #include "overlay3D_vert.h" #include "overlay3D_frag.h" #include "overlay3D_translucent_frag.h" -#include "overlay3D_emissive_frag.h" -#include "overlay3D_translucent_emissive_frag.h" +#include "overlay3D_unlit_frag.h" +#include "overlay3D_translucent_unlit_frag.h" #include "drawOpaqueStencil_frag.h" @@ -102,13 +102,13 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { auto vertex = gpu::Shader::createVertex(std::string(overlay3D_vert)); auto pixel = gpu::Shader::createPixel(std::string(overlay3D_frag)); auto pixelTranslucent = gpu::Shader::createPixel(std::string(overlay3D_translucent_frag)); - auto pixelEmissive = gpu::Shader::createPixel(std::string(overlay3D_emissive_frag)); - auto pixelTranslucentEmissive = gpu::Shader::createPixel(std::string(overlay3D_translucent_emissive_frag)); + auto pixelUnlit = gpu::Shader::createPixel(std::string(overlay3D_unlit_frag)); + auto pixelTranslucentUnlit = gpu::Shader::createPixel(std::string(overlay3D_translucent_unlit_frag)); auto opaqueProgram = gpu::Shader::createProgram(vertex, pixel); auto translucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucent); - auto emissiveOpaqueProgram = gpu::Shader::createProgram(vertex, pixelEmissive); - auto emissiveTranslucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucentEmissive); + auto unlitOpaqueProgram = gpu::Shader::createProgram(vertex, pixelUnlit); + auto unlitTranslucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucentUnlit); for (int i = 0; i < 8; i++) { bool isCulled = (i & 1); @@ -138,9 +138,9 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { isOpaque ? builder.withOpaque() : builder.withTranslucent(); auto simpleProgram = isOpaque ? opaqueProgram : translucentProgram; - auto emissiveProgram = isOpaque ? emissiveOpaqueProgram : emissiveTranslucentProgram; - plumber.addPipeline(builder.withoutEmissive().build(), simpleProgram, state, &lightBatchSetter); - plumber.addPipeline(builder.withEmissive().build(), emissiveProgram, state, &batchSetter); + auto unlitProgram = isOpaque ? unlitOpaqueProgram : unlitTranslucentProgram; + plumber.addPipeline(builder.withoutUnlit().build(), simpleProgram, state, &lightBatchSetter); + plumber.addPipeline(builder.withUnlit().build(), unlitProgram, state, &batchSetter); } } @@ -201,12 +201,12 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { // Pixel shaders auto modelPixel = gpu::Shader::createPixel(std::string(model_frag)); - auto modelEmissivePixel = gpu::Shader::createPixel(std::string(model_emissive_frag)); + auto modelUnlitPixel = gpu::Shader::createPixel(std::string(model_unlit_frag)); auto modelNormalMapPixel = gpu::Shader::createPixel(std::string(model_normal_map_frag)); auto modelSpecularMapPixel = gpu::Shader::createPixel(std::string(model_specular_map_frag)); auto modelNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_normal_specular_map_frag)); auto modelTranslucentPixel = gpu::Shader::createPixel(std::string(model_translucent_frag)); - auto modelTranslucentEmissivePixel = gpu::Shader::createPixel(std::string(model_translucent_emissive_frag)); + auto modelTranslucentUnlitPixel = gpu::Shader::createPixel(std::string(model_translucent_unlit_frag)); auto modelShadowPixel = gpu::Shader::createPixel(std::string(model_shadow_frag)); auto modelLightmapPixel = gpu::Shader::createPixel(std::string(model_lightmap_frag)); auto modelLightmapNormalMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_map_frag)); @@ -219,8 +219,8 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { Key::Builder(), modelVertex, modelPixel); addPipeline( - Key::Builder().withEmissive(), - modelVertex, modelEmissivePixel); + Key::Builder().withUnlit(), + modelVertex, modelUnlitPixel); addPipeline( Key::Builder().withTangents(), modelNormalMapVertex, modelNormalMapPixel); @@ -235,8 +235,8 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { Key::Builder().withTranslucent(), modelVertex, modelTranslucentPixel); addPipeline( - Key::Builder().withTranslucent().withEmissive(), - modelVertex, modelTranslucentEmissivePixel); + Key::Builder().withTranslucent().withUnlit(), + modelVertex, modelTranslucentUnlitPixel); addPipeline( Key::Builder().withTranslucent().withTangents(), modelNormalMapVertex, modelTranslucentPixel); @@ -296,4 +296,5 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { addPipeline( Key::Builder().withSkinned().withDepthOnly(), skinModelShadowVertex, modelShadowPixel); + } diff --git a/libraries/render-utils/src/debug_deferred_buffer.slf b/libraries/render-utils/src/debug_deferred_buffer.slf index bbc50fa97a..b323836657 100644 --- a/libraries/render-utils/src/debug_deferred_buffer.slf +++ b/libraries/render-utils/src/debug_deferred_buffer.slf @@ -12,7 +12,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include DeferredBuffer.slh@> +<@include DeferredBufferRead.slh@> uniform sampler2D pyramidMap; uniform sampler2D occlusionMap; diff --git a/libraries/render-utils/src/directional_ambient_light.slf b/libraries/render-utils/src/directional_ambient_light.slf index e1ec0d3ef0..2ee818fdba 100755 --- a/libraries/render-utils/src/directional_ambient_light.slf +++ b/libraries/render-utils/src/directional_ambient_light.slf @@ -12,7 +12,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include DeferredBuffer.slh@> +<@include DeferredBufferRead.slh@> <@include DeferredGlobalLight.slh@> <$declareEvalLightmappedColor()$> @@ -27,7 +27,9 @@ void main(void) { float shadowAttenuation = 1.0; - if (frag.mode == LIGHT_MAPPED) { + if (frag.mode == FRAG_MODE_UNLIT) { + _fragColor = vec4(frag.diffuse, 1.0); + } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) { vec3 color = evalLightmappedColor( deferredTransform.viewInverse, shadowAttenuation, diff --git a/libraries/render-utils/src/directional_ambient_light_shadow.slf b/libraries/render-utils/src/directional_ambient_light_shadow.slf index 963a10d579..20ceea9379 100644 --- a/libraries/render-utils/src/directional_ambient_light_shadow.slf +++ b/libraries/render-utils/src/directional_ambient_light_shadow.slf @@ -13,7 +13,7 @@ // <@include Shadow.slh@> -<@include DeferredBuffer.slh@> +<@include DeferredBufferRead.slh@> <@include DeferredGlobalLight.slh@> <$declareEvalLightmappedColor()$> @@ -29,7 +29,9 @@ void main(void) { vec4 worldPos = deferredTransform.viewInverse * vec4(frag.position.xyz, 1.0); float shadowAttenuation = evalShadowAttenuation(worldPos); - if (frag.mode == LIGHT_MAPPED) { + if (frag.mode == FRAG_MODE_UNLIT) { + _fragColor = vec4(frag.diffuse, 1.0); + } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) { vec3 color = evalLightmappedColor( deferredTransform.viewInverse, shadowAttenuation, diff --git a/libraries/render-utils/src/directional_light.slf b/libraries/render-utils/src/directional_light.slf index 1a739f9389..ef61e9a030 100644 --- a/libraries/render-utils/src/directional_light.slf +++ b/libraries/render-utils/src/directional_light.slf @@ -12,7 +12,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include DeferredBuffer.slh@> +<@include DeferredBufferRead.slh@> <@include DeferredGlobalLight.slh@> <$declareEvalLightmappedColor()$> @@ -28,7 +28,9 @@ void main(void) { float shadowAttenuation = 1.0; // Light mapped or not ? - if (frag.mode == LIGHT_MAPPED) { + if (frag.mode == FRAG_MODE_UNLIT) { + _fragColor = vec4(frag.diffuse, 1.0); + } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) { vec3 color = evalLightmappedColor( deferredTransform.viewInverse, shadowAttenuation, diff --git a/libraries/render-utils/src/directional_light_shadow.slf b/libraries/render-utils/src/directional_light_shadow.slf index 3b9b4d22c6..5b09d47e80 100644 --- a/libraries/render-utils/src/directional_light_shadow.slf +++ b/libraries/render-utils/src/directional_light_shadow.slf @@ -13,7 +13,7 @@ // <@include Shadow.slh@> -<@include DeferredBuffer.slh@> +<@include DeferredBufferRead.slh@> <@include DeferredGlobalLight.slh@> <$declareEvalLightmappedColor()$> @@ -30,7 +30,9 @@ void main(void) { float shadowAttenuation = evalShadowAttenuation(worldPos); // Light mapped or not ? - if (frag.mode == LIGHT_MAPPED) { + if (frag.mode == FRAG_MODE_UNLIT) { + _fragColor = vec4(frag.diffuse, 1.0); + } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) { vec3 color = evalLightmappedColor( deferredTransform.viewInverse, shadowAttenuation, diff --git a/libraries/render-utils/src/directional_skybox_light.slf b/libraries/render-utils/src/directional_skybox_light.slf index 9e24a5f585..f0c7bb476f 100755 --- a/libraries/render-utils/src/directional_skybox_light.slf +++ b/libraries/render-utils/src/directional_skybox_light.slf @@ -12,7 +12,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include DeferredBuffer.slh@> +<@include DeferredBufferRead.slh@> <@include DeferredGlobalLight.slh@> <$declareEvalLightmappedColor()$> @@ -28,7 +28,9 @@ void main(void) { float shadowAttenuation = 1.0; // Light mapped or not ? - if (frag.mode == LIGHT_MAPPED) { + if (frag.mode == FRAG_MODE_UNLIT) { + _fragColor = vec4(frag.diffuse, 1.0); + } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) { vec3 color = evalLightmappedColor( deferredTransform.viewInverse, shadowAttenuation, diff --git a/libraries/render-utils/src/directional_skybox_light_shadow.slf b/libraries/render-utils/src/directional_skybox_light_shadow.slf index c3008b5509..6a233e5985 100644 --- a/libraries/render-utils/src/directional_skybox_light_shadow.slf +++ b/libraries/render-utils/src/directional_skybox_light_shadow.slf @@ -13,7 +13,7 @@ //!> <@include Shadow.slh@> -<@include DeferredBuffer.slh@> +<@include DeferredBufferRead.slh@> <@include DeferredGlobalLight.slh@> <$declareEvalLightmappedColor()$> @@ -30,7 +30,9 @@ void main(void) { float shadowAttenuation = evalShadowAttenuation(worldPos); // Light mapped or not ? - if (frag.mode == LIGHT_MAPPED) { + if (frag.mode == FRAG_MODE_UNLIT) { + _fragColor = vec4(frag.diffuse, 1.0); + } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) { vec3 color = evalLightmappedColor( deferredTransform.viewInverse, shadowAttenuation, diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf index ddfd83d1d4..f1dcc942c9 100755 --- a/libraries/render-utils/src/model.slf +++ b/libraries/render-utils/src/model.slf @@ -30,7 +30,7 @@ void main(void) { <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex, occlusionTex)$> float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; <$discardTransparent(opacity)$>; vec3 albedo = getMaterialAlbedo(mat); diff --git a/libraries/render-utils/src/model_emissive.slf b/libraries/render-utils/src/model_emissive.slf deleted file mode 100644 index 471e613eb4..0000000000 --- a/libraries/render-utils/src/model_emissive.slf +++ /dev/null @@ -1,39 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// model_emissive.frag -// fragment shader -// -// Created by Zach Pomerantz on 2/3/2016. -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DeferredBufferWrite.slh@> -<@include model/Material.slh@> - -uniform sampler2D albedoMap; - -in vec2 _texCoord0; -in vec3 _normal; -in vec3 _color; -in float _alpha; - -void main(void) { - vec4 texel = texture(albedoMap, _texCoord0); - - Material mat = getMaterial(); - vec3 fragColor = getMaterialAlbedo(mat) * texel.rgb * _color; - - packDeferredFragmentLightmap( - normalize(_normal), - texel.a, - vec3(1.0), - getMaterialRoughness(mat), - getMaterialMetallic(mat), - getMaterialFresnel(mat), - fragColor); -} diff --git a/libraries/render-utils/src/model_normal_map.slf b/libraries/render-utils/src/model_normal_map.slf index 10ae6ee880..519b41e17f 100755 --- a/libraries/render-utils/src/model_normal_map.slf +++ b/libraries/render-utils/src/model_normal_map.slf @@ -31,7 +31,7 @@ void main(void) { <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, _SCRIBE_NULL, emissiveTex, occlusionTex)$> float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; <$discardTransparent(opacity)$>; vec3 albedo = getMaterialAlbedo(mat); diff --git a/libraries/render-utils/src/model_specular_map.slf b/libraries/render-utils/src/model_specular_map.slf index 9b2f4ae640..3cbb060ab5 100755 --- a/libraries/render-utils/src/model_specular_map.slf +++ b/libraries/render-utils/src/model_specular_map.slf @@ -31,7 +31,7 @@ void main(void) { <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex, occlusionTex)$> float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; <$discardTransparent(opacity)$>; vec3 albedo = getMaterialAlbedo(mat); diff --git a/libraries/render-utils/src/model_translucent.slf b/libraries/render-utils/src/model_translucent.slf index 1a807c5703..27a22a9763 100755 --- a/libraries/render-utils/src/model_translucent.slf +++ b/libraries/render-utils/src/model_translucent.slf @@ -38,8 +38,7 @@ void main(void) { <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex, occlusionTex)$> float opacity = getMaterialOpacity(mat) * _alpha; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>; - <$discardTransparent(opacity)$>; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; vec3 albedo = getMaterialAlbedo(mat); <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; diff --git a/libraries/render-utils/src/model_translucent_emissive.slf b/libraries/render-utils/src/model_translucent_emissive.slf deleted file mode 100644 index 82faf7cf45..0000000000 --- a/libraries/render-utils/src/model_translucent_emissive.slf +++ /dev/null @@ -1,33 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// model_translucent_emissive.frag -// fragment shader -// -// Created by Zach Pomerantz on 2/3/2016. -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include model/Material.slh@> - -uniform sampler2D albedoMap; - -in vec2 _texCoord0; -in vec3 _color; -in float _alpha; - -out vec4 _fragColor; - -void main(void) { - vec4 albedo = texture(albedoMap, _texCoord0); - - Material mat = getMaterial(); - vec3 fragColor = getMaterialAlbedo(mat) * albedo.rgb * _color; - float fragOpacity = getMaterialOpacity(mat) * albedo.a * _alpha; - - _fragColor = vec4(fragColor, fragOpacity); -} diff --git a/libraries/render-utils/src/model_translucent_unlit.slf b/libraries/render-utils/src/model_translucent_unlit.slf new file mode 100644 index 0000000000..b9d6c64d6f --- /dev/null +++ b/libraries/render-utils/src/model_translucent_unlit.slf @@ -0,0 +1,39 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_translucent_unlit.frag +// fragment shader +// +// Created by Zach Pomerantz on 2/3/2016. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +<@include model/Material.slh@> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$> + +in vec2 _texCoord0; +in vec3 _color; +in float _alpha; + +out vec4 _fragColor; + +void main(void) { + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL)$> + + float opacity = getMaterialOpacity(mat) * _alpha; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + _fragColor = vec4(albedo, opacity); +} diff --git a/libraries/render-utils/src/model_unlit.slf b/libraries/render-utils/src/model_unlit.slf new file mode 100644 index 0000000000..50778153fb --- /dev/null +++ b/libraries/render-utils/src/model_unlit.slf @@ -0,0 +1,44 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// material_opaque_unlit.frag +// fragment shader +// +// Created by Sam Gateau on 5/5/2016. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +<@include DeferredBufferWrite.slh@> +<@include model/Material.slh@> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL)$> + +in vec2 _texCoord0; +in vec3 _normal; +in vec3 _color; +in float _alpha; + +void main(void) { + + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL)$> + + float opacity = 1.0; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + <$discardTransparent(opacity)$>; + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + packDeferredFragmentUnlit( + normalize(_normal), + opacity, + albedo); +} diff --git a/libraries/render-utils/src/overlay3D.slf b/libraries/render-utils/src/overlay3D.slf index 38199a7a82..38f236e0b3 100644 --- a/libraries/render-utils/src/overlay3D.slf +++ b/libraries/render-utils/src/overlay3D.slf @@ -71,6 +71,7 @@ void main(void) { fragRoughness, fragOpacity); + // Apply standard tone mapping _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); } diff --git a/libraries/render-utils/src/overlay3D_translucent_emissive.slf b/libraries/render-utils/src/overlay3D_translucent_unlit.slf similarity index 93% rename from libraries/render-utils/src/overlay3D_translucent_emissive.slf rename to libraries/render-utils/src/overlay3D_translucent_unlit.slf index 61935f3c67..18a26d0790 100644 --- a/libraries/render-utils/src/overlay3D_translucent_emissive.slf +++ b/libraries/render-utils/src/overlay3D_translucent_unlit.slf @@ -2,7 +2,7 @@ <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // -// overlay3D_translucent_emissive.frag +// overlay3D_translucent_unlit.frag // fragment shader // // Created by Zach Pomerantz on 2/2/2016. diff --git a/libraries/render-utils/src/overlay3D_emissive.slf b/libraries/render-utils/src/overlay3D_unlit.slf similarity index 96% rename from libraries/render-utils/src/overlay3D_emissive.slf rename to libraries/render-utils/src/overlay3D_unlit.slf index 727eb0f317..42e51bdc25 100644 --- a/libraries/render-utils/src/overlay3D_emissive.slf +++ b/libraries/render-utils/src/overlay3D_unlit.slf @@ -2,7 +2,7 @@ <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // -// overlay3D_emissive.frag +// overlay3D_unlit.frag // fragment shader // // Created by Zach Pomerantz on 2/2/2016. diff --git a/libraries/render-utils/src/point_light.slf b/libraries/render-utils/src/point_light.slf index 0cadf3a760..fc72f094e7 100644 --- a/libraries/render-utils/src/point_light.slf +++ b/libraries/render-utils/src/point_light.slf @@ -13,7 +13,7 @@ // // Everything about deferred buffer -<@include DeferredBuffer.slh@> +<@include DeferredBufferRead.slh@> //Everything about deferred lighting <@include DeferredLighting.slh@> @@ -32,6 +32,10 @@ void main(void) { vec2 texCoord = _texCoord0.st / _texCoord0.q; DeferredFragment frag = unpackDeferredFragment(deferredTransform, texCoord); + if (frag.mode == FRAG_MODE_UNLIT) { + discard; + } + mat4 invViewMat = deferredTransform.viewInverse; // Kill if in front of the light volume diff --git a/libraries/render-utils/src/simple.slf b/libraries/render-utils/src/simple.slf index 5ad9dc174f..0f848ee231 100644 --- a/libraries/render-utils/src/simple.slf +++ b/libraries/render-utils/src/simple.slf @@ -18,7 +18,7 @@ // the interpolated normal in vec3 _normal; in vec3 _modelNormal; -in vec3 _color; +in vec4 _color; in vec2 _texCoord0; in vec4 _position; diff --git a/libraries/render-utils/src/simple.slv b/libraries/render-utils/src/simple.slv index 46127d6752..d56d1cc8e2 100644 --- a/libraries/render-utils/src/simple.slv +++ b/libraries/render-utils/src/simple.slv @@ -20,12 +20,12 @@ // the interpolated normal out vec3 _normal; out vec3 _modelNormal; -out vec3 _color; +out vec4 _color; out vec2 _texCoord0; out vec4 _position; void main(void) { - _color = colorToLinearRGB(inColor.rgb); + _color = colorToLinearRGBA(inColor); _texCoord0 = inTexCoord0.st; _position = inPosition; _modelNormal = inNormal.xyz; diff --git a/libraries/render-utils/src/simple_textured.slf b/libraries/render-utils/src/simple_textured.slf index 0832b22214..062fb96f7d 100644 --- a/libraries/render-utils/src/simple_textured.slf +++ b/libraries/render-utils/src/simple_textured.slf @@ -12,6 +12,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Color.slh@> <@include DeferredBufferWrite.slh@> <@include model/Material.slh@> @@ -20,13 +21,14 @@ uniform sampler2D originalTexture; // the interpolated normal in vec3 _normal; -in vec3 _color; +in vec4 _color; in vec2 _texCoord0; void main(void) { - Material material = getMaterial(); vec4 texel = texture(originalTexture, _texCoord0); - + if (_color.a <= 0.0) { + texel = colorToLinearRGBA(texel); + } packDeferredFragment( normalize(_normal.xyz), texel.a, diff --git a/libraries/render-utils/src/simple_textured_emisive.slf b/libraries/render-utils/src/simple_textured_unlit.slf similarity index 77% rename from libraries/render-utils/src/simple_textured_emisive.slf rename to libraries/render-utils/src/simple_textured_unlit.slf index 92bdee8d02..cbfc7d7768 100644 --- a/libraries/render-utils/src/simple_textured_emisive.slf +++ b/libraries/render-utils/src/simple_textured_unlit.slf @@ -12,6 +12,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Color.slh@> <@include DeferredBufferWrite.slh@> // the albedo texture @@ -19,18 +20,17 @@ uniform sampler2D originalTexture; // the interpolated normal in vec3 _normal; -in vec3 _color; +in vec4 _color; in vec2 _texCoord0; void main(void) { vec4 texel = texture(originalTexture, _texCoord0.st); - - packDeferredFragmentLightmap( + if (_color.a <= 0.0) { + texel = colorToLinearRGBA(texel); + } + + packDeferredFragmentUnlit( normalize(_normal), texel.a, - _color.rgb, - DEFAULT_ROUGHNESS, - DEFAULT_METALLIC, - DEFAULT_SPECULAR, - texel.rgb); + _color.rgb * texel.rgb); } \ No newline at end of file diff --git a/libraries/render-utils/src/spot_light.slf b/libraries/render-utils/src/spot_light.slf index 8355dcf91b..4191ba3f63 100644 --- a/libraries/render-utils/src/spot_light.slf +++ b/libraries/render-utils/src/spot_light.slf @@ -13,7 +13,7 @@ // // Everything about deferred buffer -<@include DeferredBuffer.slh@> +<@include DeferredBufferRead.slh@> //Everything about deferred lighting <@include DeferredLighting.slh@> @@ -32,6 +32,10 @@ void main(void) { vec2 texCoord = _texCoord0.st / _texCoord0.q; DeferredFragment frag = unpackDeferredFragment(deferredTransform, texCoord); + if (frag.mode == FRAG_MODE_UNLIT) { + discard; + } + mat4 invViewMat = deferredTransform.viewInverse; // Kill if in front of the light volume diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp index c2724fce42..bfbd123382 100644 --- a/libraries/render/src/render/DrawStatus.cpp +++ b/libraries/render/src/render/DrawStatus.cpp @@ -116,35 +116,25 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, // FIrst thing, we collect the bound and the status for all the items we want to render int nbItems = 0; { - if (!_itemBounds) { - _itemBounds = std::make_shared(); - } - if (!_itemStatus) { - _itemStatus = std::make_shared();; - } - if (!_itemCells) { - _itemCells = std::make_shared();; - } + _itemBounds.resize(inItems.size()); + _itemStatus.resize(inItems.size()); + _itemCells.resize(inItems.size()); - _itemBounds->resize((inItems.size() * sizeof(AABox))); - _itemStatus->resize((inItems.size() * NUM_STATUS_VEC4_PER_ITEM * sizeof(glm::vec4))); - _itemCells->resize((inItems.size() * sizeof(Octree::Location))); - - AABox* itemAABox = reinterpret_cast (_itemBounds->editData()); - glm::ivec4* itemStatus = reinterpret_cast (_itemStatus->editData()); - Octree::Location* itemCell = reinterpret_cast (_itemCells->editData()); - for (auto& item : inItems) { +// AABox* itemAABox = reinterpret_cast (_itemBounds->editData()); +// glm::ivec4* itemStatus = reinterpret_cast (_itemStatus->editData()); +// Octree::Location* itemCell = reinterpret_cast (_itemCells->editData()); + for (size_t i = 0; i < inItems.size(); ++i) { + const auto& item = inItems[i]; if (!item.bound.isInvalid()) { if (!item.bound.isNull()) { - (*itemAABox) = item.bound; + _itemBounds[i] = item.bound; } else { - (*itemAABox).setBox(item.bound.getCorner(), 0.1f); + _itemBounds[i].setBox(item.bound.getCorner(), 0.1f); } auto& itemScene = scene->getItem(item.id); - - (*itemCell) = scene->getSpatialTree().getCellLocation(itemScene.getCell()); + _itemCells[i] = scene->getSpatialTree().getCellLocation(itemScene.getCell()); auto itemStatusPointer = itemScene.getStatus(); if (itemStatusPointer) { @@ -152,25 +142,19 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, auto&& currentStatusValues = itemStatusPointer->getCurrentValues(); int valueNum = 0; for (int vec4Num = 0; vec4Num < NUM_STATUS_VEC4_PER_ITEM; vec4Num++) { - (*itemStatus) = glm::ivec4(Item::Status::Value::INVALID.getPackedData()); + auto& value = (vec4Num ? _itemStatus[i].first : _itemStatus[i].second); + value = glm::ivec4(Item::Status::Value::INVALID.getPackedData()); for (int component = 0; component < VEC4_LENGTH; component++) { valueNum = vec4Num * VEC4_LENGTH + component; if (valueNum < (int)currentStatusValues.size()) { - (*itemStatus)[component] = currentStatusValues[valueNum].getPackedData(); + value[component] = currentStatusValues[valueNum].getPackedData(); } } - itemStatus++; } } else { - (*itemStatus) = glm::ivec4(Item::Status::Value::INVALID.getPackedData()); - itemStatus++; - (*itemStatus) = glm::ivec4(Item::Status::Value::INVALID.getPackedData()); - itemStatus++; + _itemStatus[i].first = _itemStatus[i].second = glm::ivec4(Item::Status::Value::INVALID.getPackedData()); } - nbItems++; - itemAABox++; - itemCell++; } } } @@ -194,25 +178,20 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, // bind the one gpu::Pipeline we need batch.setPipeline(getDrawItemBoundsPipeline()); - AABox* itemAABox = reinterpret_cast (_itemBounds->editData()); - glm::ivec4* itemStatus = reinterpret_cast (_itemStatus->editData()); - Octree::Location* itemCell = reinterpret_cast (_itemCells->editData()); + //AABox* itemAABox = reinterpret_cast (_itemBounds->editData()); + //glm::ivec4* itemStatus = reinterpret_cast (_itemStatus->editData()); + //Octree::Location* itemCell = reinterpret_cast (_itemCells->editData()); const unsigned int VEC3_ADRESS_OFFSET = 3; if (_showDisplay) { for (int i = 0; i < nbItems; i++) { - batch._glUniform3fv(_drawItemBoundPosLoc, 1, (const float*) (itemAABox + i)); - batch._glUniform3fv(_drawItemBoundDimLoc, 1, ((const float*) (itemAABox + i)) + VEC3_ADRESS_OFFSET); - - - glm::ivec4 cellLocation(itemCell->pos.x, itemCell->pos.y, itemCell->pos.z, itemCell->depth); + batch._glUniform3fv(_drawItemBoundPosLoc, 1, (const float*)&(_itemBounds[i])); + batch._glUniform3fv(_drawItemBoundDimLoc, 1, ((const float*)&(_itemBounds[i])) + VEC3_ADRESS_OFFSET); + glm::ivec4 cellLocation(_itemCells[i].pos, _itemCells[i].depth); batch._glUniform4iv(_drawItemCellLocLoc, 1, ((const int*)(&cellLocation))); - - batch.draw(gpu::LINES, 24, 0); - itemCell++; } } @@ -222,10 +201,10 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, if (_showNetwork) { for (int i = 0; i < nbItems; i++) { - batch._glUniform3fv(_drawItemStatusPosLoc, 1, (const float*) (itemAABox + i)); - batch._glUniform3fv(_drawItemStatusDimLoc, 1, ((const float*) (itemAABox + i)) + VEC3_ADRESS_OFFSET); - batch._glUniform4iv(_drawItemStatusValue0Loc, 1, (const int*)(itemStatus + NUM_STATUS_VEC4_PER_ITEM * i)); - batch._glUniform4iv(_drawItemStatusValue1Loc, 1, (const int*)(itemStatus + NUM_STATUS_VEC4_PER_ITEM * i + 1)); + batch._glUniform3fv(_drawItemStatusPosLoc, 1, (const float*)&(_itemBounds[i])); + batch._glUniform3fv(_drawItemStatusDimLoc, 1, ((const float*)&(_itemBounds[i])) + VEC3_ADRESS_OFFSET); + batch._glUniform4iv(_drawItemStatusValue0Loc, 1, (const int*)&(_itemStatus[i].first)); + batch._glUniform4iv(_drawItemStatusValue1Loc, 1, (const int*)&(_itemStatus[i].second)); batch.draw(gpu::TRIANGLES, 24 * NUM_STATUS_VEC4_PER_ITEM, 0); } } diff --git a/libraries/render/src/render/DrawStatus.h b/libraries/render/src/render/DrawStatus.h index 839a98b373..e60cb58779 100644 --- a/libraries/render/src/render/DrawStatus.h +++ b/libraries/render/src/render/DrawStatus.h @@ -68,9 +68,13 @@ namespace render { gpu::Stream::FormatPointer _drawItemFormat; gpu::PipelinePointer _drawItemBoundsPipeline; gpu::PipelinePointer _drawItemStatusPipeline; - gpu::BufferPointer _itemBounds; - gpu::BufferPointer _itemCells; - gpu::BufferPointer _itemStatus; + + std::vector _itemBounds; + std::vector> _itemStatus; + std::vector _itemCells; + //gpu::BufferPointer _itemBounds; + //gpu::BufferPointer _itemCells; + //gpu::BufferPointer _itemStatus; gpu::TexturePointer _statusIconMap; }; } diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index aba4de6acf..bed3bd7c68 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -26,7 +26,7 @@ public: LIGHTMAP, TANGENTS, SPECULAR, - EMISSIVE, + UNLIT, SKINNED, STEREO, DEPTH_ONLY, @@ -57,7 +57,7 @@ public: Builder& withLightmap() { _flags.set(LIGHTMAP); return (*this); } Builder& withTangents() { _flags.set(TANGENTS); return (*this); } Builder& withSpecular() { _flags.set(SPECULAR); return (*this); } - Builder& withEmissive() { _flags.set(EMISSIVE); return (*this); } + Builder& withUnlit() { _flags.set(UNLIT); return (*this); } Builder& withSkinned() { _flags.set(SKINNED); return (*this); } Builder& withStereo() { _flags.set(STEREO); return (*this); } Builder& withDepthOnly() { _flags.set(DEPTH_ONLY); return (*this); } @@ -101,8 +101,8 @@ public: Builder& withSpecular() { _flags.set(SPECULAR); _mask.set(SPECULAR); return (*this); } Builder& withoutSpecular() { _flags.reset(SPECULAR); _mask.set(SPECULAR); return (*this); } - Builder& withEmissive() { _flags.set(EMISSIVE); _mask.set(EMISSIVE); return (*this); } - Builder& withoutEmissive() { _flags.reset(EMISSIVE); _mask.set(EMISSIVE); return (*this); } + Builder& withUnlit() { _flags.set(UNLIT); _mask.set(UNLIT); return (*this); } + Builder& withoutUnlit() { _flags.reset(UNLIT); _mask.set(UNLIT); return (*this); } Builder& withSkinned() { _flags.set(SKINNED); _mask.set(SKINNED); return (*this); } Builder& withoutSkinned() { _flags.reset(SKINNED); _mask.set(SKINNED); return (*this); } @@ -137,7 +137,7 @@ public: bool hasLightmap() const { return _flags[LIGHTMAP]; } bool hasTangents() const { return _flags[TANGENTS]; } bool hasSpecular() const { return _flags[SPECULAR]; } - bool hasEmissive() const { return _flags[EMISSIVE]; } + bool isUnlit() const { return _flags[UNLIT]; } bool isTranslucent() const { return _flags[TRANSLUCENT]; } bool isSkinned() const { return _flags[SKINNED]; } bool isStereo() const { return _flags[STEREO]; } @@ -173,7 +173,7 @@ inline QDebug operator<<(QDebug debug, const ShapeKey& key) { << "hasLightmap:" << key.hasLightmap() << "hasTangents:" << key.hasTangents() << "hasSpecular:" << key.hasSpecular() - << "hasEmissive:" << key.hasEmissive() + << "isUnlit:" << key.isUnlit() << "isTranslucent:" << key.isTranslucent() << "isSkinned:" << key.isSkinned() << "isStereo:" << key.isStereo() diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index f7ac7894ff..df31ad59f1 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -62,8 +62,6 @@ #include "MIDIEvent.h" -std::atomic ScriptEngine::_stoppingAllScripts { false }; - static const QString SCRIPT_EXCEPTION_FORMAT = "[UncaughtException] %1 in %2:%3"; Q_DECLARE_METATYPE(QScriptEngine::FunctionSignature) @@ -756,7 +754,7 @@ void ScriptEngine::addEventHandler(const EntityItemID& entityID, const QString& QScriptValue ScriptEngine::evaluate(const QString& sourceCode, const QString& fileName, int lineNumber) { - if (_stoppingAllScripts) { + if (DependencyManager::get()->isStopped()) { return QScriptValue(); // bail early } @@ -792,7 +790,7 @@ QScriptValue ScriptEngine::evaluate(const QString& sourceCode, const QString& fi } void ScriptEngine::run() { - if (_stoppingAllScripts) { + if (DependencyManager::get()->isStopped()) { return; // bail early - avoid setting state in init(), as evaluate() will bail too } @@ -1025,7 +1023,7 @@ QObject* ScriptEngine::setupTimerWithInterval(const QScriptValue& function, int } QObject* ScriptEngine::setInterval(const QScriptValue& function, int intervalMS) { - if (_stoppingAllScripts) { + if (DependencyManager::get()->isStopped()) { qCDebug(scriptengine) << "Script.setInterval() while shutting down is ignored... parent script:" << getFilename(); return NULL; // bail early } @@ -1034,7 +1032,7 @@ QObject* ScriptEngine::setInterval(const QScriptValue& function, int intervalMS) } QObject* ScriptEngine::setTimeout(const QScriptValue& function, int timeoutMS) { - if (_stoppingAllScripts) { + if (DependencyManager::get()->isStopped()) { qCDebug(scriptengine) << "Script.setTimeout() while shutting down is ignored... parent script:" << getFilename(); return NULL; // bail early } @@ -1086,7 +1084,7 @@ void ScriptEngine::print(const QString& message) { // If no callback is specified, the included files will be loaded synchronously and will block execution until // all of the files have finished loading. void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callback) { - if (_stoppingAllScripts) { + if (DependencyManager::get()->isStopped()) { qCDebug(scriptengine) << "Script.include() while shutting down is ignored..." << "includeFiles:" << includeFiles << "parent script:" << getFilename(); return; // bail early @@ -1184,7 +1182,7 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac } void ScriptEngine::include(const QString& includeFile, QScriptValue callback) { - if (_stoppingAllScripts) { + if (DependencyManager::get()->isStopped()) { qCDebug(scriptengine) << "Script.include() while shutting down is ignored... " << "includeFile:" << includeFile << "parent script:" << getFilename(); return; // bail early @@ -1199,7 +1197,7 @@ void ScriptEngine::include(const QString& includeFile, QScriptValue callback) { // as a stand-alone script. To accomplish this, the ScriptEngine class just emits a signal which // the Application or other context will connect to in order to know to actually load the script void ScriptEngine::load(const QString& loadFile) { - if (_stoppingAllScripts) { + if (DependencyManager::get()->isStopped()) { qCDebug(scriptengine) << "Script.load() while shutting down is ignored... " << "loadFile:" << loadFile << "parent script:" << getFilename(); return; // bail early diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index d37e3eb177..993b4e1e8a 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -83,6 +83,10 @@ public: /// run the script in the callers thread, exit when stop() is called. void run(); + void waitTillDoneRunning(); + + QString getFilename() const; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // NOTE - these are NOT intended to be public interfaces available to scripts, the are only Q_INVOKABLE so we can // properly ensure they are only called on the correct thread @@ -199,8 +203,6 @@ protected: qint64 _lastUpdate; void init(); - QString getFilename() const; - void waitTillDoneRunning(); bool evaluatePending() const { return _evaluatesPending > 0; } void timerFired(); void stopAllTimers(); @@ -232,9 +234,6 @@ protected: QUrl currentSandboxURL {}; // The toplevel url string for the entity script that loaded the code being executed, else empty. void doWithEnvironment(const EntityItemID& entityID, const QUrl& sandboxURL, std::function operation); void callWithEnvironment(const EntityItemID& entityID, const QUrl& sandboxURL, QScriptValue function, QScriptValue thisObject, QScriptValueList args); - - friend class ScriptEngines; - static std::atomic _stoppingAllScripts; }; #endif // hifi_ScriptEngine_h diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index 330a94cf0b..805ddfdada 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -119,26 +119,27 @@ void ScriptEngines::registerScriptInitializer(ScriptInitializer initializer) { } void ScriptEngines::addScriptEngine(ScriptEngine* engine) { - _allScriptsMutex.lock(); - _allKnownScriptEngines.insert(engine); - _allScriptsMutex.unlock(); + if (_isStopped) { + engine->deleteLater(); + } else { + QMutexLocker locker(&_allScriptsMutex); + _allKnownScriptEngines.insert(engine); + } } void ScriptEngines::removeScriptEngine(ScriptEngine* engine) { // If we're not already in the middle of stopping all scripts, then we should remove ourselves // from the list of running scripts. We don't do this if we're in the process of stopping all scripts // because that method removes scripts from its list as it iterates them - if (!_stoppingAllScripts) { - _allScriptsMutex.lock(); + if (!_isStopped) { + QMutexLocker locker(&_allScriptsMutex); _allKnownScriptEngines.remove(engine); - _allScriptsMutex.unlock(); } } void ScriptEngines::shutdownScripting() { - _allScriptsMutex.lock(); - _stoppingAllScripts = true; - ScriptEngine::_stoppingAllScripts = true; + _isStopped = true; + QMutexLocker locker(&_allScriptsMutex); qCDebug(scriptengine) << "Stopping all scripts.... currently known scripts:" << _allKnownScriptEngines.size(); QMutableSetIterator i(_allKnownScriptEngines); @@ -174,8 +175,6 @@ void ScriptEngines::shutdownScripting() { i.remove(); } } - _stoppingAllScripts = false; - _allScriptsMutex.unlock(); qCDebug(scriptengine) << "DONE Stopping all scripts...."; } @@ -499,7 +498,6 @@ void ScriptEngines::launchScriptEngine(ScriptEngine* scriptEngine) { } } - void ScriptEngines::onScriptFinished(const QString& rawScriptURL, ScriptEngine* engine) { bool removed = false; { diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h index 6522aa9bb3..72bf7d529e 100644 --- a/libraries/script-engine/src/ScriptEngines.h +++ b/libraries/script-engine/src/ScriptEngines.h @@ -86,16 +86,17 @@ protected: void onScriptEngineLoaded(const QString& scriptFilename); void onScriptEngineError(const QString& scriptFilename); void launchScriptEngine(ScriptEngine* engine); + bool isStopped() const { return _isStopped; } QReadWriteLock _scriptEnginesHashLock; QHash _scriptEnginesHash; QSet _allKnownScriptEngines; QMutex _allScriptsMutex; - std::atomic _stoppingAllScripts { false }; std::list _scriptInitializers; mutable Setting::Handle _scriptsLocationHandle; ScriptsModel _scriptsModel; ScriptsModelFilter _scriptsModelFilter; + std::atomic _isStopped { false }; }; QUrl normalizeScriptURL(const QUrl& rawScriptURL); diff --git a/scripts/developer/utilities/render/framebuffer.qml b/scripts/developer/utilities/render/framebuffer.qml index f13018142e..0d8d85cc32 100644 --- a/scripts/developer/utilities/render/framebuffer.qml +++ b/scripts/developer/utilities/render/framebuffer.qml @@ -33,6 +33,7 @@ Column { "Roughness", "Metallic", "Emissive", + "Shaded/Lightmapped/Unlit", "Occlusion", "Lightmap", "Lighting", diff --git a/scripts/system/away.js b/scripts/system/away.js index 932efd6b60..2b2ea8a42b 100644 --- a/scripts/system/away.js +++ b/scripts/system/away.js @@ -262,6 +262,14 @@ eventMapping.from(Controller.Standard.LeftPrimaryThumb).peek().to(goActive); eventMapping.from(Controller.Standard.RightPrimaryThumb).peek().to(goActive); eventMapping.from(Controller.Standard.LeftSecondaryThumb).peek().to(goActive); eventMapping.from(Controller.Standard.RightSecondaryThumb).peek().to(goActive); +eventMapping.from(Controller.Standard.LT).peek().to(goActive); +eventMapping.from(Controller.Standard.LB).peek().to(goActive); +eventMapping.from(Controller.Standard.LS).peek().to(goActive); +eventMapping.from(Controller.Standard.RT).peek().to(goActive); +eventMapping.from(Controller.Standard.RB).peek().to(goActive); +eventMapping.from(Controller.Standard.RS).peek().to(goActive); +eventMapping.from(Controller.Standard.Back).peek().to(goActive); +eventMapping.from(Controller.Standard.Start).peek().to(goActive); Controller.enableMapping(eventMappingName); Script.scriptEnding.connect(function () { @@ -270,4 +278,4 @@ Script.scriptEnding.connect(function () { Controller.disableMapping(eventMappingName); Controller.mousePressEvent.disconnect(goActive); Controller.keyPressEvent.disconnect(maybeGoActive); -}); \ No newline at end of file +}); diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index 0fdaed58f2..ed4ac219c0 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -739,6 +739,9 @@ function MyController(hand) { }; this.propsArePhysical = function(props) { + if (!props.dynamic) { + return false; + } var isPhysical = (props.shapeType && props.shapeType != 'none'); return isPhysical; } diff --git a/scripts/system/users.js b/scripts/system/users.js index 9612a19eee..d935dd23ca 100644 --- a/scripts/system/users.js +++ b/scripts/system/users.js @@ -9,7 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -var PopUpMenu = function(properties) { +var PopUpMenu = function (properties) { var value = properties.value, promptOverlay, valueOverlay, @@ -21,9 +21,8 @@ var PopUpMenu = function(properties) { MIN_MAX_BUTTON_SVG_WIDTH = 17.1, MIN_MAX_BUTTON_SVG_HEIGHT = 32.5, MIN_MAX_BUTTON_WIDTH = 14, - MIN_MAX_BUTTON_HEIGHT = MIN_MAX_BUTTON_WIDTH; - - MIN_MAX_BUTTON_SVG = Script.resolvePath("assets/images/tools/min-max-toggle.svg"); + MIN_MAX_BUTTON_HEIGHT = MIN_MAX_BUTTON_WIDTH, + MIN_MAX_BUTTON_SVG = Script.resolvePath("assets/images/tools/min-max-toggle.svg"); function positionDisplayOptions() { var y, @@ -203,7 +202,7 @@ var PopUpMenu = function(properties) { width: MIN_MAX_BUTTON_SVG_WIDTH, height: MIN_MAX_BUTTON_SVG_HEIGHT / 2 }, - color: properties.buttonColor, + //color: properties.buttonColor, alpha: properties.buttonAlpha, visible: properties.visible }); @@ -218,11 +217,10 @@ var PopUpMenu = function(properties) { }; }; -var usersWindow = (function() { +var usersWindow = (function () { - var baseURL = Script.resolvePath("assets/images/tools/"); - - var WINDOW_WIDTH = 260, + var baseURL = Script.resolvePath("assets/images/tools/"), + WINDOW_WIDTH = 260, WINDOW_MARGIN = 12, WINDOW_BASE_MARGIN = 6, // A little less is needed in order look correct WINDOW_FONT = { @@ -248,6 +246,17 @@ var usersWindow = (function() { WINDOW_BACKGROUND_ALPHA = 0.8, windowPane, windowHeading, + + // Window border is similar to that of edit.js. + WINDOW_BORDER_WIDTH = WINDOW_WIDTH + 2 * WINDOW_BASE_MARGIN, + WINDOW_BORDER_TOP_MARGIN = 2 * WINDOW_BASE_MARGIN, + WINDOW_BORDER_BOTTOM_MARGIN = WINDOW_BASE_MARGIN, + WINDOW_BORDER_LEFT_MARGIN = WINDOW_BASE_MARGIN, + WINDOW_BORDER_RADIUS = 4, + WINDOW_BORDER_COLOR = { red: 255, green: 255, blue: 255 }, + WINDOW_BORDER_ALPHA = 0.5, + windowBorder, + MIN_MAX_BUTTON_SVG = baseURL + "min-max-toggle.svg", MIN_MAX_BUTTON_SVG_WIDTH = 17.1, MIN_MAX_BUTTON_SVG_HEIGHT = 32.5, @@ -331,6 +340,7 @@ var usersWindow = (function() { visibilityControl, windowHeight, + windowBorderHeight, windowTextHeight, windowLineSpacing, windowLineHeight, // = windowTextHeight + windowLineSpacing @@ -356,14 +366,21 @@ var usersWindow = (function() { MENU_ITEM_AFTER = "Chat...", SETTING_USERS_WINDOW_MINIMIZED = "UsersWindow.Minimized", + SETINGS_USERS_WINDOW_OFFSET = "UsersWindow.Offset", + // +ve x, y values are offset from left, top of screen; -ve from right, bottom. isVisible = true, isMinimized = false, + isBorderVisible = false, - viewportHeight, + viewport, isMirrorDisplay = false, isFullscreenMirror = false, + windowPosition = { }, // Bottom left corner of window pane. + isMovingWindow = false, + movingClickOffset = { x: 0, y: 0 }, + isUsingScrollbars = false, isMovingScrollbar = false, scrollbarBackgroundPosition = {}, @@ -379,19 +396,23 @@ var usersWindow = (function() { if (isMinimized) { windowHeight = windowTextHeight + WINDOW_MARGIN + WINDOW_BASE_MARGIN; + windowBorderHeight = windowHeight + WINDOW_BORDER_TOP_MARGIN + WINDOW_BORDER_BOTTOM_MARGIN; return; } // Reserve space for title, friends button, and option controls - nonUsersHeight = WINDOW_MARGIN + windowLineHeight + FRIENDS_BUTTON_SPACER + FRIENDS_BUTTON_HEIGHT + DISPLAY_SPACER + windowLineHeight + VISIBILITY_SPACER + windowLineHeight + WINDOW_BASE_MARGIN; + nonUsersHeight = WINDOW_MARGIN + windowLineHeight + FRIENDS_BUTTON_SPACER + FRIENDS_BUTTON_HEIGHT + DISPLAY_SPACER + + windowLineHeight + VISIBILITY_SPACER + + windowLineHeight + WINDOW_BASE_MARGIN; - // Limit window to height of viewport minus VU meter and mirror if displayed + // Limit window to height of viewport above window position minus VU meter and mirror if displayed windowHeight = linesOfUsers.length * windowLineHeight - windowLineSpacing + nonUsersHeight; - maxWindowHeight = viewportHeight - AUDIO_METER_HEIGHT; + maxWindowHeight = windowPosition.y - AUDIO_METER_HEIGHT; if (isMirrorDisplay && !isFullscreenMirror) { maxWindowHeight -= MIRROR_HEIGHT; } windowHeight = Math.max(Math.min(windowHeight, maxWindowHeight), nonUsersHeight); + windowBorderHeight = windowHeight + WINDOW_BORDER_TOP_MARGIN + WINDOW_BORDER_BOTTOM_MARGIN; // Corresponding number of users to actually display numUsersToDisplay = Math.max(Math.round((windowHeight - nonUsersHeight) / windowLineHeight), 0); @@ -405,38 +426,57 @@ var usersWindow = (function() { } function updateOverlayPositions() { - var y; + // Overlay positions are all relative to windowPosition; windowPosition is the position of the windowPane overlay. + var windowLeft = windowPosition.x, + windowTop = windowPosition.y - windowHeight, + x, + y; + Overlays.editOverlay(windowBorder, { + x: windowPosition.x - WINDOW_BORDER_LEFT_MARGIN, + y: windowTop - WINDOW_BORDER_TOP_MARGIN + }); Overlays.editOverlay(windowPane, { - y: viewportHeight - windowHeight + x: windowLeft, + y: windowTop }); Overlays.editOverlay(windowHeading, { - y: viewportHeight - windowHeight + WINDOW_MARGIN + x: windowLeft + WINDOW_MARGIN, + y: windowTop + WINDOW_MARGIN }); Overlays.editOverlay(minimizeButton, { - y: viewportHeight - windowHeight + WINDOW_MARGIN / 2 + x: windowLeft + WINDOW_WIDTH - WINDOW_MARGIN / 2 - MIN_MAX_BUTTON_WIDTH, + y: windowTop + WINDOW_MARGIN / 2 }); - scrollbarBackgroundPosition.y = viewportHeight - windowHeight + WINDOW_MARGIN + windowTextHeight; + scrollbarBackgroundPosition.x = windowLeft + WINDOW_WIDTH - 0.5 * WINDOW_MARGIN - SCROLLBAR_BACKGROUND_WIDTH; + scrollbarBackgroundPosition.y = windowTop + WINDOW_MARGIN + windowTextHeight; Overlays.editOverlay(scrollbarBackground, { + x: scrollbarBackgroundPosition.x, y: scrollbarBackgroundPosition.y }); - scrollbarBarPosition.y = scrollbarBackgroundPosition.y + 1 + scrollbarValue * (scrollbarBackgroundHeight - scrollbarBarHeight - 2); + scrollbarBarPosition.y = scrollbarBackgroundPosition.y + 1 + + scrollbarValue * (scrollbarBackgroundHeight - scrollbarBarHeight - 2); Overlays.editOverlay(scrollbarBar, { + x: scrollbarBackgroundPosition.x + 1, y: scrollbarBarPosition.y }); - y = viewportHeight - FRIENDS_BUTTON_HEIGHT - DISPLAY_SPACER - windowLineHeight - VISIBILITY_SPACER - windowLineHeight - WINDOW_BASE_MARGIN; + x = windowLeft + WINDOW_MARGIN; + y = windowPosition.y - FRIENDS_BUTTON_HEIGHT - DISPLAY_SPACER + - windowLineHeight - VISIBILITY_SPACER + - windowLineHeight - WINDOW_BASE_MARGIN; Overlays.editOverlay(friendsButton, { + x: x, y: y }); y += FRIENDS_BUTTON_HEIGHT + DISPLAY_SPACER; - displayControl.updatePosition(WINDOW_MARGIN, y); + displayControl.updatePosition(x, y); y += windowLineHeight + VISIBILITY_SPACER; - visibilityControl.updatePosition(WINDOW_MARGIN, y); + visibilityControl.updatePosition(x, y); } function updateUsersDisplay() { @@ -487,6 +527,10 @@ var usersWindow = (function() { }); } + Overlays.editOverlay(windowBorder, { + height: windowBorderHeight + }); + Overlays.editOverlay(windowPane, { height: windowHeight, text: displayText @@ -512,7 +556,7 @@ var usersWindow = (function() { usersRequest.send(); } - processUsers = function() { + processUsers = function () { var response, myUsername, user, @@ -565,12 +609,15 @@ var usersWindow = (function() { } }; - pollUsersTimedOut = function() { + pollUsersTimedOut = function () { print("Error: Request for users status timed out"); usersTimer = Script.setTimeout(pollUsers, HTTP_GET_TIMEOUT); // Try again after a longer delay. }; function updateOverlayVisibility() { + Overlays.editOverlay(windowBorder, { + visible: isVisible && isBorderVisible + }); Overlays.editOverlay(windowPane, { visible: isVisible }); @@ -670,7 +717,7 @@ var usersWindow = (function() { if (clickedOverlay === windowPane) { overlayX = event.x - WINDOW_MARGIN; - overlayY = event.y - viewportHeight + windowHeight - WINDOW_MARGIN - windowLineHeight; + overlayY = event.y - windowPosition.y + windowHeight - WINDOW_MARGIN - windowLineHeight; numLinesBefore = Math.round(overlayY / windowLineHeight); minY = numLinesBefore * windowLineHeight; @@ -683,7 +730,8 @@ var usersWindow = (function() { userClicked = firstUserToDisplay + lineClicked; - if (0 <= userClicked && userClicked < linesOfUsers.length && 0 <= overlayX && overlayX <= usersOnline[linesOfUsers[userClicked]].textWidth) { + if (0 <= userClicked && userClicked < linesOfUsers.length && 0 <= overlayX + && overlayX <= usersOnline[linesOfUsers[userClicked]].textWidth) { //print("Go to " + usersOnline[linesOfUsers[userClicked]].username); location.goToUser(usersOnline[linesOfUsers[userClicked]].username); } @@ -735,13 +783,29 @@ var usersWindow = (function() { friendsWindow.setURL(FRIENDS_WINDOW_URL); friendsWindow.setVisible(true); friendsWindow.raise(); + return; + } + + if (clickedOverlay === windowBorder) { + movingClickOffset = { + x: event.x - windowPosition.x, + y: event.y - windowPosition.y + }; + + isMovingWindow = true; } } function onMouseMoveEvent(event) { + var isVisible; + if (isMovingScrollbar) { - if (scrollbarBackgroundPosition.x - WINDOW_MARGIN <= event.x && event.x <= scrollbarBackgroundPosition.x + SCROLLBAR_BACKGROUND_WIDTH + WINDOW_MARGIN && scrollbarBackgroundPosition.y - WINDOW_MARGIN <= event.y && event.y <= scrollbarBackgroundPosition.y + scrollbarBackgroundHeight + WINDOW_MARGIN) { - scrollbarValue = (event.y - scrollbarBarClickedAt * scrollbarBarHeight - scrollbarBackgroundPosition.y) / (scrollbarBackgroundHeight - scrollbarBarHeight - 2); + if (scrollbarBackgroundPosition.x - WINDOW_MARGIN <= event.x + && event.x <= scrollbarBackgroundPosition.x + SCROLLBAR_BACKGROUND_WIDTH + WINDOW_MARGIN + && scrollbarBackgroundPosition.y - WINDOW_MARGIN <= event.y + && event.y <= scrollbarBackgroundPosition.y + scrollbarBackgroundHeight + WINDOW_MARGIN) { + scrollbarValue = (event.y - scrollbarBarClickedAt * scrollbarBarHeight - scrollbarBackgroundPosition.y) + / (scrollbarBackgroundHeight - scrollbarBarHeight - 2); scrollbarValue = Math.min(Math.max(scrollbarValue, 0.0), 1.0); firstUserToDisplay = Math.floor(scrollbarValue * (linesOfUsers.length - numUsersToDisplay)); updateOverlayPositions(); @@ -753,35 +817,95 @@ var usersWindow = (function() { isMovingScrollbar = false; } } + + if (isMovingWindow) { + windowPosition = { + x: event.x - movingClickOffset.x, + y: event.y - movingClickOffset.y + }; + calculateWindowHeight(); + updateOverlayPositions(); + updateUsersDisplay(); + + } else { + + isVisible = isBorderVisible; + if (isVisible) { + isVisible = windowPosition.x - WINDOW_BORDER_LEFT_MARGIN <= event.x + && event.x <= windowPosition.x - WINDOW_BORDER_LEFT_MARGIN + WINDOW_BORDER_WIDTH + && windowPosition.y - windowHeight - WINDOW_BORDER_TOP_MARGIN <= event.y + && event.y <= windowPosition.y + WINDOW_BORDER_BOTTOM_MARGIN; + } else { + isVisible = windowPosition.x <= event.x && event.x <= windowPosition.x + WINDOW_WIDTH + && windowPosition.y - windowHeight <= event.y && event.y <= windowPosition.y; + } + if (isVisible !== isBorderVisible) { + isBorderVisible = isVisible; + Overlays.editOverlay(windowBorder, { + visible: isBorderVisible + }); + } + } } function onMouseReleaseEvent() { - Overlays.editOverlay(scrollbarBar, { - backgroundAlpha: SCROLLBAR_BAR_ALPHA - }); - isMovingScrollbar = false; + var offset = {}; + + if (isMovingScrollbar) { + Overlays.editOverlay(scrollbarBar, { + backgroundAlpha: SCROLLBAR_BAR_ALPHA + }); + isMovingScrollbar = false; + } + + if (isMovingWindow) { + // Save offset of bottom of window to nearest edge of the window. + offset.x = (windowPosition.x + WINDOW_WIDTH / 2 < viewport.x / 2) ? windowPosition.x : windowPosition.x - viewport.x; + offset.y = (windowPosition.y < viewport.y / 2) ? windowPosition.y : windowPosition.y - viewport.y; + Settings.setValue(SETINGS_USERS_WINDOW_OFFSET, JSON.stringify(offset)); + isMovingWindow = false; + } } function onScriptUpdate() { - var oldViewportHeight = viewportHeight, + var oldViewport = viewport, oldIsMirrorDisplay = isMirrorDisplay, oldIsFullscreenMirror = isFullscreenMirror, MIRROR_MENU_ITEM = "Mirror", FULLSCREEN_MIRROR_MENU_ITEM = "Fullscreen Mirror"; - viewportHeight = Controller.getViewportDimensions().y; + viewport = Controller.getViewportDimensions(); isMirrorDisplay = Menu.isOptionChecked(MIRROR_MENU_ITEM); isFullscreenMirror = Menu.isOptionChecked(FULLSCREEN_MIRROR_MENU_ITEM); - if (viewportHeight !== oldViewportHeight || isMirrorDisplay !== oldIsMirrorDisplay || isFullscreenMirror !== oldIsFullscreenMirror) { + if (viewport.y !== oldViewport.y || isMirrorDisplay !== oldIsMirrorDisplay + || isFullscreenMirror !== oldIsFullscreenMirror) { calculateWindowHeight(); updateUsersDisplay(); - updateOverlayPositions(); } + + if (viewport.y !== oldViewport.y) { + if (windowPosition.y > oldViewport.y / 2) { + // Maintain position w.r.t. bottom of window. + windowPosition.y = viewport.y - (oldViewport.y - windowPosition.y); + } + } + + if (viewport.x !== oldViewport.x) { + if (windowPosition.x + (WINDOW_WIDTH / 2) > oldViewport.x / 2) { + // Maintain position w.r.t. right of window. + windowPosition.x = viewport.x - (oldViewport.x - windowPosition.x); + } + } + + updateOverlayPositions(); } function setUp() { - var textSizeOverlay; + var textSizeOverlay, + offsetSetting, + offset = {}, + hmdViewport; textSizeOverlay = Overlays.addOverlay("text", { font: WINDOW_FONT, @@ -792,13 +916,40 @@ var usersWindow = (function() { windowLineHeight = windowTextHeight + windowLineSpacing; Overlays.deleteOverlay(textSizeOverlay); - viewportHeight = Controller.getViewportDimensions().y; + viewport = Controller.getViewportDimensions(); + + offsetSetting = Settings.getValue(SETINGS_USERS_WINDOW_OFFSET); + if (offsetSetting !== "") { + offset = JSON.parse(Settings.getValue(SETINGS_USERS_WINDOW_OFFSET)); + } + if (offset.hasOwnProperty("x") && offset.hasOwnProperty("y")) { + windowPosition.x = offset.x < 0 ? viewport.x + offset.x : offset.x; + windowPosition.y = offset.y <= 0 ? viewport.y + offset.y : offset.y; + + } else { + hmdViewport = Controller.getRecommendedOverlayRect(); + windowPosition = { + x: (viewport.x - hmdViewport.width) / 2, // HMD viewport is narrower than screen. + y: hmdViewport.height // HMD viewport starts at top of screen but only extends down so far. + }; + } calculateWindowHeight(); + windowBorder = Overlays.addOverlay("rectangle", { + x: 0, + y: viewport.y, // Start up off-screen + width: WINDOW_BORDER_WIDTH, + height: windowBorderHeight, + radius: WINDOW_BORDER_RADIUS, + color: WINDOW_BORDER_COLOR, + alpha: WINDOW_BORDER_ALPHA, + visible: isVisible && isBorderVisible + }); + windowPane = Overlays.addOverlay("text", { x: 0, - y: viewportHeight, // Start up off-screen + y: viewport.y, width: WINDOW_WIDTH, height: windowHeight, topMargin: WINDOW_MARGIN + windowLineHeight, @@ -813,8 +964,8 @@ var usersWindow = (function() { }); windowHeading = Overlays.addOverlay("text", { - x: WINDOW_MARGIN, - y: viewportHeight, + x: 0, + y: viewport.y, width: WINDOW_WIDTH - 2 * WINDOW_MARGIN, height: windowTextHeight, topMargin: 0, @@ -828,8 +979,8 @@ var usersWindow = (function() { }); minimizeButton = Overlays.addOverlay("image", { - x: WINDOW_WIDTH - WINDOW_MARGIN / 2 - MIN_MAX_BUTTON_WIDTH, - y: viewportHeight, + x: 0, + y: viewport.y, width: MIN_MAX_BUTTON_WIDTH, height: MIN_MAX_BUTTON_HEIGHT, imageURL: MIN_MAX_BUTTON_SVG, @@ -845,11 +996,11 @@ var usersWindow = (function() { }); scrollbarBackgroundPosition = { - x: WINDOW_WIDTH - 0.5 * WINDOW_MARGIN - SCROLLBAR_BACKGROUND_WIDTH, - y: viewportHeight + x: 0, + y: viewport.y }; scrollbarBackground = Overlays.addOverlay("text", { - x: scrollbarBackgroundPosition.x, + x: 0, y: scrollbarBackgroundPosition.y, width: SCROLLBAR_BACKGROUND_WIDTH, height: windowTextHeight, @@ -860,11 +1011,11 @@ var usersWindow = (function() { }); scrollbarBarPosition = { - x: WINDOW_WIDTH - 0.5 * WINDOW_MARGIN - SCROLLBAR_BACKGROUND_WIDTH + 1, - y: viewportHeight + x: 0, + y: viewport.y }; scrollbarBar = Overlays.addOverlay("text", { - x: scrollbarBarPosition.x, + x: 0, y: scrollbarBarPosition.y, width: SCROLLBAR_BACKGROUND_WIDTH - 2, height: windowTextHeight, @@ -875,8 +1026,8 @@ var usersWindow = (function() { }); friendsButton = Overlays.addOverlay("image", { - x: WINDOW_MARGIN, - y: viewportHeight, + x: 0, + y: viewport.y, width: FRIENDS_BUTTON_WIDTH, height: FRIENDS_BUTTON_HEIGHT, imageURL: FRIENDS_BUTTON_SVG, @@ -895,8 +1046,8 @@ var usersWindow = (function() { value: DISPLAY_VALUES[0], values: DISPLAY_VALUES, displayValues: DISPLAY_DISPLAY_VALUES, - x: WINDOW_MARGIN, - y: viewportHeight, + x: 0, + y: viewport.y, width: WINDOW_WIDTH - 1.5 * WINDOW_MARGIN, promptWidth: DISPLAY_PROMPT_WIDTH, lineHeight: windowLineHeight, @@ -928,8 +1079,8 @@ var usersWindow = (function() { value: myVisibility, values: VISIBILITY_VALUES, displayValues: VISIBILITY_DISPLAY_VALUES, - x: WINDOW_MARGIN, - y: viewportHeight, + x: 0, + y: viewport.y, width: WINDOW_WIDTH - 1.5 * WINDOW_MARGIN, promptWidth: VISIBILITY_PROMPT_WIDTH, lineHeight: windowLineHeight, @@ -979,6 +1130,7 @@ var usersWindow = (function() { Menu.removeMenuItem(MENU_NAME, MENU_ITEM); Script.clearTimeout(usersTimer); + Overlays.deleteOverlay(windowBorder); Overlays.deleteOverlay(windowPane); Overlays.deleteOverlay(windowHeading); Overlays.deleteOverlay(minimizeButton); @@ -991,4 +1143,4 @@ var usersWindow = (function() { setUp(); Script.scriptEnding.connect(tearDown); -}()); \ No newline at end of file +}()); diff --git a/tests/shaders/src/main.cpp b/tests/shaders/src/main.cpp index 2bc957b2d1..c50f5769e6 100644 --- a/tests/shaders/src/main.cpp +++ b/tests/shaders/src/main.cpp @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include @@ -160,7 +160,7 @@ void QTestWindow::draw() { testShaderBuild(skybox_vert, skybox_frag); testShaderBuild(simple_vert, simple_frag); testShaderBuild(simple_vert, simple_textured_frag); - testShaderBuild(simple_vert, simple_textured_emisive_frag); + testShaderBuild(simple_vert, simple_textured_unlit_frag); testShaderBuild(deferred_light_vert, directional_light_frag); testShaderBuild(deferred_light_vert, directional_ambient_light_frag); testShaderBuild(deferred_light_vert, directional_skybox_light_frag); diff --git a/tools/scribe/src/main.cpp b/tools/scribe/src/main.cpp index 13003f05cf..b7038e392e 100755 --- a/tools/scribe/src/main.cpp +++ b/tools/scribe/src/main.cpp @@ -12,6 +12,7 @@ #include "TextTemplate.h" #include +#include #include #include @@ -168,7 +169,7 @@ int main (int argc, char** argv) { auto scribe = std::make_shared(srcFilename, config); // ready to parse and generate - std::ostringstream destStringStream; + std::stringstream destStringStream; int numErrors = scribe->scribe(destStringStream, srcStream, vars); if (numErrors) { cerr << "Scribe " << srcFilename << "> failed: " << numErrors << " errors." << endl; @@ -187,14 +188,38 @@ int main (int argc, char** argv) { std::ostringstream targetStringStream; if (makeCPlusPlus) { + // Because there is a maximum size for literal strings declared in source we need to partition the + // full source string stream into pages that seems to be around that value... + const int MAX_STRING_LITERAL = 10000; + std::string lineToken; + auto pageSize = lineToken.length(); + std::vector> pages(1, std::make_shared()); + while (!destStringStream.eof()) { + std::getline(destStringStream, lineToken); + auto lineSize = lineToken.length() + 1; + + if (pageSize + lineSize > MAX_STRING_LITERAL) { + pages.push_back(std::make_shared()); + // reset pageStringStream + pageSize = 0; + } + + (*pages.back()) << lineToken << std::endl; + pageSize += lineSize; + } + targetStringStream << "// File generated by Scribe " << vars["_SCRIBE_DATE"] << std::endl; targetStringStream << "#ifndef scribe_" << targetName << "_h" << std::endl; targetStringStream << "#define scribe_" << targetName << "_h" << std::endl << std::endl; - // targetStringStream << "const char " << targetName << "[] = R\"XXXX(" << destStringStream.str() << ")XXXX\";"; - targetStringStream << "const char " << targetName << "[] = R\"SCRIBE("; - targetStringStream << destStringStream.str(); - targetStringStream << "\n)SCRIBE\";\n\n"; + targetStringStream << "const char " << targetName << "[] = \n"; + + // Write the pages content + for (auto page : pages) { + targetStringStream << "R\"SCRIBE(\n" << page->str() << "\n)SCRIBE\"\n"; + } + targetStringStream << ";\n" << std::endl << std::endl; + targetStringStream << "#endif" << std::endl; } else { targetStringStream << destStringStream.str(); diff --git a/unpublishedScripts/DomainContent/Home/cuckooClock/wrapper.js b/unpublishedScripts/DomainContent/Home/cuckooClock/wrapper.js index 6c6704514b..36d06cd8e8 100644 --- a/unpublishedScripts/DomainContent/Home/cuckooClock/wrapper.js +++ b/unpublishedScripts/DomainContent/Home/cuckooClock/wrapper.js @@ -9,7 +9,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -var MINUTE_HAND_CLOCK_SCRIPT_URL = Script.resolvePath("cuckooClockMinuteHandEntityScript.js" ) +var MINUTE_HAND_CLOCK_SCRIPT_URL = Script.resolvePath("cuckooClockMinuteHandEntityScript.js") var CLOCK_BODY_URL = "atp:/cuckooClock/cuckoo2_BODY.fbx"; var CLOCK_BODY_COLLISION_HULL_URL = "atp:/cuckooClock/clockHull.obj"; var CLOCK_FACE_URL = "atp:/cuckooClock/cuckooClock2_FACE.fbx"; @@ -38,11 +38,11 @@ MyCuckooClock = function(spawnPosition, spawnRotation) { }, position: spawnPosition, rotation: clockRotation, - dimensions: { + dimensions: Vec3.multiply(0.5, { x: 0.8181, y: 1.3662, z: 0.8181 - }, + }), userData: JSON.stringify({ hifiHomeKey: { reset: true @@ -50,9 +50,9 @@ MyCuckooClock = function(spawnPosition, spawnRotation) { }) }) - var forwardOffset = -0.13 - var upOffset = 0.255; - var sideOffset = -0.03; + var forwardOffset = 0.5 * -0.13; + var upOffset = 0.5 * 0.255; + var sideOffset = 0.5 * -0.03; var clockFacePosition = spawnPosition; clockFacePosition = Vec3.sum(clockFacePosition, Vec3.multiply(Quat.getFront(clockRotation), forwardOffset)); clockFacePosition = Vec3.sum(clockFacePosition, Vec3.multiply(Quat.getUp(clockRotation), upOffset)); @@ -65,11 +65,11 @@ MyCuckooClock = function(spawnPosition, spawnRotation) { name: "home_model_clockFace", modelURL: CLOCK_FACE_URL, position: clockFacePosition, - dimensions: { + dimensions: Vec3.multiply(0.5, { x: 0.2397, y: 0.2402, z: 0.0212 - }, + }), userData: JSON.stringify({ hifiHomeKey: { reset: true @@ -86,7 +86,7 @@ MyCuckooClock = function(spawnPosition, spawnRotation) { var myDate = new Date() // HOUR HAND ************************* - var clockHandForwardOffset = -0.017; + var clockHandForwardOffset = (0.5 * -0.017); var hourHandPosition = Vec3.sum(clockFacePosition, Vec3.multiply(Quat.getFront(clockRotation), clockHandForwardOffset)); @@ -118,11 +118,11 @@ MyCuckooClock = function(spawnPosition, spawnRotation) { rotation: worldClockHandRotation, angularDamping: 0, angularVelocity: worldAngularVelocity, - dimensions: { + dimensions: Vec3.multiply(0.5, { x: 0.0263, y: 0.0982, z: 0.0024 - }, + }), userData: JSON.stringify({ hifiHomeKey: { reset: true @@ -150,11 +150,11 @@ MyCuckooClock = function(spawnPosition, spawnRotation) { modelURL: CLOCK_SECOND_HAND_URL, name: "home_model_clockSecondHand", position: hourHandPosition, - dimensions: { + dimensions: Vec3.multiply(0.5, { x: 0.0043, y: 0.1117, z: 0.0008 - }, + }), color: { red: 200, green: 10, @@ -202,14 +202,14 @@ MyCuckooClock = function(spawnPosition, spawnRotation) { y: 0.05, z: 0.5 }, - rotation:worldClockHandRotation, + rotation: worldClockHandRotation, angularDamping: 0, angularVelocity: worldAngularVelocity, - dimensions: { + dimensions: Vec3.multiply(0.5, { x: 0.0251, y: 0.1179, z: 0.0032 - }, + }), script: MINUTE_HAND_CLOCK_SCRIPT_URL, userData: JSON.stringify({ clockBody: clockBody, diff --git a/unpublishedScripts/DomainContent/Home/firePit/fire.js b/unpublishedScripts/DomainContent/Home/firePit/fire.js new file mode 100644 index 0000000000..b0ed9a61b6 --- /dev/null +++ b/unpublishedScripts/DomainContent/Home/firePit/fire.js @@ -0,0 +1,165 @@ +// this script turns an entity into an exploder -- anything that collides with it will be vaporized! +// +// + +(function() { + + var _this = this; + + function Fire() { + _this = this; + } + + var RED = { + red: 255, + green: 0, + blue: 0 + }; + + var ORANGE = { + red: 255, + green: 165, + blue: 0 + }; + + var YELLOW = { + red: 255, + green: 255, + blue: 0 + }; + + var GREEN = { + red: 0, + green: 255, + blue: 0 + }; + + var BLUE = { + red: 0, + green: 0, + blue: 255 + }; + + var INDIGO = { + red: 128, + green: 0, + blue: 128 + }; + + var VIOLET = { + red: 75, + green: 0, + blue: 130 + }; + + var colors = [RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET]; + + Fire.prototype = { + preload: function(entityID) { + this.entityID = entityID; + this.EXPLOSION_SOUND = SoundCache.getSound("atp:/firepit/fire_burst.wav"); + + }, + collisionWithEntity: function(myID, otherID, collisionInfo) { + var otherProps = Entities.getEntityProperties(otherID); + var data = null; + try { + data = JSON.parse(otherProps.userData) + } catch (err) { + print('ERROR GETTING USERDATA!'); + } + if (data === null || "") { + return; + } else { + if (data.hasOwnProperty('hifiHomeKey')) { + if (data.hifiHomeKey.reset === true) { + print('FLAMMABLE THING, EXPLODE IT!'); + _this.playSoundAtCurrentPosition(); + _this.explodeWithColor(); + _this.smokePuff(); + Entities.deleteEntity(otherID) + } + } + } + }, + explodeWithColor: function() { + print('EXPLODE!') + var myProps = Entities.getEntityProperties(this.entityID); + var color = colors[Math.floor(Math.random() * colors.length)]; + var explosionParticleProperties = { + "color": color, + "isEmitting": 1, + "maxParticles": 1000, + "lifespan": 0.25, + "emitRate": 1, + "emitSpeed": 0.1, + "speedSpread": 1, + "emitOrientation": Quat.getUp(myProps.rotation), + "emitDimensions": { + "x": 0, + "y": 0, + "z": 0 + }, + "polarStart": 0, + "polarFinish": 0, + "azimuthStart": 0, + "azimuthFinish": 0, + "emitAcceleration": { + "x": 0, + "y": 0, + "z": 0 + }, + "accelerationSpread": { + "x": 0, + "y": 0, + "z": 0 + }, + "particleRadius": 0.829, + "radiusSpread": 0, + "radiusStart": 0.361, + "radiusFinish": 0.294, + "colorSpread": { + "red": 0, + "green": 0, + "blue": 0 + }, + "colorStart": { + "red": 255, + "green": 255, + "blue": 255 + }, + "colorFinish": { + "red": 255, + "green": 255, + "blue": 255 + }, + "alpha": 1, + "alphaSpread": 0, + "alphaStart": -0.2, + "alphaFinish": 0.5, + "emitterShouldTrail": 0, + "textures": "atp:/firepit/explode.png", + "type": "ParticleEffect", + lifetime: 1, + position: myProps.position + }; + + var explosion = Entities.addEntity(explosionParticleProperties); + print('explosion is: ' + explosion) + }, + smokePuff: function() { + //smoke puff here + }, + playSoundAtCurrentPosition: function() { + + var audioProperties = { + volume: 0.5, + position: Entities.getEntityProperties(this.entityID).position + }; + + Audio.playSound(this.EXPLOSION_SOUND, audioProperties); + }, + } + + return new Fire(); +}); \ No newline at end of file diff --git a/unpublishedScripts/DomainContent/Home/firePit/flicker.js b/unpublishedScripts/DomainContent/Home/firePit/flicker.js new file mode 100644 index 0000000000..43148dabba --- /dev/null +++ b/unpublishedScripts/DomainContent/Home/firePit/flicker.js @@ -0,0 +1,51 @@ +(function() { + + var MINIMUM_LIGHT_INTENSITY = 50.0; + var MAXIMUM_LIGHT_INTENSITY = 200.0; + var LIGHT_FALLOFF_RADIUS = 0.1; + var LIGHT_INTENSITY_RANDOMNESS = 0.1; + + function randFloat(low, high) { + return low + Math.random() * (high - low); + } + + var _this; + + function FlickeringFlame() { + _this = this; + } + + var totalTime = 0; + var spacer = 2; + FlickeringFlame.prototype = { + preload: function(entityID) { + this.entityID = entityID; + Script.update.connect(this.update); + }, + update: function(deltaTime) { + + totalTime += deltaTime; + if (totalTime > spacer) { + var howManyAvatars = AvatarList.getAvatarIdentifiers().length; + var intensity = (MINIMUM_LIGHT_INTENSITY + (MAXIMUM_LIGHT_INTENSITY + (Math.sin(totalTime) * MAXIMUM_LIGHT_INTENSITY))); + intensity += randFloat(-LIGHT_INTENSITY_RANDOMNESS, LIGHT_INTENSITY_RANDOMNESS); + + Entities.editEntity(_this.entityID, { + intensity: intensity + }); + + spacer = Math.random(0, 100) * (2 / howManyAvatars); + totalTime = 0; + } else { + //just keep counting + } + }, + unload: function() { + Script.update.disconnect(this.update) + } + } + + return new FlickeringFlame + + +}); \ No newline at end of file diff --git a/unpublishedScripts/DomainContent/Home/reset.js b/unpublishedScripts/DomainContent/Home/reset.js index 6f8dde1212..376ae843e1 100644 --- a/unpublishedScripts/DomainContent/Home/reset.js +++ b/unpublishedScripts/DomainContent/Home/reset.js @@ -37,14 +37,10 @@ var whiteboardPath = Script.resolvePath("atp:/whiteboard/wrapper.js"); - var plantPath = Script.resolvePath("atp:/growingPlant/wrapper.js"); - var cuckooClockPath = Script.resolvePath("atp:/cuckooClock/wrapper.js"); var pingPongGunPath = Script.resolvePath("atp:/pingPongGun/wrapper.js"); - var musicBoxPath = Script.resolvePath("musicBox/wrapper.js?" + Math.random()); - var transformerPath = Script.resolvePath("atp:/dressingRoom/wrapper.js"); Script.include(utilsPath); @@ -54,10 +50,8 @@ Script.include(fishTankPath); Script.include(tiltMazePath); Script.include(whiteboardPath); - Script.include(plantPath); Script.include(cuckooClockPath); Script.include(pingPongGunPath); - // Script.include(musicBoxPath); Script.include(transformerPath); var TRANSFORMER_URL_ROBOT = 'atp:/dressingRoom/simple_robot.fbx'; @@ -204,23 +198,13 @@ }); var whiteboard = new Whiteboard({ - x: 1104, - y: 460.5, - z: -77 + x: 1105.0955, + y: 460.5000, + z: -77.4409 }, { - x: 0, - y: -133, - z: 0 - }); - - var myPlant = new Plant({ - x: 1099.8785, - y: 460.3115, - z: -84.7736 - }, { - x: 0, - y: 0, - z: 0 + x: -0.0013, + y: -133.0056, + z: -0.0013 }); var pingPongGun = new HomePingPongGun({ @@ -234,16 +218,15 @@ }); var cuckooClock = new MyCuckooClock({ - x: 1105.267, - y: 461.44, - z: -81.9495 + x: 1105.5237, + y: 461.4826, + z: -81.7524 }, { - x: 0, - y: -57, - z: 0 + x: -0.0013, + y: -57.0089, + z: -0.0013 }); - // var musicBox = new MusicBox(); print('HOME after creating scripted entities') },