From aaf191b6dc5b27bb6d32a4c1e15191dae9689e31 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 3 Apr 2015 14:31:43 -0700 Subject: [PATCH 01/31] first cut at new avatar preferences UI --- interface/src/Application.cpp | 29 +--- interface/src/Application.h | 5 +- interface/src/avatar/MyAvatar.cpp | 71 +++++++- interface/src/avatar/MyAvatar.h | 24 ++- interface/src/ui/PreferencesDialog.cpp | 125 ++++++++++---- interface/src/ui/PreferencesDialog.h | 18 +- interface/ui/preferencesDialog.ui | 223 ++++++++++++++++++++++++- 7 files changed, 418 insertions(+), 77 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f0324b7361..c2560a9a54 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3743,30 +3743,16 @@ bool Application::askToSetAvatarUrl(const QString& url) { if (msgBox.clickedButton() == headButton) { qDebug() << "Chose to use for head: " << url; - _myAvatar->setFaceModelURL(url); - UserActivityLogger::getInstance().changedModel("head", url); - _myAvatar->sendIdentityPacket(); - emit faceURLChanged(url); + _myAvatar->useHeadURL(url); + emit headURLChanged(url); } else if (msgBox.clickedButton() == bodyButton) { qDebug() << "Chose to use for body: " << url; - _myAvatar->setSkeletonModelURL(url); - // if the head is empty, reset it to the default head. - if (_myAvatar->getFaceModelURLString().isEmpty()) { - _myAvatar->setFaceModelURL(DEFAULT_HEAD_MODEL_URL); - emit faceURLChanged(DEFAULT_HEAD_MODEL_URL.toString()); - UserActivityLogger::getInstance().changedModel("head", DEFAULT_HEAD_MODEL_URL.toString()); - } - UserActivityLogger::getInstance().changedModel("skeleton", url); - _myAvatar->sendIdentityPacket(); - emit skeletonURLChanged(url); + _myAvatar->useBodyURL(url); + emit bodyURLChanged(url); } else if (msgBox.clickedButton() == bodyAndHeadButton) { qDebug() << "Chose to use for body + head: " << url; - _myAvatar->setFaceModelURL(QString()); - _myAvatar->setSkeletonModelURL(url); - UserActivityLogger::getInstance().changedModel("skeleton", url); - _myAvatar->sendIdentityPacket(); - emit faceURLChanged(QString()); - emit skeletonURLChanged(url); + _myAvatar->useFullAvatarURL(url); + emit fullAvatarURLChanged(url); } else { qDebug() << "Declined to use the avatar: " << url; } @@ -4281,8 +4267,7 @@ void Application::checkSkeleton() { msgBox.setIcon(QMessageBox::Warning); msgBox.exec(); - _myAvatar->setSkeletonModelURL(DEFAULT_BODY_MODEL_URL); - _myAvatar->sendIdentityPacket(); + _myAvatar->useBodyURL(DEFAULT_BODY_MODEL_URL); } else { _myAvatar->updateCharacterController(); _physicsEngine.setCharacterController(_myAvatar->getCharacterController()); diff --git a/interface/src/Application.h b/interface/src/Application.h index e9b8deff55..387de78e49 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -335,8 +335,9 @@ signals: void checkBackgroundDownloads(); void domainConnectionRefused(const QString& reason); - void faceURLChanged(const QString& newValue); - void skeletonURLChanged(const QString& newValue); + void headURLChanged(const QString& newValue); + void bodyURLChanged(const QString& newValue); + void fullAvatarURLChanged(const QString& newValue); public slots: void domainChanged(const QString& domainHostname); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index f92523c58f..418f978451 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include "Application.h" #include "AvatarManager.h" @@ -604,9 +605,11 @@ void MyAvatar::saveData() { settings.setValue("leanScale", _leanScale); settings.setValue("scale", _targetScale); - - settings.setValue("faceModelURL", _faceModelURL); - settings.setValue("skeletonModelURL", _skeletonModelURL); + + settings.setValue("useFullAvatar", _useFullAvatar); + settings.setValue("fullAvatarURL", _fullAvatarURLFromPreferences); + settings.setValue("faceModelURL", _headURLFromPreferences); + settings.setValue("skeletonModelURL", _skeletonURLFromPreferences); settings.beginWriteArray("attachmentData"); for (int i = 0; i < _attachmentData.size(); i++) { @@ -667,9 +670,26 @@ void MyAvatar::loadData() { _targetScale = loadSetting(settings, "scale", 1.0f); setScale(_scale); Application::getInstance()->getCamera()->setScale(_scale); + + + // The old preferences only stored the face and skeleton URLs, we didn't track if the user wanted to use 1 or 2 urls + // for their avatar, So we need to attempt to detect this old case and set our new preferences accordingly. If + // the head URL is empty, then we will assume they are using a full url... + _headURLFromPreferences = settings.value("faceModelURL", DEFAULT_HEAD_MODEL_URL).toUrl(); - setFaceModelURL(settings.value("faceModelURL", DEFAULT_HEAD_MODEL_URL).toUrl()); - setSkeletonModelURL(settings.value("skeletonModelURL").toUrl()); + bool assumeFullAvatar = _headURLFromPreferences.isEmpty(); + + _useFullAvatar = settings.value("useFullAvatar", assumeFullAvatar).toBool(); + _fullAvatarURLFromPreferences = settings.value("fullAvatarURL").toUrl(); + _skeletonURLFromPreferences = settings.value("skeletonModelURL").toUrl(); + + if (_useFullAvatar) { + setFaceModelURL(QUrl()); + setSkeletonModelURL(_fullAvatarURLFromPreferences); + } else { + setFaceModelURL(_headURLFromPreferences); + setSkeletonModelURL(_skeletonURLFromPreferences); + } QVector attachmentData; int attachmentCount = settings.beginReadArray("attachmentData"); @@ -902,6 +922,47 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { _billboardValid = false; } +void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL) { + _useFullAvatar = true; + _fullAvatarURLFromPreferences = fullAvatarURL; + + if (!getFaceModelURLString().isEmpty()) { + setFaceModelURL(QString()); + } + + if (fullAvatarURL != getSkeletonModelURL()) { + setSkeletonModelURL(fullAvatarURL); + UserActivityLogger::getInstance().changedModel("skeleton", fullAvatarURL.toString()); + } + sendIdentityPacket(); +} + +void MyAvatar::useHeadURL(const QUrl& headURL) { + useHeadAndBodyURLs(headURL, _skeletonURLFromPreferences); +} + +void MyAvatar::useBodyURL(const QUrl& bodyURL) { + useHeadAndBodyURLs(_headURLFromPreferences, bodyURL); +} + +void MyAvatar::useHeadAndBodyURLs(const QUrl& headURL, const QUrl& bodyURL) { + _useFullAvatar = false; + _headURLFromPreferences = headURL; + _skeletonURLFromPreferences = bodyURL; + + if (headURL != getFaceModelURL()) { + setFaceModelURL(headURL); + UserActivityLogger::getInstance().changedModel("head", headURL.toString()); + } + + if (bodyURL != getSkeletonModelURL()) { + setSkeletonModelURL(bodyURL); + UserActivityLogger::getInstance().changedModel("skeleton", bodyURL.toString()); + } + sendIdentityPacket(); +} + + void MyAvatar::setAttachmentData(const QVector& attachmentData) { Avatar::setAttachmentData(attachmentData); if (QThread::currentThread() != thread()) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 2bc3a4e4ba..57c8ca9e96 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -116,8 +116,17 @@ public: virtual void setJointData(int index, const glm::quat& rotation); virtual void clearJointData(int index); virtual void clearJointsData(); - virtual void setFaceModelURL(const QUrl& faceModelURL); - virtual void setSkeletonModelURL(const QUrl& skeletonModelURL); + + void useFullAvatarURL(const QUrl& fullAvatarURL); + void useHeadURL(const QUrl& headURL); + void useBodyURL(const QUrl& bodyURL); + void useHeadAndBodyURLs(const QUrl& headURL, const QUrl& bodyURL); + + bool getUseFullAvatar() const { return _useFullAvatar; } + const QUrl& getFullAvatarURLFromPreferences() const { return _fullAvatarURLFromPreferences; } + const QUrl& getHeadURLFromPreferences() const { return _headURLFromPreferences; } + const QUrl& getBodyURLFromPreferences() const { return _skeletonURLFromPreferences; } + virtual void setAttachmentData(const QVector& attachmentData); virtual glm::vec3 getSkeletonPosition() const; @@ -185,6 +194,11 @@ protected: virtual void renderAttachments(RenderMode renderMode, RenderArgs* args); private: + + // These are made private for MyAvatar so that you will use the "use" methods instead + virtual void setFaceModelURL(const QUrl& faceModelURL); + virtual void setSkeletonModelURL(const QUrl& skeletonModelURL); + float _turningKeyPressTime; glm::vec3 _gravity; @@ -229,6 +243,12 @@ private: void updatePosition(float deltaTime); void updateCollisionSound(const glm::vec3& penetration, float deltaTime, float frequency); void maybeUpdateBillboard(); + + // Avatar Preferences + bool _useFullAvatar = false; + QUrl _fullAvatarURLFromPreferences; + QUrl _headURLFromPreferences; + QUrl _skeletonURLFromPreferences; }; #endif // hifi_MyAvatar_h diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index bd32fc7c34..4879bbfffc 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -43,28 +43,71 @@ PreferencesDialog::PreferencesDialog(QWidget* parent) : connect(ui.buttonBrowseHead, &QPushButton::clicked, this, &PreferencesDialog::openHeadModelBrowser); connect(ui.buttonBrowseBody, &QPushButton::clicked, this, &PreferencesDialog::openBodyModelBrowser); + connect(ui.buttonBrowseFullAvatar, &QPushButton::clicked, this, &PreferencesDialog::openFullAvatarModelBrowser); + connect(ui.buttonBrowseLocation, &QPushButton::clicked, this, &PreferencesDialog::openSnapshotLocationBrowser); connect(ui.buttonBrowseScriptsLocation, &QPushButton::clicked, this, &PreferencesDialog::openScriptsLocationBrowser); - connect(ui.buttonReloadDefaultScripts, &QPushButton::clicked, - Application::getInstance(), &Application::loadDefaultScripts); + connect(ui.buttonReloadDefaultScripts, &QPushButton::clicked, Application::getInstance(), &Application::loadDefaultScripts); - - connect(Application::getInstance(), &Application::faceURLChanged, this, &PreferencesDialog::faceURLChanged); - connect(Application::getInstance(), &Application::skeletonURLChanged, this, &PreferencesDialog::skeletonURLChanged); + connect(ui.useSeparateBodyAndHead, &QRadioButton::clicked, this, &PreferencesDialog::useSeparateBodyAndHead); + connect(ui.useFullAvatar, &QRadioButton::clicked, this, &PreferencesDialog::useFullAvatar); + + + connect(Application::getInstance(), &Application::headURLChanged, this, &PreferencesDialog::headURLChanged); + connect(Application::getInstance(), &Application::bodyURLChanged, this, &PreferencesDialog::bodyURLChanged); + connect(Application::getInstance(), &Application::fullAvatarURLChanged, this, &PreferencesDialog::fullAvatarURLChanged); // move dialog to left side move(parentWidget()->geometry().topLeft()); setFixedHeight(parentWidget()->size().height() - PREFERENCES_HEIGHT_PADDING); + + ui.bodyNameLabel->setText("Body - name of model here"); + ui.headNameLabel->setText("Head - name of model here"); + ui.fullAvatarNameLabel->setText("Full Avatar - name of model here"); + + UIUtil::scaleWidgetFontSizes(this); } -void PreferencesDialog::faceURLChanged(const QString& newValue) { - ui.faceURLEdit->setText(newValue); +void PreferencesDialog::useSeparateBodyAndHead(bool checked) { + setUseFullAvatar(!checked); + + QUrl headURL(ui.faceURLEdit->text()); + QUrl bodyURL(ui.skeletonURLEdit->text()); + + DependencyManager::get()->getMyAvatar()->useHeadAndBodyURLs(headURL, bodyURL); } -void PreferencesDialog::skeletonURLChanged(const QString& newValue) { +void PreferencesDialog::useFullAvatar(bool checked) { + setUseFullAvatar(checked); + QUrl fullAvatarURL(ui.fullAvatarURLEdit->text()); + DependencyManager::get()->getMyAvatar()->useFullAvatarURL(fullAvatarURL); +} + +void PreferencesDialog::setUseFullAvatar(bool useFullAvatar) { + _useFullAvatar = useFullAvatar; + ui.faceURLEdit->setEnabled(!_useFullAvatar); + ui.skeletonURLEdit->setEnabled(!_useFullAvatar); + ui.fullAvatarURLEdit->setEnabled(_useFullAvatar); + + ui.useFullAvatar->setChecked(_useFullAvatar); + ui.useSeparateBodyAndHead->setChecked(!_useFullAvatar); +} + +void PreferencesDialog::headURLChanged(const QString& newValue) { + ui.faceURLEdit->setText(newValue); + setUseFullAvatar(false); +} + +void PreferencesDialog::bodyURLChanged(const QString& newValue) { ui.skeletonURLEdit->setText(newValue); + setUseFullAvatar(false); +} + +void PreferencesDialog::fullAvatarURLChanged(const QString& newValue) { + ui.fullAvatarURLEdit->setText(newValue); + setUseFullAvatar(true); } void PreferencesDialog::accept() { @@ -82,6 +125,16 @@ void PreferencesDialog::setSkeletonUrl(QString modelUrl) { ui.skeletonURLEdit->setText(modelUrl); } +void PreferencesDialog::openFullAvatarModelBrowser() { + auto MARKETPLACE_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/marketplace?category=avatars"; + auto WIDTH = 900; + auto HEIGHT = 700; + if (!_marketplaceWindow) { + _marketplaceWindow = new WebWindowClass("Marketplace", MARKETPLACE_URL, WIDTH, HEIGHT, false); + } + _marketplaceWindow->setVisible(true); +} + void PreferencesDialog::openHeadModelBrowser() { auto MARKETPLACE_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/marketplace?category=avatars"; auto WIDTH = 900; @@ -143,11 +196,18 @@ void PreferencesDialog::loadPreferences() { _displayNameString = myAvatar->getDisplayName(); ui.displayNameEdit->setText(_displayNameString); - _faceURLString = myAvatar->getHead()->getFaceModel().getURL().toString(); - ui.faceURLEdit->setText(_faceURLString); - _skeletonURLString = myAvatar->getSkeletonModel().getURL().toString(); - ui.skeletonURLEdit->setText(_skeletonURLString); + _useFullAvatar = myAvatar->getUseFullAvatar(); + _fullAvatarURLString = myAvatar->getFullAvatarURLFromPreferences().toString(); + _headURLString = myAvatar->getHeadURLFromPreferences().toString(); + _bodyURLString = myAvatar->getBodyURLFromPreferences().toString(); + + ui.fullAvatarURLEdit->setText(_fullAvatarURLString); + ui.faceURLEdit->setText(_headURLString); + ui.skeletonURLEdit->setText(_bodyURLString); + setUseFullAvatar(_useFullAvatar); + + // TODO: load the names for the models. ui.sendDataCheckBox->setChecked(!menuInstance->isOptionChecked(MenuOption::DisableActivityLogger)); @@ -217,31 +277,26 @@ void PreferencesDialog::savePreferences() { shouldDispatchIdentityPacket = true; } - auto AVATAR_FILE_EXTENSION = ".fst"; - - QUrl faceModelURL(ui.faceURLEdit->text()); - QString faceModelURLString = faceModelURL.toString(); - if (faceModelURLString != _faceURLString) { - if (faceModelURLString.isEmpty() || faceModelURLString.toLower().contains(AVATAR_FILE_EXTENSION)) { - // change the faceModelURL in the profile, it will also update this user's BlendFace - myAvatar->setFaceModelURL(faceModelURL); - UserActivityLogger::getInstance().changedModel("head", faceModelURLString); - shouldDispatchIdentityPacket = true; - } else { - qDebug() << "ERROR: Head model not FST or blank - " << faceModelURLString; - } - } + QUrl headURL(ui.faceURLEdit->text()); + QString headURLString = headURL.toString(); - QUrl skeletonModelURL(ui.skeletonURLEdit->text()); - QString skeletonModelURLString = skeletonModelURL.toString(); - if (skeletonModelURLString != _skeletonURLString) { - if (skeletonModelURLString.isEmpty() || skeletonModelURLString.toLower().contains(AVATAR_FILE_EXTENSION)) { - // change the skeletonModelURL in the profile, it will also update this user's Body - myAvatar->setSkeletonModelURL(skeletonModelURL); - UserActivityLogger::getInstance().changedModel("skeleton", skeletonModelURLString); - shouldDispatchIdentityPacket = true; + QUrl bodyURL(ui.skeletonURLEdit->text()); + QString bodyURLString = bodyURL.toString(); + + QUrl fullAvatarURL(ui.fullAvatarURLEdit->text()); + QString fullAvatarURLString = fullAvatarURL.toString(); + + bool somethingChanged = + _useFullAvatar != myAvatar->getUseFullAvatar() || + fullAvatarURLString != myAvatar->getFullAvatarURLFromPreferences().toString() || + headURLString != myAvatar->getHeadURLFromPreferences().toString() || + bodyURLString != myAvatar->getBodyURLFromPreferences().toString(); + + if (somethingChanged) { + if (_useFullAvatar) { + myAvatar->useFullAvatarURL(fullAvatarURL); } else { - qDebug() << "ERROR: Skeleton model not FST or blank - " << skeletonModelURLString; + myAvatar->useHeadAndBodyURLs(headURL, bodyURL); } } diff --git a/interface/src/ui/PreferencesDialog.h b/interface/src/ui/PreferencesDialog.h index 4daa2d9696..961ef6287d 100644 --- a/interface/src/ui/PreferencesDialog.h +++ b/interface/src/ui/PreferencesDialog.h @@ -33,10 +33,17 @@ private: void savePreferences(); void openHeadModelBrowser(); void openBodyModelBrowser(); + void openFullAvatarModelBrowser(); + void setUseFullAvatar(bool useFullAvatar); Ui_PreferencesDialog ui; - QString _faceURLString; - QString _skeletonURLString; + + bool _useFullAvatar; + QString _headURLString; + QString _bodyURLString; + QString _fullAvatarURLString; + + QString _displayNameString; WebWindowClass* _marketplaceWindow = NULL; @@ -47,8 +54,11 @@ private slots: void setSkeletonUrl(QString modelUrl); void openSnapshotLocationBrowser(); void openScriptsLocationBrowser(); - void faceURLChanged(const QString& newValue); - void skeletonURLChanged(const QString& newValue); + void headURLChanged(const QString& newValue); + void bodyURLChanged(const QString& newValue); + void fullAvatarURLChanged(const QString& newValue); + void useSeparateBodyAndHead(bool checked); + void useFullAvatar(bool checked); }; diff --git a/interface/ui/preferencesDialog.ui b/interface/ui/preferencesDialog.ui index d295d094c2..4a0b1e961a 100644 --- a/interface/ui/preferencesDialog.ui +++ b/interface/ui/preferencesDialog.ui @@ -198,8 +198,194 @@ 7 + + + + + + + + 0 + 0 + + + + + 32 + 28 + + + + + 0 + 0 + + + + + Arial + + + + Use single avatar with Body and Head + + + + 0 + 0 + + + + + + + + + + + 0 + + + 10 + + + 7 + + + 7 + + + - + + + + Arial + + + + Full Avatar + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + fullAvatarURLEdit + + + + + + + + 0 + + + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 5 + 20 + + + + + + + + + Arial + + + + Browse + + + + 0 + 0 + + + + + + + + + + + + + + 0 + 0 + + + + + 32 + 28 + + + + + 0 + 0 + + + + + Arial + + + + Use separate Body and Head avatar files + + + + 0 + 0 + + + + + + + + + + 0 + + + 10 + + + 7 + + + 7 + + + + + + Arial @@ -211,11 +397,11 @@ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - snapshotLocationEdit - + + + @@ -260,21 +446,28 @@ + + + - + 0 + + 10 + 7 7 + - + Arial @@ -290,9 +483,10 @@ skeletonURLEdit + - + 0 @@ -344,6 +538,20 @@ + + + + + + + + + + + + + + @@ -665,6 +873,7 @@ + From 1a463a025697043d9848b83275231c58cdf0ea0a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 3 Apr 2015 17:03:22 -0700 Subject: [PATCH 02/31] more work on improved avatar UI adding model names and backward compatible support --- interface/src/Application.cpp | 33 +++++-------- interface/src/Application.h | 6 +-- interface/src/avatar/MyAvatar.cpp | 66 +++++++++++++++++++------- interface/src/avatar/MyAvatar.h | 16 +++++-- interface/src/ui/PreferencesDialog.cpp | 19 ++++---- interface/src/ui/PreferencesDialog.h | 6 +-- libraries/avatars/src/AvatarData.h | 2 + libraries/fbx/src/FSTReader.cpp | 21 ++++++++ libraries/fbx/src/FSTReader.h | 1 + 9 files changed, 115 insertions(+), 55 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c2560a9a54..c2bab11065 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3689,17 +3689,7 @@ bool Application::askToSetAvatarUrl(const QString& url) { } // Download the FST file, to attempt to determine its model type - QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); - QNetworkRequest networkRequest = QNetworkRequest(url); - networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); - QNetworkReply* reply = networkAccessManager.get(networkRequest); - qDebug() << "Downloading avatar file at " << url; - QEventLoop loop; - QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); - loop.exec(); - QByteArray fstContents = reply->readAll(); - delete reply; - QVariantHash fstMapping = FSTReader::readMapping(fstContents); + QVariantHash fstMapping = FSTReader::downloadMapping(url); FSTReader::ModelType modelType = FSTReader::predictModelType(fstMapping); @@ -3710,26 +3700,27 @@ bool Application::askToSetAvatarUrl(const QString& url) { QPushButton* bodyButton = NULL; QPushButton* bodyAndHeadButton = NULL; + QString modelName = fstMapping["name"].toString(); QString message; QString typeInfo; switch (modelType) { case FSTReader::HEAD_MODEL: - message = QString("Would you like to use '") + fstMapping["name"].toString() + QString("' for your avatar head?"); + message = QString("Would you like to use '") + modelName + QString("' for your avatar head?"); headButton = msgBox.addButton(tr("Yes"), QMessageBox::ActionRole); break; case FSTReader::BODY_ONLY_MODEL: - message = QString("Would you like to use '") + fstMapping["name"].toString() + QString("' for your avatar body?"); + message = QString("Would you like to use '") + modelName + QString("' for your avatar body?"); bodyButton = msgBox.addButton(tr("Yes"), QMessageBox::ActionRole); break; case FSTReader::HEAD_AND_BODY_MODEL: - message = QString("Would you like to use '") + fstMapping["name"].toString() + QString("' for your avatar?"); + message = QString("Would you like to use '") + modelName + QString("' for your avatar?"); bodyAndHeadButton = msgBox.addButton(tr("Yes"), QMessageBox::ActionRole); break; default: - message = QString("Would you like to use '") + fstMapping["name"].toString() + QString("' for some part of your avatar head?"); + message = QString("Would you like to use '") + modelName + QString("' for some part of your avatar head?"); headButton = msgBox.addButton(tr("Use for Head"), QMessageBox::ActionRole); bodyButton = msgBox.addButton(tr("Use for Body"), QMessageBox::ActionRole); bodyAndHeadButton = msgBox.addButton(tr("Use for Body and Head"), QMessageBox::ActionRole); @@ -3743,16 +3734,16 @@ bool Application::askToSetAvatarUrl(const QString& url) { if (msgBox.clickedButton() == headButton) { qDebug() << "Chose to use for head: " << url; - _myAvatar->useHeadURL(url); - emit headURLChanged(url); + _myAvatar->useHeadURL(url, modelName); + emit headURLChanged(url, modelName); } else if (msgBox.clickedButton() == bodyButton) { qDebug() << "Chose to use for body: " << url; - _myAvatar->useBodyURL(url); - emit bodyURLChanged(url); + _myAvatar->useBodyURL(url, modelName); + emit bodyURLChanged(url, modelName); } else if (msgBox.clickedButton() == bodyAndHeadButton) { qDebug() << "Chose to use for body + head: " << url; - _myAvatar->useFullAvatarURL(url); - emit fullAvatarURLChanged(url); + _myAvatar->useFullAvatarURL(url, modelName); + emit fullAvatarURLChanged(url, modelName); } else { qDebug() << "Declined to use the avatar: " << url; } diff --git a/interface/src/Application.h b/interface/src/Application.h index 387de78e49..57a2f07216 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -335,9 +335,9 @@ signals: void checkBackgroundDownloads(); void domainConnectionRefused(const QString& reason); - void headURLChanged(const QString& newValue); - void bodyURLChanged(const QString& newValue); - void fullAvatarURLChanged(const QString& newValue); + void headURLChanged(const QString& newValue, const QString& modelName); + void bodyURLChanged(const QString& newValue, const QString& modelName); + void fullAvatarURLChanged(const QString& newValue, const QString& modelName); public slots: void domainChanged(const QString& domainHostname); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 418f978451..085b7bccab 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -610,7 +610,10 @@ void MyAvatar::saveData() { settings.setValue("fullAvatarURL", _fullAvatarURLFromPreferences); settings.setValue("faceModelURL", _headURLFromPreferences); settings.setValue("skeletonModelURL", _skeletonURLFromPreferences); - + settings.setValue("headModelName", _headModelName); + settings.setValue("bodyModelName", _bodyModelName); + settings.setValue("fullAvatarModelName", _fullAvatarModelName); + settings.beginWriteArray("attachmentData"); for (int i = 0; i < _attachmentData.size(); i++) { settings.setArrayIndex(i); @@ -675,20 +678,48 @@ void MyAvatar::loadData() { // The old preferences only stored the face and skeleton URLs, we didn't track if the user wanted to use 1 or 2 urls // for their avatar, So we need to attempt to detect this old case and set our new preferences accordingly. If // the head URL is empty, then we will assume they are using a full url... - _headURLFromPreferences = settings.value("faceModelURL", DEFAULT_HEAD_MODEL_URL).toUrl(); - - bool assumeFullAvatar = _headURLFromPreferences.isEmpty(); + bool isOldSettings = !(settings.contains("useFullAvatar") || settings.contains("fullAvatarURL")); - _useFullAvatar = settings.value("useFullAvatar", assumeFullAvatar).toBool(); + _useFullAvatar = settings.value("useFullAvatar").toBool(); + _headURLFromPreferences = settings.value("faceModelURL", DEFAULT_HEAD_MODEL_URL).toUrl(); _fullAvatarURLFromPreferences = settings.value("fullAvatarURL").toUrl(); _skeletonURLFromPreferences = settings.value("skeletonModelURL").toUrl(); - + _headModelName = settings.value("headModelName").toString(); + _bodyModelName = settings.value("bodyModelName").toString(); + _fullAvatarModelName = settings.value("fullAvatarModelName").toString();; + + if (isOldSettings) { + bool assumeFullAvatar = _headURLFromPreferences.isEmpty(); + _useFullAvatar = assumeFullAvatar; + + if (_useFullAvatar) { + _fullAvatarURLFromPreferences = settings.value("skeletonModelURL").toUrl(); + _headURLFromPreferences = DEFAULT_HEAD_MODEL_URL; + _skeletonURLFromPreferences = DEFAULT_BODY_MODEL_URL; + + QVariantHash fullAvatarFST = FSTReader::downloadMapping(_fullAvatarURLFromPreferences.toString()); + + _headModelName = "Default"; + _bodyModelName = "Default"; + _fullAvatarModelName = fullAvatarFST["name"].toString(); + + } else { + _fullAvatarURLFromPreferences = DEFAULT_FULL_AVATAR_MODEL_URL; + _skeletonURLFromPreferences = settings.value("skeletonModelURL").toUrl(); + + QVariantHash headFST = FSTReader::downloadMapping(_headURLFromPreferences.toString()); + QVariantHash bodyFST = FSTReader::downloadMapping(_skeletonURLFromPreferences.toString()); + + _headModelName = headFST["name"].toString(); + _bodyModelName = bodyFST["name"].toString(); + _fullAvatarModelName = "Default"; + } + } + if (_useFullAvatar) { - setFaceModelURL(QUrl()); - setSkeletonModelURL(_fullAvatarURLFromPreferences); + useFullAvatarURL(_fullAvatarURLFromPreferences, _fullAvatarModelName); } else { - setFaceModelURL(_headURLFromPreferences); - setSkeletonModelURL(_skeletonURLFromPreferences); + useHeadAndBodyURLs(_headURLFromPreferences, _skeletonURLFromPreferences, _headModelName, _bodyModelName); } QVector attachmentData; @@ -922,9 +953,10 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { _billboardValid = false; } -void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL) { +void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelName) { _useFullAvatar = true; _fullAvatarURLFromPreferences = fullAvatarURL; + _fullAvatarModelName = modelName; if (!getFaceModelURLString().isEmpty()) { setFaceModelURL(QString()); @@ -937,18 +969,20 @@ void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL) { sendIdentityPacket(); } -void MyAvatar::useHeadURL(const QUrl& headURL) { - useHeadAndBodyURLs(headURL, _skeletonURLFromPreferences); +void MyAvatar::useHeadURL(const QUrl& headURL, const QString& modelName) { + useHeadAndBodyURLs(headURL, _skeletonURLFromPreferences, modelName, _bodyModelName); } -void MyAvatar::useBodyURL(const QUrl& bodyURL) { - useHeadAndBodyURLs(_headURLFromPreferences, bodyURL); +void MyAvatar::useBodyURL(const QUrl& bodyURL, const QString& modelName) { + useHeadAndBodyURLs(_headURLFromPreferences, bodyURL, _headModelName, modelName); } -void MyAvatar::useHeadAndBodyURLs(const QUrl& headURL, const QUrl& bodyURL) { +void MyAvatar::useHeadAndBodyURLs(const QUrl& headURL, const QUrl& bodyURL, const QString& headName, const QString& bodyName) { _useFullAvatar = false; _headURLFromPreferences = headURL; _skeletonURLFromPreferences = bodyURL; + _headModelName = headName; + _bodyModelName = bodyName; if (headURL != getFaceModelURL()) { setFaceModelURL(headURL); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 57c8ca9e96..9c1f78c696 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -117,16 +117,20 @@ public: virtual void clearJointData(int index); virtual void clearJointsData(); - void useFullAvatarURL(const QUrl& fullAvatarURL); - void useHeadURL(const QUrl& headURL); - void useBodyURL(const QUrl& bodyURL); - void useHeadAndBodyURLs(const QUrl& headURL, const QUrl& bodyURL); + void useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelName = QString()); + void useHeadURL(const QUrl& headURL, const QString& modelName = QString()); + void useBodyURL(const QUrl& bodyURL, const QString& modelName = QString()); + void useHeadAndBodyURLs(const QUrl& headURL, const QUrl& bodyURL, const QString& headName = QString(), const QString& bodyName = QString()); bool getUseFullAvatar() const { return _useFullAvatar; } const QUrl& getFullAvatarURLFromPreferences() const { return _fullAvatarURLFromPreferences; } const QUrl& getHeadURLFromPreferences() const { return _headURLFromPreferences; } const QUrl& getBodyURLFromPreferences() const { return _skeletonURLFromPreferences; } + const QString& getHeadModelName() const { return _headModelName; } + const QString& getBodyModelName() const { return _bodyModelName; } + const QString& getFullAvartarModelName() const { return _fullAvatarModelName; } + virtual void setAttachmentData(const QVector& attachmentData); virtual glm::vec3 getSkeletonPosition() const; @@ -249,6 +253,10 @@ private: QUrl _fullAvatarURLFromPreferences; QUrl _headURLFromPreferences; QUrl _skeletonURLFromPreferences; + + QString _headModelName; + QString _bodyModelName; + QString _fullAvatarModelName; }; #endif // hifi_MyAvatar_h diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 4879bbfffc..9b6cd03dfa 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -61,11 +61,11 @@ PreferencesDialog::PreferencesDialog(QWidget* parent) : move(parentWidget()->geometry().topLeft()); setFixedHeight(parentWidget()->size().height() - PREFERENCES_HEIGHT_PADDING); - - ui.bodyNameLabel->setText("Body - name of model here"); - ui.headNameLabel->setText("Head - name of model here"); - ui.fullAvatarNameLabel->setText("Full Avatar - name of model here"); - + auto myAvatar = DependencyManager::get()->getMyAvatar(); + + ui.bodyNameLabel->setText("Body - " + myAvatar->getBodyModelName()); + ui.headNameLabel->setText("Head - " + myAvatar->getHeadModelName()); + ui.fullAvatarNameLabel->setText("Full Avatar - " + myAvatar->getFullAvartarModelName()); UIUtil::scaleWidgetFontSizes(this); } @@ -95,19 +95,22 @@ void PreferencesDialog::setUseFullAvatar(bool useFullAvatar) { ui.useSeparateBodyAndHead->setChecked(!_useFullAvatar); } -void PreferencesDialog::headURLChanged(const QString& newValue) { +void PreferencesDialog::headURLChanged(const QString& newValue, const QString& modelName) { ui.faceURLEdit->setText(newValue); setUseFullAvatar(false); + ui.headNameLabel->setText("Head - " + modelName); } -void PreferencesDialog::bodyURLChanged(const QString& newValue) { +void PreferencesDialog::bodyURLChanged(const QString& newValue, const QString& modelName) { ui.skeletonURLEdit->setText(newValue); setUseFullAvatar(false); + ui.bodyNameLabel->setText("Body - " + modelName); } -void PreferencesDialog::fullAvatarURLChanged(const QString& newValue) { +void PreferencesDialog::fullAvatarURLChanged(const QString& newValue, const QString& modelName) { ui.fullAvatarURLEdit->setText(newValue); setUseFullAvatar(true); + ui.fullAvatarNameLabel->setText("Full Avatar - " + modelName); } void PreferencesDialog::accept() { diff --git a/interface/src/ui/PreferencesDialog.h b/interface/src/ui/PreferencesDialog.h index 961ef6287d..3f097ca9ab 100644 --- a/interface/src/ui/PreferencesDialog.h +++ b/interface/src/ui/PreferencesDialog.h @@ -54,9 +54,9 @@ private slots: void setSkeletonUrl(QString modelUrl); void openSnapshotLocationBrowser(); void openScriptsLocationBrowser(); - void headURLChanged(const QString& newValue); - void bodyURLChanged(const QString& newValue); - void fullAvatarURLChanged(const QString& newValue); + void headURLChanged(const QString& newValue, const QString& modelName); + void bodyURLChanged(const QString& newValue, const QString& modelName); + void fullAvatarURLChanged(const QString& newValue, const QString& modelName); void useSeparateBodyAndHead(bool checked); void useFullAvatar(bool checked); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index ad90c88aaa..eb94557bd5 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -103,6 +103,8 @@ const int AVATAR_BILLBOARD_PACKET_SEND_INTERVAL_MSECS = 5000; const QUrl DEFAULT_HEAD_MODEL_URL = QUrl("http://public.highfidelity.io/models/heads/defaultAvatar_head.fst"); const QUrl DEFAULT_BODY_MODEL_URL = QUrl("http://public.highfidelity.io/models/skeletons/defaultAvatar_body.fst"); +const QUrl DEFAULT_FULL_AVATAR_MODEL_URL = QUrl("http://public.highfidelity.io/marketplace/contents/029db3d4-da2c-4cb2-9c08-b9612ba576f5/02949063e7c4aed42ad9d1a58461f56d.fst"); + // Where one's own Avatar begins in the world (will be overwritten if avatar data file is found). // This is the start location in the Sandbox (xyz: 6270, 211, 6000). diff --git a/libraries/fbx/src/FSTReader.cpp b/libraries/fbx/src/FSTReader.cpp index 6a5cc2bd53..d7f0ff4e70 100644 --- a/libraries/fbx/src/FSTReader.cpp +++ b/libraries/fbx/src/FSTReader.cpp @@ -10,6 +10,13 @@ // #include +#include +#include +#include + +#include +#include +#include #include "FSTReader.h" @@ -169,3 +176,17 @@ FSTReader::ModelType FSTReader::predictModelType(const QVariantHash& mapping) { return ENTITY_MODEL; } + +QVariantHash FSTReader::downloadMapping(const QString& url) { + QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); + QNetworkRequest networkRequest = QNetworkRequest(url); + networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); + QNetworkReply* reply = networkAccessManager.get(networkRequest); + qDebug() << "Downloading avatar file at " << url; + QEventLoop loop; + QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); + loop.exec(); + QByteArray fstContents = reply->readAll(); + delete reply; + return FSTReader::readMapping(fstContents); +} \ No newline at end of file diff --git a/libraries/fbx/src/FSTReader.h b/libraries/fbx/src/FSTReader.h index 5752a224c6..981bae4feb 100644 --- a/libraries/fbx/src/FSTReader.h +++ b/libraries/fbx/src/FSTReader.h @@ -51,6 +51,7 @@ public: static QString getNameFromType(ModelType modelType); static FSTReader::ModelType getTypeFromName(const QString& name); + static QVariantHash downloadMapping(const QString& url); private: static void writeVariant(QBuffer& buffer, QVariantHash::const_iterator& it); From 50479d5d5e831b8179fde125c2f3922ecbec1735 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 3 Apr 2015 17:06:54 -0700 Subject: [PATCH 03/31] set name to Default when using default url --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c2bab11065..1f044a5a0f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4258,7 +4258,7 @@ void Application::checkSkeleton() { msgBox.setIcon(QMessageBox::Warning); msgBox.exec(); - _myAvatar->useBodyURL(DEFAULT_BODY_MODEL_URL); + _myAvatar->useBodyURL(DEFAULT_BODY_MODEL_URL, "Default"); } else { _myAvatar->updateCharacterController(); _physicsEngine.setCharacterController(_myAvatar->getCharacterController()); From 0bc1b028954c586d828a27b3e4517f9288185993 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 3 Apr 2015 17:24:53 -0700 Subject: [PATCH 04/31] improvements to tracking model names --- interface/src/Application.cpp | 1 + interface/src/avatar/MyAvatar.cpp | 36 +++++++++++++++++++++----- interface/src/ui/PreferencesDialog.cpp | 1 + 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1f044a5a0f..6befbe2555 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3747,6 +3747,7 @@ bool Application::askToSetAvatarUrl(const QString& url) { } else { qDebug() << "Declined to use the avatar: " << url; } + return true; } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 085b7bccab..3073bbb219 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -955,8 +955,16 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelName) { _useFullAvatar = true; - _fullAvatarURLFromPreferences = fullAvatarURL; - _fullAvatarModelName = modelName; + + if (_fullAvatarURLFromPreferences != fullAvatarURL) { + _fullAvatarURLFromPreferences = fullAvatarURL; + if (modelName.isEmpty()) { + QVariantHash fullAvatarFST = FSTReader::downloadMapping(_fullAvatarURLFromPreferences.toString()); + _fullAvatarModelName = fullAvatarFST["name"].toString(); + } else { + _fullAvatarModelName = modelName; + } + } if (!getFaceModelURLString().isEmpty()) { setFaceModelURL(QString()); @@ -979,10 +987,26 @@ void MyAvatar::useBodyURL(const QUrl& bodyURL, const QString& modelName) { void MyAvatar::useHeadAndBodyURLs(const QUrl& headURL, const QUrl& bodyURL, const QString& headName, const QString& bodyName) { _useFullAvatar = false; - _headURLFromPreferences = headURL; - _skeletonURLFromPreferences = bodyURL; - _headModelName = headName; - _bodyModelName = bodyName; + + if (_headURLFromPreferences != headURL) { + _headURLFromPreferences = headURL; + if (headName.isEmpty()) { + QVariantHash headFST = FSTReader::downloadMapping(_headURLFromPreferences.toString()); + _headModelName = headFST["name"].toString(); + } else { + _headModelName = headName; + } + } + + if (_skeletonURLFromPreferences != bodyURL) { + _skeletonURLFromPreferences = bodyURL; + if (bodyName.isEmpty()) { + QVariantHash bodyFST = FSTReader::downloadMapping(_skeletonURLFromPreferences.toString()); + _bodyModelName = bodyFST["name"].toString(); + } else { + _bodyModelName = bodyName; + } + } if (headURL != getFaceModelURL()) { setFaceModelURL(headURL); diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 9b6cd03dfa..bc10109c36 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -271,6 +271,7 @@ void PreferencesDialog::loadPreferences() { void PreferencesDialog::savePreferences() { MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); + bool shouldDispatchIdentityPacket = false; QString displayNameStr(ui.displayNameEdit->text()); From 7f4c577e8073d2398ae8498407ef6f60280059b4 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 3 Apr 2015 17:25:39 -0700 Subject: [PATCH 05/31] end of file --- libraries/fbx/src/FSTReader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/fbx/src/FSTReader.cpp b/libraries/fbx/src/FSTReader.cpp index d7f0ff4e70..32be82b392 100644 --- a/libraries/fbx/src/FSTReader.cpp +++ b/libraries/fbx/src/FSTReader.cpp @@ -189,4 +189,4 @@ QVariantHash FSTReader::downloadMapping(const QString& url) { QByteArray fstContents = reply->readAll(); delete reply; return FSTReader::readMapping(fstContents); -} \ No newline at end of file +} From 69484ad00b960a00423405342533d939a13ed303 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Sun, 12 Apr 2015 17:36:45 -0700 Subject: [PATCH 06/31] Creating the Framebuffer class and the companion Swapbuffer --- libraries/gpu/src/gpu/Format.h | 1 + libraries/gpu/src/gpu/Framebuffer.cpp | 267 ++++++++++++++++++++++++++ libraries/gpu/src/gpu/Framebuffer.h | 195 +++++++++++++++++++ 3 files changed, 463 insertions(+) create mode 100755 libraries/gpu/src/gpu/Framebuffer.cpp create mode 100755 libraries/gpu/src/gpu/Framebuffer.h diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index 7f36797374..aee6f3bdf4 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -34,6 +34,7 @@ typedef glm::mat3 Mat3; typedef glm::vec4 Vec4; typedef glm::vec3 Vec3; typedef glm::vec2 Vec2; +typedef glm::ivec2 Vec2i; // Description of a scalar type enum Type { diff --git a/libraries/gpu/src/gpu/Framebuffer.cpp b/libraries/gpu/src/gpu/Framebuffer.cpp new file mode 100755 index 0000000000..597a31788e --- /dev/null +++ b/libraries/gpu/src/gpu/Framebuffer.cpp @@ -0,0 +1,267 @@ +// +// Framebuffer.cpp +// libraries/gpu/src/gpu +// +// Created by Sam Gateau on 4/12/2015. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "Framebuffer.h" +#include +#include + +using namespace gpu; + +Framebuffer::Framebuffer() +{ +} + +Framebuffer::~Framebuffer() +{ +} + +Framebuffer* Framebuffer::create() { + auto framebuffer = new Framebuffer(); + framebuffer->_renderBuffers.resize(MAX_NUM_RENDER_BUFFERS); + framebuffer->_renderBuffersSubresource.resize(MAX_NUM_RENDER_BUFFERS, 0); + return framebuffer; +} + +Framebuffer* Framebuffer::create( const Format& colorBufferFormat, const Format& depthStencilBufferFormat, uint16 width, uint16 height, uint16 numSamples) { + auto framebuffer = Framebuffer::create(); + + auto colorTexture = TexturePointer(Texture::create2D(colorBufferFormat, width, height)); + auto depthTexture = TexturePointer(Texture::create2D(depthStencilBufferFormat, width, height)); + + framebuffer->setRenderBuffer(0, colorTexture); + framebuffer->setDepthStencilBuffer(depthTexture); + + return framebuffer; +} + + +bool Framebuffer::isSwapchain() const { + return _swapchain != 0; +} + +uint32 Framebuffer::getFrameCount() const { + if (_swapchain) { + return _swapchain->getFrameCount(); + } else { + return _frameCount; + } +} + +bool Framebuffer::isEmpty() const { + return (_buffersMask == 0); +} + +bool Framebuffer::validateTargetCompatibility(const Texture& texture, uint32 subresource) const { + if (texture.getType() == Texture::TEX_1D) { + return false; + } + + if (isEmpty()) { + return true; + } else { + if ((texture.getWidth() == getWidth()) && + (texture.getHeight() == getHeight()) && + (texture.getNumSamples() == getNumSamples())) { + return true; + } else { + return false; + } + } +} + +void Framebuffer::updateSize(const TexturePointer& texture) { + if (!isEmpty()) { + return; + } + + if (texture) { + _width = texture->getWidth(); + _height = texture->getHeight(); + _numSamples = texture->getNumSamples(); + } else { + _width = _height = _numSamples = 0; + } +} + +void Framebuffer::resize(uint16 width, uint16 height, uint16 numSamples) { + if (width && height && numSamples && !isEmpty() && !isSwapchain()) { + if ((width != _width) || (height != _height) || (numSamples != _numSamples)) { + for (uint32 i = 0; i < _renderBuffers.size(); ++i) { + if (_renderBuffers[i]) { + _renderBuffers[i]->resize2D(width, height, numSamples); + _numSamples = _renderBuffers[i]->getNumSamples(); + } + } + + if (_depthStencilBuffer) { + _depthStencilBuffer->resize2D(width, height, numSamples); + _numSamples = _depthStencilBuffer->getNumSamples(); + } + + _width = width; + _height = height; + // _numSamples = numSamples; + } + } +} + +uint16 Framebuffer::getWidth() const { + if (isSwapchain()) { + return getSwapchain()->getWidth(); + } else { + return _width; + } +} + +uint16 Framebuffer::getHeight() const { + if (isSwapchain()) { + return getSwapchain()->getHeight(); + } else { + return _height; + } +} + +uint16 Framebuffer::getNumSamples() const { + if (isSwapchain()) { + return getSwapchain()->getNumSamples(); + } else { + return _numSamples; + } +} + +// Render buffers +int Framebuffer::setRenderBuffer(uint32 slot, const TexturePointer& texture, uint32 subresource) { + if (isSwapchain()) { + return -1; + } + + // Check for the slot + if (slot >= getMaxNumRenderBuffers()) { + return -1; + } + + // Check for the compatibility of size + if (texture) { + if (!validateTargetCompatibility(*texture, subresource)) { + return -1; + } + } + + // everything works, assign + // dereference the previously used buffer if exists + if (_renderBuffers[slot]) { + _renderBuffers[slot].reset(); + _renderBuffersSubresource[slot] = 0; + } + + updateSize(texture); + + // assign the new one + _renderBuffers[slot] = texture; + + // Assign the subresource + _renderBuffersSubresource[slot] = subresource; + + // update the mask + int mask = (1< + +namespace gpu { + +typedef Element Format; + +class Viewport { +public: + int32 width = 1; + int32 height = 1; + int32 top = 0; + int32 left = 0; + float zmin = 0.f; + float zmax = 1.f; + + Viewport() {} + Viewport(int32 w, int32 h, int32 t = 0, int32 l = 0, float zin = 0.f, float zax = 1.f): + width(w), + height(h), + top(t), + left(l), + zmin(zin), + zmax(zax) + {} + Viewport(const Vec2i& wh, const Vec2i& tl = Vec2i(0), const Vec2& zrange = Vec2(0.f, 1.f)): + width(wh.x), + height(wh.y), + top(tl.x), + left(tl.y), + zmin(zrange.x), + zmax(zrange.y) + {} + ~Viewport() {} +}; + +class Swapchain { +public: + // Properties + uint16 getWidth() const { return _width; } + uint16 getHeight() const { return _height; } + uint16 getNumSamples() const { return _numSamples; } + + bool hasDepthStencil() const { return _hasDepthStencil; } + bool isFullscreen() const { return _isFullscreen; } + + uint32 getSwapInterval() const { return _swapInterval; } + + bool isStereo() const { return _isStereo; } + + uint32 getFrameCount() const { return _frameCount; } + + // Pure interface + void setSwapInterval(uint32 interval); + + void resize(uint16 width, uint16 height); + void setFullscreen(bool fullscreen); + + Swapchain() {} + Swapchain(const Swapchain& swapchain) {} + virtual ~Swapchain() {} + +protected: + mutable uint32 _frameCount = 0; + + Format _colorFormat; + uint16 _width = 1; + uint16 _height = 1; + uint16 _numSamples = 1; + uint16 _swapInterval = 0; + + bool _hasDepthStencil = false; + bool _isFullscreen = false; + bool _isStereo = false; + + // Non exposed + + friend class Framebuffer; +}; +typedef std::shared_ptr SwapchainPointer; + + +class Framebuffer { +public: + enum BufferMask { + BUFFER_COLOR0 = 1, + BUFFER_COLOR1 = 2, + BUFFER_COLOR2 = 4, + BUFFER_COLOR3 = 8, + BUFFER_COLOR4 = 16, + BUFFER_COLOR5 = 32, + BUFFER_COLOR6 = 64, + BUFFER_COLOR7 = 128, + BUFFER_COLORS = 0x000000FF, + + BUFFER_DEPTH = 0x40000000, + BUFFER_STENCIL = 0x80000000, + BUFFER_DEPTHSTENCIL = 0xC0000000, + }; + + ~Framebuffer(); + + static Framebuffer* create(const SwapchainPointer& swapchain); + static Framebuffer* create(); + static Framebuffer* create(const Format& colorBufferFormat, const Format& depthStencilBufferFormat, uint16 width, uint16 height, uint16 samples ); + + bool isSwapchain() const; + SwapchainPointer getSwapchain() const { return _swapchain; } + + uint32 getFrameCount() const; + + // Render buffers + int32 setRenderBuffer(uint32 slot, const TexturePointer& texture, uint32 subresource = 0); + void removeRenderBuffers(); + uint32 getNumRenderBuffers() const; + + TexturePointer getRenderBuffer(uint32 slot) const; + uint32 getRenderBufferSubresource(uint32 slot) const; + + bool setDepthStencilBuffer(const TexturePointer& texture, uint32 subresource = 0); + TexturePointer getDepthStencilBuffer() const; + uint32 getDepthStencilBufferSubresource() const; + + // Properties + uint32 getBuffersMask() const { return _buffersMask; } + bool isEmpty() const; + + bool validateTargetCompatibility(const Texture& texture, uint32 subresource = 0) const; + + uint16 getWidth() const; + uint16 getHeight() const; + uint16 getNumSamples() const; + + float getAspectRatio() const { return getWidth() / (float) getHeight() ; } + + // If not a swapchain canvas, resize can resize all the render buffers and depth stencil attached in one call + void resize( uint16 width, uint16 height, uint16 samples = 1 ); + + static const uint32 MAX_NUM_RENDER_BUFFERS = 8; + static uint32 getMaxNumRenderBuffers() { return MAX_NUM_RENDER_BUFFERS; } + + // Get viewport covering the ful Canvas + Viewport getViewport() const { return Viewport(getWidth(), getHeight(), 0, 0); } + + +protected: + + Viewport _viewport; + + uint16 _width; + uint16 _height; + uint16 _numSamples; + + uint32 _buffersMask; + + uint32 _frameCount; + + SwapchainPointer _swapchain; + + Textures _renderBuffers; + std::vector _renderBuffersSubresource; + + TexturePointer _depthStencilBuffer; + uint32 _depthStencilBufferSubresource; + + + void updateSize(const TexturePointer& texture); + + // Non exposed + Framebuffer(const Framebuffer& framebuffer) {} + Framebuffer(); + + // This shouldn't be used by anything else than the Backend class with the proper casting. + mutable GPUObject* _gpuObject = NULL; + void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; } + GPUObject* getGPUObject() const { return _gpuObject; } + friend class Backend; +}; + +} + +#endif \ No newline at end of file From 05689c0413034de614601e4b89d984208e9ffefd Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 13 Apr 2015 11:13:30 -0700 Subject: [PATCH 07/31] Bringin the Framebuffer to GLBackend and refining the interface --- libraries/gpu/src/gpu/Batch.cpp | 13 +++- libraries/gpu/src/gpu/Batch.h | 8 +++ libraries/gpu/src/gpu/Context.h | 31 ++++++---- libraries/gpu/src/gpu/Framebuffer.cpp | 38 ++++-------- libraries/gpu/src/gpu/Framebuffer.h | 13 ++-- libraries/gpu/src/gpu/GLBackend.cpp | 6 +- libraries/gpu/src/gpu/GLBackend.h | 29 +++++++-- libraries/gpu/src/gpu/GLBackendOutput.cpp | 72 +++++++++++++++++++++++ libraries/gpu/src/gpu/Texture.h | 14 ++++- 9 files changed, 169 insertions(+), 55 deletions(-) create mode 100755 libraries/gpu/src/gpu/GLBackendOutput.cpp diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 9eb9648478..4b145b55a0 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -25,7 +25,8 @@ Batch::Batch() : _textures(), _streamFormats(), _transforms(), - _pipelines() + _pipelines(), + _framebuffers() { } @@ -41,7 +42,8 @@ void Batch::clear() { _textures.clear(); _streamFormats.clear(); _transforms.clear(); - _pipelines.clear(); + _pipelines.clear(); + _framebuffers.clear(); } uint32 Batch::cacheData(uint32 size, const void* data) { @@ -186,3 +188,10 @@ void Batch::setUniformTexture(uint32 slot, const TextureView& view) { setUniformTexture(slot, view._texture); } +void Batch::setFramebuffer(const FramebufferPointer& framebuffer) { + ADD_COMMAND(setUniformTexture); + + _params.push_back(_framebuffers.cache(framebuffer)); + +} + diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 6e8a2d1da6..b6bc05ab40 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -23,6 +23,8 @@ #include "Pipeline.h" +#include "Framebuffer.h" + #if defined(NSIGHT_FOUND) #include "nvToolsExt.h" class ProfileRange { @@ -112,6 +114,8 @@ public: void setUniformTexture(uint32 slot, const TexturePointer& view); void setUniformTexture(uint32 slot, const TextureView& view); // not a command, just a shortcut from a TextureView + // Framebuffer Stage + void setFramebuffer(const FramebufferPointer& framebuffer); // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long @@ -170,6 +174,8 @@ public: COMMAND_setUniformBuffer, COMMAND_setUniformTexture, + COMMAND_setFramebuffer, + // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API @@ -266,6 +272,7 @@ public: typedef Cache::Vector StreamFormatCaches; typedef Cache::Vector TransformCaches; typedef Cache::Vector PipelineCaches; + typedef Cache::Vector FramebufferCaches; // Cache Data in a byte array if too big to fit in Param // FOr example Mat4s are going there @@ -289,6 +296,7 @@ public: StreamFormatCaches _streamFormats; TransformCaches _transforms; PipelineCaches _pipelines; + FramebufferCaches _framebuffers; protected: }; diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index 8276ff5f95..022ca02d6d 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -15,8 +15,8 @@ #include "Resource.h" #include "Texture.h" -#include "Shader.h" #include "Pipeline.h" +#include "Framebuffer.h" namespace gpu { @@ -47,8 +47,8 @@ public: }; template< typename T > - static void setGPUObject(const Buffer& buffer, T* bo) { - buffer.setGPUObject(bo); + static void setGPUObject(const Buffer& buffer, T* object) { + buffer.setGPUObject(object); } template< typename T > static T* getGPUObject(const Buffer& buffer) { @@ -56,8 +56,8 @@ public: } template< typename T > - static void setGPUObject(const Texture& texture, T* to) { - texture.setGPUObject(to); + static void setGPUObject(const Texture& texture, T* object) { + texture.setGPUObject(object); } template< typename T > static T* getGPUObject(const Texture& texture) { @@ -65,8 +65,8 @@ public: } template< typename T > - static void setGPUObject(const Shader& shader, T* so) { - shader.setGPUObject(so); + static void setGPUObject(const Shader& shader, T* object) { + shader.setGPUObject(object); } template< typename T > static T* getGPUObject(const Shader& shader) { @@ -74,8 +74,8 @@ public: } template< typename T > - static void setGPUObject(const Pipeline& pipeline, T* po) { - pipeline.setGPUObject(po); + static void setGPUObject(const Pipeline& pipeline, T* object) { + pipeline.setGPUObject(object); } template< typename T > static T* getGPUObject(const Pipeline& pipeline) { @@ -83,14 +83,23 @@ public: } template< typename T > - static void setGPUObject(const State& state, T* so) { - state.setGPUObject(so); + static void setGPUObject(const State& state, T* object) { + state.setGPUObject(object); } template< typename T > static T* getGPUObject(const State& state) { return reinterpret_cast(state.getGPUObject()); } + template< typename T > + static void setGPUObject(const Framebuffer& framebuffer, T* object) { + framebuffer.setGPUObject(object); + } + template< typename T > + static T* getGPUObject(const Framebuffer& framebuffer) { + return reinterpret_cast(framebuffer.getGPUObject()); + } + protected: }; diff --git a/libraries/gpu/src/gpu/Framebuffer.cpp b/libraries/gpu/src/gpu/Framebuffer.cpp index 597a31788e..de8961886b 100755 --- a/libraries/gpu/src/gpu/Framebuffer.cpp +++ b/libraries/gpu/src/gpu/Framebuffer.cpp @@ -26,7 +26,6 @@ Framebuffer::~Framebuffer() Framebuffer* Framebuffer::create() { auto framebuffer = new Framebuffer(); framebuffer->_renderBuffers.resize(MAX_NUM_RENDER_BUFFERS); - framebuffer->_renderBuffersSubresource.resize(MAX_NUM_RENDER_BUFFERS, 0); return framebuffer; } @@ -96,14 +95,14 @@ void Framebuffer::resize(uint16 width, uint16 height, uint16 numSamples) { if ((width != _width) || (height != _height) || (numSamples != _numSamples)) { for (uint32 i = 0; i < _renderBuffers.size(); ++i) { if (_renderBuffers[i]) { - _renderBuffers[i]->resize2D(width, height, numSamples); - _numSamples = _renderBuffers[i]->getNumSamples(); + _renderBuffers[i]._texture->resize2D(width, height, numSamples); + _numSamples = _renderBuffers[i]._texture->getNumSamples(); } } if (_depthStencilBuffer) { - _depthStencilBuffer->resize2D(width, height, numSamples); - _numSamples = _depthStencilBuffer->getNumSamples(); + _depthStencilBuffer._texture->resize2D(width, height, numSamples); + _numSamples = _depthStencilBuffer._texture->getNumSamples(); } _width = width; @@ -155,20 +154,10 @@ int Framebuffer::setRenderBuffer(uint32 slot, const TexturePointer& texture, uin } } - // everything works, assign - // dereference the previously used buffer if exists - if (_renderBuffers[slot]) { - _renderBuffers[slot].reset(); - _renderBuffersSubresource[slot] = 0; - } - updateSize(texture); // assign the new one - _renderBuffers[slot] = texture; - - // Assign the subresource - _renderBuffersSubresource[slot] = subresource; + _renderBuffers[slot] = TextureView(texture, subresource); // update the mask int mask = (1< _renderBuffersSubresource; - - TexturePointer _depthStencilBuffer; - uint32 _depthStencilBufferSubresource; + TextureViews _renderBuffers; + TextureView _depthStencilBuffer; + bool _isDefined = false; void updateSize(const TexturePointer& texture); @@ -189,6 +185,7 @@ protected: GPUObject* getGPUObject() const { return _gpuObject; } friend class Backend; }; +typedef std::shared_ptr FramebufferPointer; } diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 8fcc2362c1..c9de132b73 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -32,6 +32,9 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_setUniformBuffer), (&::gpu::GLBackend::do_setUniformTexture), + (&::gpu::GLBackend::do_setFramebuffer), + + (&::gpu::GLBackend::do_glEnable), (&::gpu::GLBackend::do_glDisable), @@ -67,7 +70,8 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = GLBackend::GLBackend() : _input(), _transform(), - _pipeline() + _pipeline(), + _output() { initTransform(); } diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index ea97fd8908..e3069f5205 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -133,14 +133,25 @@ public: class GLPipeline : public GPUObject { public: - GLShader* _program; - GLState* _state; + GLShader* _program = 0; + GLState* _state = 0; GLPipeline(); ~GLPipeline(); }; static GLPipeline* syncGPUObject(const Pipeline& pipeline); + + class GLFramebuffer : public GPUObject { + public: + GLuint _fbo = 0; + + GLFramebuffer(); + ~GLFramebuffer(); + }; + static GLFramebuffer* syncGPUObject(const Framebuffer& framebuffer); + static GLuint getFramebufferID(const FramebufferPointer& framebuffer); + static const int MAX_NUM_ATTRIBUTES = Stream::NUM_INPUT_SLOTS; static const int MAX_NUM_INPUT_BUFFERS = 16; @@ -276,8 +287,8 @@ protected: State::Signature _stateSignatureCache; GLState* _state; - bool _invalidState; - bool _needStateSync; + bool _invalidState = false; + bool _needStateSync = true; PipelineStageState() : _pipeline(), @@ -291,6 +302,16 @@ protected: {} } _pipeline; + // Output stage + void do_setFramebuffer(Batch& batch, uint32 paramOffset); + + struct OutputStageState { + + FramebufferPointer _framebuffer = nullptr; + + OutputStageState() {} + } _output; + // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API diff --git a/libraries/gpu/src/gpu/GLBackendOutput.cpp b/libraries/gpu/src/gpu/GLBackendOutput.cpp new file mode 100755 index 0000000000..8865008e49 --- /dev/null +++ b/libraries/gpu/src/gpu/GLBackendOutput.cpp @@ -0,0 +1,72 @@ +// +// GLBackendTexture.cpp +// libraries/gpu/src/gpu +// +// Created by Sam Gateau on 1/19/2015. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "GPULogging.h" +#include "GLBackendShared.h" + + +GLBackend::GLFramebuffer::GLFramebuffer() +{} + +GLBackend::GLFramebuffer::~GLFramebuffer() { + if (_fbo != 0) { + glDeleteFramebuffers(1, &_fbo); + } +} + +GLBackend::GLFramebuffer* GLBackend::syncGPUObject(const Framebuffer& framebuffer) { + GLFramebuffer* object = Backend::getGPUObject(framebuffer); + + // If GPU object already created and in sync + bool needUpdate = false; + if (object) { + return object; + } else if (!framebuffer.isDefined()) { + // NO framebuffer definition yet so let's avoid thinking + return nullptr; + } + + // need to have a gpu object? + if (!object) { + object = new GLFramebuffer(); + glGenFramebuffers(1, &object->_fbo); + CHECK_GL_ERROR(); + Backend::setGPUObject(framebuffer, object); + } + + + CHECK_GL_ERROR(); + + return object; +} + + + +GLuint GLBackend::getFramebufferID(const FramebufferPointer& framebuffer) { + if (!framebuffer) { + return 0; + } + GLFramebuffer* object = GLBackend::syncGPUObject(*framebuffer); + if (object) { + return object->_fbo; + } else { + return 0; + } +} + +void GLBackend::do_setFramebuffer(Batch& batch, uint32 paramOffset) { + auto framebuffer = batch._framebuffers.get(batch._params[paramOffset]._uint); + + if (_output._framebuffer != framebuffer) { + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, getFramebufferID(framebuffer)); + _output._framebuffer = framebuffer; + } +} + diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 3eed52c686..cb124b7b08 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -240,15 +240,25 @@ public: _subresource(0), _element(element) {}; - TextureView(const TexturePointer& texture, const Element& element) : + TextureView(const TexturePointer& texture, uint16 subresource, const Element& element) : _texture(texture), - _subresource(0), + _subresource(subresource), _element(element) {}; + + TextureView(const TexturePointer& texture, uint16 subresource) : + _texture(texture), + _subresource(subresource) + {}; + ~TextureView() {} TextureView(const TextureView& view) = default; TextureView& operator=(const TextureView& view) = default; + + explicit operator bool() const { return (_texture); } + bool operator !() const { return (!_texture); } }; +typedef std::vector TextureViews; }; From 51ce3129b9c3e715ba5610d1cd98ec4be09142bd Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 13 Apr 2015 12:22:08 -0700 Subject: [PATCH 08/31] connecting the dots for a framebuffer GLBackend, need to be tested --- libraries/gpu/src/gpu/Framebuffer.cpp | 29 ++++--- libraries/gpu/src/gpu/Framebuffer.h | 14 ++-- libraries/gpu/src/gpu/GLBackendOutput.cpp | 99 +++++++++++++++++++++-- 3 files changed, 119 insertions(+), 23 deletions(-) diff --git a/libraries/gpu/src/gpu/Framebuffer.cpp b/libraries/gpu/src/gpu/Framebuffer.cpp index de8961886b..cb33a930ca 100755 --- a/libraries/gpu/src/gpu/Framebuffer.cpp +++ b/libraries/gpu/src/gpu/Framebuffer.cpp @@ -36,7 +36,7 @@ Framebuffer* Framebuffer::create( const Format& colorBufferFormat, const Format& auto depthTexture = TexturePointer(Texture::create2D(depthStencilBufferFormat, width, height)); framebuffer->setRenderBuffer(0, colorTexture); - framebuffer->setDepthStencilBuffer(depthTexture); + framebuffer->setDepthStencilBuffer(depthTexture, depthStencilBufferFormat); return framebuffer; } @@ -54,10 +54,6 @@ uint32 Framebuffer::getFrameCount() const { } } -bool Framebuffer::isEmpty() const { - return (_buffersMask == 0); -} - bool Framebuffer::validateTargetCompatibility(const Texture& texture, uint32 subresource) const { if (texture.getType() == Texture::TEX_1D) { return false; @@ -161,9 +157,9 @@ int Framebuffer::setRenderBuffer(uint32 slot, const TexturePointer& texture, uin // update the mask int mask = (1<getDepthStencilBufferFormat(); + return _depthStencilBuffer._element; + } else { + return _depthStencilBuffer._element; + } +} \ No newline at end of file diff --git a/libraries/gpu/src/gpu/Framebuffer.h b/libraries/gpu/src/gpu/Framebuffer.h index 46303b0d81..9253cd021e 100755 --- a/libraries/gpu/src/gpu/Framebuffer.h +++ b/libraries/gpu/src/gpu/Framebuffer.h @@ -123,20 +123,24 @@ public: uint32 getFrameCount() const; // Render buffers - int32 setRenderBuffer(uint32 slot, const TexturePointer& texture, uint32 subresource = 0); void removeRenderBuffers(); uint32 getNumRenderBuffers() const; + const TextureViews& getRenderBuffers() const { return _renderBuffers; } + int32 setRenderBuffer(uint32 slot, const TexturePointer& texture, uint32 subresource = 0); TexturePointer getRenderBuffer(uint32 slot) const; uint32 getRenderBufferSubresource(uint32 slot) const; - bool setDepthStencilBuffer(const TexturePointer& texture, uint32 subresource = 0); + bool setDepthStencilBuffer(const TexturePointer& texture, const Format& format, uint32 subresource = 0); TexturePointer getDepthStencilBuffer() const; uint32 getDepthStencilBufferSubresource() const; + Format getDepthStencilBufferFormat() const; // Properties - uint32 getBuffersMask() const { return _buffersMask; } - bool isEmpty() const; + uint32 getBufferMask() const { return _bufferMask; } + bool isEmpty() const { return (_bufferMask == 0); } + bool hasColor() const { return (getBufferMask() & BUFFER_COLORS); } + bool hasDepthStencil() const { return (getBufferMask() & BUFFER_DEPTHSTENCIL); } bool validateTargetCompatibility(const Texture& texture, uint32 subresource = 0) const; @@ -162,7 +166,7 @@ protected: uint16 _height; uint16 _numSamples; - uint32 _buffersMask; + uint32 _bufferMask; uint32 _frameCount; diff --git a/libraries/gpu/src/gpu/GLBackendOutput.cpp b/libraries/gpu/src/gpu/GLBackendOutput.cpp index 8865008e49..877ecce950 100755 --- a/libraries/gpu/src/gpu/GLBackendOutput.cpp +++ b/libraries/gpu/src/gpu/GLBackendOutput.cpp @@ -35,15 +35,102 @@ GLBackend::GLFramebuffer* GLBackend::syncGPUObject(const Framebuffer& framebuffe // need to have a gpu object? if (!object) { - object = new GLFramebuffer(); - glGenFramebuffers(1, &object->_fbo); + GLuint fbo; + glGenFramebuffers(1, &fbo); CHECK_GL_ERROR(); + + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); + + unsigned int nbColorBuffers = 0; + GLenum colorBuffers[16]; + if (framebuffer.hasColor()) { + static const GLenum colorAttachments[] = { + GL_COLOR_ATTACHMENT0, + GL_COLOR_ATTACHMENT1, + GL_COLOR_ATTACHMENT2, + GL_COLOR_ATTACHMENT3, + GL_COLOR_ATTACHMENT4, + GL_COLOR_ATTACHMENT5, + GL_COLOR_ATTACHMENT6, + GL_COLOR_ATTACHMENT7, + GL_COLOR_ATTACHMENT8, + GL_COLOR_ATTACHMENT9, + GL_COLOR_ATTACHMENT10, + GL_COLOR_ATTACHMENT11, + GL_COLOR_ATTACHMENT12, + GL_COLOR_ATTACHMENT13, + GL_COLOR_ATTACHMENT14, + GL_COLOR_ATTACHMENT15 }; + + int unit = 0; + for (auto& b : framebuffer.getRenderBuffers()) { + auto surface = b._texture; + if (surface) { + auto gltexture = GLBackend::syncGPUObject(*surface); + if (gltexture) { + glFramebufferTexture2D(GL_FRAMEBUFFER, colorAttachments[unit], GL_TEXTURE_2D, gltexture->_texture, 0); + } + colorBuffers[nbColorBuffers] = colorAttachments[unit]; + nbColorBuffers++; + unit++; + } + } + } + + if (framebuffer.hasDepthStencil()) { + auto surface = framebuffer.getDepthStencilBuffer(); + if (surface) { + auto gltexture = GLBackend::syncGPUObject(*surface); + if (gltexture) { + if (surface) + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, gltexture->_texture, 0); + } + } + } + + // Last but not least, define where we draw + if (nbColorBuffers > 0) { + glDrawBuffers(nbColorBuffers, colorBuffers); + } else { + glDrawBuffer( GL_NONE ); + } + + // Now check for completness + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + bool result = false; + switch (status) { + case GL_FRAMEBUFFER_COMPLETE : + // Success ! + result = true; + break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT : + qCDebug(gpulogging) << "GLFramebuffer::syncGPUObject : Framebuffer not valid, GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT."; + break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT : + qCDebug(gpulogging) << "GLFramebuffer::syncGPUObject : Framebuffer not valid, GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT."; + break; + case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER : + qCDebug(gpulogging) << "GLFramebuffer::syncGPUObject : Framebuffer not valid, GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER."; + break; + case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER : + qCDebug(gpulogging) << "GLFramebuffer::syncGPUObject : Framebuffer not valid, GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER."; + break; + case GL_FRAMEBUFFER_UNSUPPORTED : + qCDebug(gpulogging) << "GLFramebuffer::syncGPUObject : Framebuffer not valid, GL_FRAMEBUFFER_UNSUPPORTED."; + break; + } + if (!result && fbo) { + glDeleteFramebuffers( 1, &fbo ); + return nullptr; + } + + + // All is green, assign the gpuobject to the Framebuffer + object = new GLFramebuffer(); + object->_fbo = fbo; Backend::setGPUObject(framebuffer, object); } - - CHECK_GL_ERROR(); - return object; } @@ -69,4 +156,4 @@ void GLBackend::do_setFramebuffer(Batch& batch, uint32 paramOffset) { _output._framebuffer = framebuffer; } } - + From d2b643d389833bc7479f7cd1f278b02b4061e872 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Mon, 13 Apr 2015 23:57:08 +0100 Subject: [PATCH 09/31] Add targetVelocity into MyAvatar simulation MyAvatar sets a target velocity to achieve, this is parsed in the preSimulation controller step. --- interface/src/avatar/MyAvatar.cpp | 14 +++++++------- libraries/avatars/src/AvatarData.cpp | 1 + libraries/avatars/src/AvatarData.h | 2 ++ .../physics/src/DynamicCharacterController.cpp | 3 ++- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 6b70577754..be438f3297 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -126,7 +126,7 @@ void MyAvatar::reset() { _skeletonModel.reset(); getHead()->reset(); - _velocity = glm::vec3(0.0f); + _targetVelocity = glm::vec3(0.0f); setThrust(glm::vec3(0.0f)); // Reset the pitch and roll components of the avatar's orientation, preserve yaw direction glm::vec3 eulers = safeEulerAngles(getOrientation()); @@ -1240,28 +1240,28 @@ glm::vec3 MyAvatar::applyScriptedMotor(float deltaTime, const glm::vec3& localVe void MyAvatar::updatePosition(float deltaTime) { // rotate velocity into camera frame glm::quat rotation = getHead()->getCameraOrientation(); - glm::vec3 localVelocity = glm::inverse(rotation) * _velocity; + glm::vec3 localVelocity = glm::inverse(rotation) * _targetVelocity; bool isHovering = _characterController.isHovering(); glm::vec3 newLocalVelocity = applyKeyboardMotor(deltaTime, localVelocity, isHovering); newLocalVelocity = applyScriptedMotor(deltaTime, newLocalVelocity); // rotate back into world-frame - _velocity = rotation * newLocalVelocity; + _targetVelocity = rotation * newLocalVelocity; - _velocity += _thrust * deltaTime; + _targetVelocity += _thrust * deltaTime; _thrust = glm::vec3(0.0f); // cap avatar speed - float speed = glm::length(_velocity); + float speed = glm::length(_targetVelocity); if (speed > MAX_AVATAR_SPEED) { - _velocity *= MAX_AVATAR_SPEED / speed; + _targetVelocity *= MAX_AVATAR_SPEED / speed; speed = MAX_AVATAR_SPEED; } if (speed > MIN_AVATAR_SPEED && !_characterController.isEnabled()) { // update position ourselves - applyPositionDelta(deltaTime * _velocity); + applyPositionDelta(deltaTime * _targetVelocity); measureMotionDerivatives(deltaTime); } // else physics will move avatar later diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index bc49fb3514..a8d2c209c3 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -60,6 +60,7 @@ AvatarData::AvatarData() : _owningAvatarMixer(), _lastUpdateTimer(), _velocity(0.0f), + _targetVelocity(0.0f), _localAABox(DEFAULT_LOCAL_AABOX_CORNER, DEFAULT_LOCAL_AABOX_SCALE) { } diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index ad90c88aaa..881b68d52f 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -294,6 +294,7 @@ public: void setVelocity(const glm::vec3 velocity) { _velocity = velocity; } Q_INVOKABLE glm::vec3 getVelocity() const { return _velocity; } + glm::vec3 getTargetVelocity() const { return _targetVelocity; } public slots: void sendAvatarDataPacket(); @@ -384,6 +385,7 @@ protected: void changeReferential(Referential* ref); glm::vec3 _velocity; + glm::vec3 _targetVelocity; AABox _localAABox; diff --git a/libraries/physics/src/DynamicCharacterController.cpp b/libraries/physics/src/DynamicCharacterController.cpp index db84bea540..15b7eb86b6 100644 --- a/libraries/physics/src/DynamicCharacterController.cpp +++ b/libraries/physics/src/DynamicCharacterController.cpp @@ -386,7 +386,7 @@ void DynamicCharacterController::preSimulation(btScalar timeStep) { setHovering(true); } - _walkVelocity = glmToBullet(_avatarData->getVelocity()); + _walkVelocity = glmToBullet(_avatarData->getTargetVelocity()); if (_pendingFlags & PENDING_FLAG_JUMP) { _pendingFlags &= ~ PENDING_FLAG_JUMP; @@ -408,6 +408,7 @@ void DynamicCharacterController::postSimulation() { _avatarData->setOrientation(rotation); _avatarData->setPosition(position - rotation * _shapeLocalOffset); + _avatarData->setVelocity(bulletToGLM(_rigidBody->getLinearVelocity())); } } From c34c5f60758039f4aaddb4aa4396d79dea09cd88 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 14 Apr 2015 08:47:52 -0700 Subject: [PATCH 10/31] adding the Fremabuffer to be used for shadows and main rendering --- interface/src/Application.cpp | 21 ++- libraries/gpu/src/gpu/Format.h | 3 +- libraries/gpu/src/gpu/Framebuffer.cpp | 8 ++ libraries/gpu/src/gpu/Framebuffer.h | 18 ++- libraries/gpu/src/gpu/GLBackendOutput.cpp | 5 +- libraries/gpu/src/gpu/GLBackendTexture.cpp | 34 +++++ .../src/DeferredLightingEffect.cpp | 23 +++- libraries/render-utils/src/GlowEffect.cpp | 23 +++- libraries/render-utils/src/Model.cpp | 125 ++++-------------- libraries/render-utils/src/TextureCache.cpp | 124 ++++++++++++++++- libraries/render-utils/src/TextureCache.h | 31 ++++- 11 files changed, 276 insertions(+), 139 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 82447257fb..3fe03476a3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -798,7 +798,8 @@ void Application::paintGL() { DependencyManager::get()->prepare(); // Viewport is assigned to the size of the framebuffer - QSize size = DependencyManager::get()->getPrimaryFramebufferObject()->size(); + // QSize size = DependencyManager::get()->getPrimaryFramebufferObject()->size(); + QSize size = DependencyManager::get()->getFrameBufferSize(); glViewport(0, 0, size.width(), size.height()); glMatrixMode(GL_MODELVIEW); @@ -2636,8 +2637,12 @@ void Application::updateShadowMap() { activeRenderingThread = QThread::currentThread(); PerformanceTimer perfTimer("shadowMap"); - QOpenGLFramebufferObject* fbo = DependencyManager::get()->getShadowFramebufferObject(); - fbo->bind(); +// QOpenGLFramebufferObject* fbo = DependencyManager::get()->getShadowFramebufferObject(); +// fbo->bind(); + auto shadowFramebuffer = DependencyManager::get()->getShadowFramebuffer(); + GLuint shadowFBO = gpu::GLBackend::getFramebufferID(shadowFramebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, shadowFBO); + glEnable(GL_DEPTH_TEST); glClear(GL_DEPTH_BUFFER_BIT); @@ -2653,16 +2658,18 @@ void Application::updateShadowMap() { loadViewFrustum(_myCamera, _viewFrustum); int matrixCount = 1; - int targetSize = fbo->width(); + //int targetSize = fbo->width(); + int sourceSize = shadowFramebuffer->getWidth(); + int targetSize = shadowFramebuffer->getWidth(); float targetScale = 1.0f; if (Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows)) { matrixCount = CASCADED_SHADOW_MATRIX_COUNT; - targetSize = fbo->width() / 2; + targetSize = sourceSize / 2; targetScale = 0.5f; } for (int i = 0; i < matrixCount; i++) { const glm::vec2& coord = MAP_COORDS[i]; - glViewport(coord.s * fbo->width(), coord.t * fbo->height(), targetSize, targetSize); + glViewport(coord.s * sourceSize, coord.t * sourceSize, targetSize, targetSize); // if simple shadow then since the resolution is twice as much as with cascaded, cover 2 regions with the map, not just one int regionIncrement = (matrixCount == 1 ? 2 : 1); @@ -2785,7 +2792,7 @@ void Application::updateShadowMap() { glMatrixMode(GL_MODELVIEW); } - fbo->release(); + // fbo->release(); glViewport(0, 0, _glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); activeRenderingThread = nullptr; diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index aee6f3bdf4..d3330fd147 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -119,7 +119,8 @@ enum Semantic { INDEX, //used by index buffer of a mesh PART, // used by part buffer of a mesh - DEPTH, // Depth buffer + DEPTH, // Depth only buffer + STENCIL, // Stencil only buffer DEPTH_STENCIL, // Depth Stencil buffer SRGB, diff --git a/libraries/gpu/src/gpu/Framebuffer.cpp b/libraries/gpu/src/gpu/Framebuffer.cpp index cb33a930ca..f671dba28e 100755 --- a/libraries/gpu/src/gpu/Framebuffer.cpp +++ b/libraries/gpu/src/gpu/Framebuffer.cpp @@ -41,6 +41,14 @@ Framebuffer* Framebuffer::create( const Format& colorBufferFormat, const Format& return framebuffer; } +Framebuffer* Framebuffer::createShadowmap(uint16 width) { + auto framebuffer = Framebuffer::create(); + auto depthTexture = TexturePointer(Texture::create2D(Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH), width, width)); + + framebuffer->setDepthStencilBuffer(depthTexture, Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH)); + + return framebuffer; +} bool Framebuffer::isSwapchain() const { return _swapchain != 0; diff --git a/libraries/gpu/src/gpu/Framebuffer.h b/libraries/gpu/src/gpu/Framebuffer.h index 9253cd021e..8028d1b478 100755 --- a/libraries/gpu/src/gpu/Framebuffer.h +++ b/libraries/gpu/src/gpu/Framebuffer.h @@ -116,6 +116,7 @@ public: static Framebuffer* create(const SwapchainPointer& swapchain); static Framebuffer* create(); static Framebuffer* create(const Format& colorBufferFormat, const Format& depthStencilBufferFormat, uint16 width, uint16 height, uint16 samples ); + static Framebuffer* createShadowmap(uint16 width); bool isSwapchain() const; SwapchainPointer getSwapchain() const { return _swapchain; } @@ -136,6 +137,7 @@ public: uint32 getDepthStencilBufferSubresource() const; Format getDepthStencilBufferFormat() const; + // Properties uint32 getBufferMask() const { return _bufferMask; } bool isEmpty() const { return (_bufferMask == 0); } @@ -157,26 +159,22 @@ public: static uint32 getMaxNumRenderBuffers() { return MAX_NUM_RENDER_BUFFERS; } // Get viewport covering the ful Canvas - Viewport getViewport() const { return Viewport(getWidth(), getHeight(), 0, 0); } - - bool isDefined() const { return _isDefined; } + Viewport getViewport() const { return Viewport(getWidth(), getHeight(), 0, 0); } protected: - uint16 _width; - uint16 _height; - uint16 _numSamples; + uint16 _width = 0; + uint16 _height = 0; + uint16 _numSamples = 0; - uint32 _bufferMask; + uint32 _bufferMask = 0; - uint32 _frameCount; + uint32 _frameCount = 0; SwapchainPointer _swapchain; TextureViews _renderBuffers; TextureView _depthStencilBuffer; - bool _isDefined = false; - void updateSize(const TexturePointer& texture); // Non exposed diff --git a/libraries/gpu/src/gpu/GLBackendOutput.cpp b/libraries/gpu/src/gpu/GLBackendOutput.cpp index 877ecce950..9b3fb5fe34 100755 --- a/libraries/gpu/src/gpu/GLBackendOutput.cpp +++ b/libraries/gpu/src/gpu/GLBackendOutput.cpp @@ -28,7 +28,7 @@ GLBackend::GLFramebuffer* GLBackend::syncGPUObject(const Framebuffer& framebuffe bool needUpdate = false; if (object) { return object; - } else if (!framebuffer.isDefined()) { + } else if (framebuffer.isEmpty()) { // NO framebuffer definition yet so let's avoid thinking return nullptr; } @@ -39,7 +39,7 @@ GLBackend::GLFramebuffer* GLBackend::syncGPUObject(const Framebuffer& framebuffe glGenFramebuffers(1, &fbo); CHECK_GL_ERROR(); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); unsigned int nbColorBuffers = 0; GLenum colorBuffers[16]; @@ -82,7 +82,6 @@ GLBackend::GLFramebuffer* GLBackend::syncGPUObject(const Framebuffer& framebuffe if (surface) { auto gltexture = GLBackend::syncGPUObject(*surface); if (gltexture) { - if (surface) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, gltexture->_texture, 0); } } diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index 2bbb3d633f..da6d993171 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -144,7 +144,38 @@ public: texel.internalFormat = GL_RED; break; case gpu::DEPTH: + texel.format = GL_DEPTH_COMPONENT; // It's depth component to load it texel.internalFormat = GL_DEPTH_COMPONENT; + switch (dstFormat.getType()) { + case gpu::UINT32: + case gpu::INT32: + case gpu::NUINT32: + case gpu::NINT32: { + texel.internalFormat = GL_DEPTH_COMPONENT32; + break; + } + case gpu::NFLOAT: + case gpu::FLOAT: { + texel.internalFormat = GL_DEPTH_COMPONENT32F; + break; + } + case gpu::UINT16: + case gpu::INT16: + case gpu::NUINT16: + case gpu::NINT16: + case gpu::HALF: + case gpu::NHALF: { + texel.internalFormat = GL_DEPTH_COMPONENT16; + break; + } + case gpu::UINT8: + case gpu::INT8: + case gpu::NUINT8: + case gpu::NINT8: { + texel.internalFormat = GL_DEPTH_COMPONENT24; + break; + } + } break; default: qCDebug(gpulogging) << "Unknown combination of texel format"; @@ -306,6 +337,9 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) { if (bytes && texture.isAutogenerateMips()) { glGenerateMipmap(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); } // At this point the mip piels have been loaded, we can notify diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index a4f45802a4..c5a09a4f0f 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -183,15 +183,17 @@ void DeferredLightingEffect::render() { auto textureCache = DependencyManager::get(); - QOpenGLFramebufferObject* primaryFBO = textureCache->getPrimaryFramebufferObject(); - primaryFBO->release(); + // QOpenGLFramebufferObject* primaryFBO = textureCache->getPrimaryFramebufferObject(); + // primaryFBO->release(); + QSize framebufferSize = textureCache->getFrameBufferSize(); QOpenGLFramebufferObject* freeFBO = DependencyManager::get()->getFreeFramebufferObject(); freeFBO->bind(); glClear(GL_COLOR_BUFFER_BIT); // glEnable(GL_FRAMEBUFFER_SRGB); - glBindTexture(GL_TEXTURE_2D, primaryFBO->texture()); + // glBindTexture(GL_TEXTURE_2D, primaryFBO->texture()); + glBindTexture(GL_TEXTURE_2D, textureCache->getPrimaryColorTextureID()); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, textureCache->getPrimaryNormalTextureID()); @@ -209,11 +211,17 @@ void DeferredLightingEffect::render() { const int VIEWPORT_Y_INDEX = 1; const int VIEWPORT_WIDTH_INDEX = 2; const int VIEWPORT_HEIGHT_INDEX = 3; - float sMin = viewport[VIEWPORT_X_INDEX] / (float)primaryFBO->width(); + /* float sMin = viewport[VIEWPORT_X_INDEX] / (float)primaryFBO->width(); float sWidth = viewport[VIEWPORT_WIDTH_INDEX] / (float)primaryFBO->width(); float tMin = viewport[VIEWPORT_Y_INDEX] / (float)primaryFBO->height(); float tHeight = viewport[VIEWPORT_HEIGHT_INDEX] / (float)primaryFBO->height(); - + */ + float sMin = viewport[VIEWPORT_X_INDEX] / (float)framebufferSize.width(); + float sWidth = viewport[VIEWPORT_WIDTH_INDEX] / (float)framebufferSize.width(); + float tMin = viewport[VIEWPORT_Y_INDEX] / (float)framebufferSize.height(); + float tHeight = viewport[VIEWPORT_HEIGHT_INDEX] / (float)framebufferSize.height(); + + // Fetch the ViewMatrix; glm::mat4 invViewMat; _viewState->getViewTransform().getMatrix(invViewMat); @@ -437,7 +445,10 @@ void DeferredLightingEffect::render() { glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); glColorMask(true, true, true, false); - primaryFBO->bind(); + auto primaryFBO = gpu::GLBackend::getFramebufferID(textureCache->getPrimaryOpaqueFramebuffer()); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, primaryFBO); + + //primaryFBO->bind(); glBindTexture(GL_TEXTURE_2D, freeFBO->texture()); glEnable(GL_TEXTURE_2D); diff --git a/libraries/render-utils/src/GlowEffect.cpp b/libraries/render-utils/src/GlowEffect.cpp index 2ba1d7df13..2399cfa1a7 100644 --- a/libraries/render-utils/src/GlowEffect.cpp +++ b/libraries/render-utils/src/GlowEffect.cpp @@ -24,6 +24,7 @@ #include "TextureCache.h" #include "RenderUtilsLogging.h" +#include "gpu/GLBackend.h" GlowEffect::GlowEffect() : _initialized(false), @@ -105,7 +106,11 @@ int GlowEffect::getDeviceHeight() const { void GlowEffect::prepare() { - DependencyManager::get()->getPrimaryFramebufferObject()->bind(); + //DependencyManager::get()->getPrimaryFramebufferObject()->bind(); + auto primaryFBO = DependencyManager::get()->getPrimaryOpaqueFramebuffer(); + GLuint fbo = gpu::GLBackend::getFramebufferID(primaryFBO); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); _isEmpty = true; @@ -140,9 +145,11 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { PerformanceTimer perfTimer("glowEffect"); auto textureCache = DependencyManager::get(); - QOpenGLFramebufferObject* primaryFBO = textureCache->getPrimaryFramebufferObject(); - primaryFBO->release(); - glBindTexture(GL_TEXTURE_2D, primaryFBO->texture()); + // QOpenGLFramebufferObject* primaryFBO = textureCache->getPrimaryFramebufferObject(); + // primaryFBO->release(); + auto primaryFBO = gpu::GLBackend::getFramebufferID(textureCache->getPrimaryOpaqueFramebuffer()); + glBindTexture(GL_TEXTURE_2D, textureCache->getPrimaryColorTextureID()); + auto framebufferSize = textureCache->getFrameBufferSize(); glPushMatrix(); glLoadIdentity(); @@ -160,7 +167,10 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { if (!_enabled || _isEmpty) { // copy the primary to the screen if (destFBO && QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) { - QOpenGLFramebufferObject::blitFramebuffer(destFBO, primaryFBO); + glBindFramebuffer(GL_READ_FRAMEBUFFER, primaryFBO); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, destFBO->handle()); + glBlitFramebuffer(0, 0, framebufferSize.width(), framebufferSize.height(), 0, 0, framebufferSize.width(), framebufferSize.height(), GL_COLOR_BUFFER_BIT, GL_NEAREST); + // QOpenGLFramebufferObject::blitFramebuffer(destFBO, primaryFBO); } else { maybeBind(destFBO); if (!destFBO) { @@ -192,7 +202,8 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { glBindTexture(GL_TEXTURE_2D, oldDiffusedFBO->texture()); _diffuseProgram->bind(); - QSize size = primaryFBO->size(); + //QSize size = primaryFBO->size(); + QSize size = framebufferSize; _diffuseProgram->setUniformValue(_diffusionScaleLocation, 1.0f / size.width(), 1.0f / size.height()); renderFullscreenQuad(); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index b98123803f..bddbc2a0ff 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -673,8 +673,6 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { return false; } - // auto glowEffectIntensity = DependencyManager::get()->getIntensity(); - // Let's introduce a gpu::Batch to capture all the calls to the graphics api _renderBatch.clear(); gpu::Batch& batch = _renderBatch; @@ -703,35 +701,12 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { batch.setViewTransform(_transforms[0]); - // GLBATCH(glDisable)(GL_COLOR_MATERIAL); - - // taking care of by the state? - /* if (mode == RenderArgs::DIFFUSE_RENDER_MODE || mode == RenderArgs::NORMAL_RENDER_MODE) { - GLBATCH(glDisable)(GL_CULL_FACE); - } else { - GLBATCH(glEnable)(GL_CULL_FACE); - if (mode == RenderArgs::SHADOW_RENDER_MODE) { - GLBATCH(glCullFace)(GL_FRONT); - } - } - */ - - // render opaque meshes with alpha testing - -// GLBATCH(glDisable)(GL_BLEND); -// GLBATCH(glEnable)(GL_ALPHA_TEST); - - /* if (mode == RenderArgs::SHADOW_RENDER_MODE) { - GLBATCH(glAlphaFunc)(GL_EQUAL, 0.0f); - } - */ - /*DependencyManager::get()->setPrimaryDrawBuffers( mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE, mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::NORMAL_RENDER_MODE, mode == RenderArgs::DEFAULT_RENDER_MODE); */ - { + /*if (mode != RenderArgs::SHADOW_RENDER_MODE)*/ { GLenum buffers[3]; int bufferCount = 0; @@ -748,6 +723,7 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; } GLBATCH(glDrawBuffers)(bufferCount, buffers); + // batch.setFramebuffer(DependencyManager::get()->getPrimaryOpaqueFramebuffer()); } const float DEFAULT_ALPHA_THRESHOLD = 0.5f; @@ -790,12 +766,6 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, args, true); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args, true); - // GLBATCH(glDisable)(GL_ALPHA_TEST); - /* GLBATCH(glEnable)(GL_BLEND); - GLBATCH(glDepthMask)(false); - GLBATCH(glDepthFunc)(GL_LEQUAL); - */ - //DependencyManager::get()->setPrimaryDrawBuffers(true); { GLenum buffers[1]; int bufferCount = 0; @@ -805,6 +775,8 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { // if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE) { if (mode != RenderArgs::SHADOW_RENDER_MODE) { + // batch.setFramebuffer(DependencyManager::get()->getPrimaryTransparentFramebuffer()); + const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f; translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args, true); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, args, true); @@ -814,6 +786,8 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, true, args, true); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, false, args, true); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, true, args, true); + + // batch.setFramebuffer(DependencyManager::get()->getPrimaryOpaqueFramebuffer()); } GLBATCH(glDepthMask)(true); @@ -1758,14 +1732,6 @@ void Model::setupBatchTransform(gpu::Batch& batch, RenderArgs* args) { void Model::endScene(RenderMode mode, RenderArgs* args) { PROFILE_RANGE(__FUNCTION__); - // auto glowEffectIntensity = DependencyManager::get()->getIntensity(); - - - #if defined(ANDROID) - #else - glPushMatrix(); - #endif - RenderArgs::RenderSide renderSide = RenderArgs::MONO; if (args) { renderSide = args->_renderSide; @@ -1792,34 +1758,15 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { _sceneRenderBatch.clear(); gpu::Batch& batch = _sceneRenderBatch; - // GLBATCH(glDisable)(GL_COLOR_MATERIAL); - - /* if (mode == RenderArgs::DIFFUSE_RENDER_MODE || mode == RenderArgs::NORMAL_RENDER_MODE) { - GLBATCH(glDisable)(GL_CULL_FACE); - } else { - GLBATCH(glEnable)(GL_CULL_FACE); - if (mode == RenderArgs::SHADOW_RENDER_MODE) { - GLBATCH(glCullFace)(GL_FRONT); - } - }*/ - - // render opaque meshes with alpha testing - - // GLBATCH(glDisable)(GL_BLEND); - // GLBATCH(glEnable)(GL_ALPHA_TEST); - - /* if (mode == RenderArgs::SHADOW_RENDER_MODE) { - GLBATCH(glAlphaFunc)(GL_EQUAL, 0.0f); - } -*/ - /*DependencyManager::get()->setPrimaryDrawBuffers( mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE, mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::NORMAL_RENDER_MODE, mode == RenderArgs::DEFAULT_RENDER_MODE); */ - { + + /* if (mode != RenderArgs::SHADOW_RENDER_MODE) */{ GLenum buffers[3]; + int bufferCount = 0; // if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE) { if (mode != RenderArgs::SHADOW_RENDER_MODE) { @@ -1834,6 +1781,8 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; } GLBATCH(glDrawBuffers)(bufferCount, buffers); + + // batch.setFramebuffer(DependencyManager::get()->getPrimaryOpaqueFramebuffer()); } const float DEFAULT_ALPHA_THRESHOLD = 0.5f; @@ -1856,7 +1805,6 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, args); // render translucent meshes afterwards - //DependencyManager::get()->setPrimaryDrawBuffers(false, true, true); { GLenum buffers[2]; int bufferCount = 0; @@ -1876,21 +1824,19 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args); - // GLBATCH(glDisable)(GL_ALPHA_TEST); - /* GLBATCH(glEnable)(GL_BLEND); - GLBATCH(glDepthMask)(false); - GLBATCH(glDepthFunc)(GL_LEQUAL); - */ - //DependencyManager::get()->setPrimaryDrawBuffers(true); + { GLenum buffers[1]; int bufferCount = 0; buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; GLBATCH(glDrawBuffers)(bufferCount, buffers); + // batch.setFramebuffer(DependencyManager::get()->getPrimaryTransparentFramebuffer()); } // if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE) { if (mode != RenderArgs::SHADOW_RENDER_MODE) { + // batch.setFramebuffer(DependencyManager::get()->getPrimaryTransparentFramebuffer()); + const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f; translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, args); @@ -1900,6 +1846,8 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, true, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, false, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, true, args); + + // batch.setFramebuffer(DependencyManager::get()->getPrimaryOpaqueFramebuffer()); } GLBATCH(glDepthMask)(true); @@ -1938,10 +1886,10 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { // Back to no program GLBATCH(glUseProgram)(0); - if (args) { - args->_translucentMeshPartsRendered = translucentParts; - args->_opaqueMeshPartsRendered = opaqueMeshPartsRendered; - } + if (args) { + args->_translucentMeshPartsRendered = translucentParts; + args->_opaqueMeshPartsRendered = opaqueMeshPartsRendered; + } } @@ -1951,12 +1899,6 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { backend.render(_sceneRenderBatch); } - - #if defined(ANDROID) - #else - glPopMatrix(); - #endif - // restore all the default material settings _viewState->setupWorldLight(); @@ -2334,17 +2276,15 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f RenderKey key(mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned); auto pipeline = _renderPipelineLib.find(key.getRaw()); if (pipeline == _renderPipelineLib.end()) { - qDebug() << "No good, couldn;t find a pipeline from the key ?" << key.getRaw(); + qDebug() << "No good, couldn't find a pipeline from the key ?" << key.getRaw(); return; } gpu::ShaderPointer program = (*pipeline).second._pipeline->getProgram(); locations = (*pipeline).second._locations.get(); - //GLuint glprogram = gpu::GLBackend::getShaderID(program); - //GLBATCH(glUseProgram)(glprogram); - // dare! + // Setup the One pipeline batch.setPipeline((*pipeline).second._pipeline); if ((locations->alphaThreshold > -1) && (mode != RenderArgs::SHADOW_RENDER_MODE)) { @@ -2354,9 +2294,6 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f if ((locations->glowIntensity > -1) && (mode != RenderArgs::SHADOW_RENDER_MODE)) { GLBATCH(glUniform1f)(locations->glowIntensity, DependencyManager::get()->getIntensity()); } - // if (!(translucent && alphaThreshold == 0.0f) && (mode != RenderArgs::SHADOW_RENDER_MODE)) { - // GLBATCH(glAlphaFunc)(GL_EQUAL, DependencyManager::get()->getIntensity()); - // } } int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, @@ -2383,10 +2320,7 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool } } } - // if we selected a program, then unselect it - if (!pickProgramsNeeded) { - // GLBATCH(glUseProgram)(0); - } + return meshPartsRendered; } @@ -2415,8 +2349,6 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl args, locations); meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, locations, forceRenderSomeMeshes); - // GLBATCH(glUseProgram)(0); - return meshPartsRendered; } @@ -2427,7 +2359,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod PROFILE_RANGE(__FUNCTION__); auto textureCache = DependencyManager::get(); - // auto glowEffect = DependencyManager::get(); + QString lastMaterialID; int meshPartsRendered = 0; updateVisibleJointStates(); @@ -2531,13 +2463,6 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod qCDebug(renderutils) << "NEW part.materialID:" << part.materialID; } -/* if (locations->glowIntensity >= 0) { - GLBATCH(glUniform1f)(locations->glowIntensity, glowEffect->getIntensity()); - } - if (!(translucent && alphaThreshold == 0.0f)) { - GLBATCH(glAlphaFunc)(GL_EQUAL, glowEffect->getIntensity()); - } -*/ if (locations->materialBufferUnit >= 0) { batch.setUniformBuffer(locations->materialBufferUnit, material->getSchemaBuffer()); } diff --git a/libraries/render-utils/src/TextureCache.cpp b/libraries/render-utils/src/TextureCache.cpp index 9b2a458231..28da6977f2 100644 --- a/libraries/render-utils/src/TextureCache.cpp +++ b/libraries/render-utils/src/TextureCache.cpp @@ -72,6 +72,15 @@ void TextureCache::setFrameBufferSize(QSize frameBufferSize) { if (_frameBufferSize != frameBufferSize) { _frameBufferSize = frameBufferSize; + if (_primaryOpaqueFramebuffer) { + _primaryOpaqueFramebuffer.reset(); + _primaryTransparentFramebuffer.reset(); + _primaryDepthTexture.reset(); + _primaryColorTexture.reset(); + _primaryNormalTexture.reset(); + _primarySpecularTexture.reset(); + } + if (_primaryFramebufferObject) { delete _primaryFramebufferObject; _primaryFramebufferObject = NULL; @@ -243,20 +252,95 @@ QOpenGLFramebufferObject* TextureCache::getPrimaryFramebufferObject() { return _primaryFramebufferObject; } +void TextureCache::createPrimaryFramebuffer() { + _primaryOpaqueFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); + _primaryTransparentFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); + + auto colorFormat = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); + auto width = _frameBufferSize.width(); + auto height = _frameBufferSize.height(); + _primaryColorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height)); + _primaryNormalTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height)); + _primarySpecularTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height)); + + _primaryOpaqueFramebuffer->setRenderBuffer(0, _primaryColorTexture); + _primaryOpaqueFramebuffer->setRenderBuffer(1, _primaryNormalTexture); + _primaryOpaqueFramebuffer->setRenderBuffer(2, _primarySpecularTexture); + + _primaryTransparentFramebuffer->setRenderBuffer(0, _primaryColorTexture); + + auto depthFormat = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH); + _primaryDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(depthFormat, width, height)); + + _primaryOpaqueFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); + + _primaryTransparentFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); +} + +gpu::FramebufferPointer TextureCache::getPrimaryOpaqueFramebuffer() { + if (!_primaryOpaqueFramebuffer) { + createPrimaryFramebuffer(); + } + return _primaryOpaqueFramebuffer; +} + +gpu::FramebufferPointer TextureCache::getPrimaryTransparentFramebuffer() { + if (!_primaryTransparentFramebuffer) { + createPrimaryFramebuffer(); + } + return _primaryTransparentFramebuffer; +} + +gpu::TexturePointer TextureCache::getPrimaryDepthTexture() { + if (!_primaryDepthTexture) { + createPrimaryFramebuffer(); + } + return _primaryDepthTexture; +} + +gpu::TexturePointer TextureCache::getPrimaryColorTexture() { + if (!_primaryColorTexture) { + createPrimaryFramebuffer(); + } + return _primaryColorTexture; +} + +gpu::TexturePointer TextureCache::getPrimaryNormalTexture() { + if (!_primaryNormalTexture) { + createPrimaryFramebuffer(); + } + return _primaryNormalTexture; +} + +gpu::TexturePointer TextureCache::getPrimarySpecularTexture() { + if (!_primarySpecularTexture) { + createPrimaryFramebuffer(); + } + return _primarySpecularTexture; +} + GLuint TextureCache::getPrimaryDepthTextureID() { // ensure that the primary framebuffer object is initialized before returning the depth texture id - getPrimaryFramebufferObject(); + //getPrimaryFramebufferObject(); + + _primaryDepthTextureID = gpu::GLBackend::getTextureID(_primaryDepthTexture); return _primaryDepthTextureID; } +GLuint TextureCache::getPrimaryColorTextureID() { + return gpu::GLBackend::getTextureID(_primaryColorTexture); +} + GLuint TextureCache::getPrimaryNormalTextureID() { // ensure that the primary framebuffer object is initialized before returning the normal texture id - getPrimaryFramebufferObject(); + //getPrimaryFramebufferObject(); + _primaryNormalTextureID = gpu::GLBackend::getTextureID(_primaryNormalTexture); return _primaryNormalTextureID; } GLuint TextureCache::getPrimarySpecularTextureID() { - getPrimaryFramebufferObject(); + //getPrimaryFramebufferObject(); + _primarySpecularTextureID = gpu::GLBackend::getTextureID(_primarySpecularTexture); return _primarySpecularTextureID; } @@ -289,6 +373,36 @@ QOpenGLFramebufferObject* TextureCache::getTertiaryFramebufferObject() { return _tertiaryFramebufferObject; } + +gpu::FramebufferPointer TextureCache::getShadowFramebuffer() { + if (!_shadowFramebuffer) { + const int SHADOW_MAP_SIZE = 2048; + _shadowFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::createShadowmap(SHADOW_MAP_SIZE)); + + _shadowTexture = _shadowFramebuffer->getDepthStencilBuffer(); + /* + glGenTextures(1, &_shadowDepthTextureID); + glBindTexture(GL_TEXTURE_2D, _shadowDepthTextureID); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE, + 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + const float DISTANT_BORDER[] = { 1.0f, 1.0f, 1.0f, 1.0f }; + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, DISTANT_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); + glBindTexture(GL_TEXTURE_2D, 0); + + _shadowFramebufferObject->bind(); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _shadowDepthTextureID, 0); + _shadowFramebufferObject->release(); + */ + } + return _shadowFramebuffer; +} + QOpenGLFramebufferObject* TextureCache::getShadowFramebufferObject() { if (!_shadowFramebufferObject) { const int SHADOW_MAP_SIZE = 2048; @@ -318,7 +432,9 @@ QOpenGLFramebufferObject* TextureCache::getShadowFramebufferObject() { GLuint TextureCache::getShadowDepthTextureID() { // ensure that the shadow framebuffer object is initialized before returning the depth texture id - getShadowFramebufferObject(); + //getShadowFramebufferObject(); + _shadowDepthTextureID = gpu::GLBackend::getTextureID(_shadowTexture); + return _shadowDepthTextureID; } diff --git a/libraries/render-utils/src/TextureCache.h b/libraries/render-utils/src/TextureCache.h index 3ea46a4421..0d0cfc40aa 100644 --- a/libraries/render-utils/src/TextureCache.h +++ b/libraries/render-utils/src/TextureCache.h @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -62,9 +63,18 @@ public: /// used for scene rendering. QOpenGLFramebufferObject* getPrimaryFramebufferObject(); + gpu::FramebufferPointer getPrimaryOpaqueFramebuffer(); + gpu::FramebufferPointer getPrimaryTransparentFramebuffer(); + + gpu::TexturePointer getPrimaryDepthTexture(); + gpu::TexturePointer getPrimaryColorTexture(); + gpu::TexturePointer getPrimaryNormalTexture(); + gpu::TexturePointer getPrimarySpecularTexture(); + /// Returns the ID of the primary framebuffer object's depth texture. This contains the Z buffer used in rendering. GLuint getPrimaryDepthTextureID(); - + GLuint getPrimaryColorTextureID(); + /// Returns the ID of the primary framebuffer object's normal texture. GLuint getPrimaryNormalTextureID(); @@ -78,6 +88,7 @@ public: /// screen effects. QOpenGLFramebufferObject* getSecondaryFramebufferObject(); + /// Returns a pointer to the tertiary framebuffer object, used as an additional render target when performing full /// screen effects. QOpenGLFramebufferObject* getTertiaryFramebufferObject(); @@ -85,6 +96,9 @@ public: /// Returns a pointer to the framebuffer object used to render shadow maps. QOpenGLFramebufferObject* getShadowFramebufferObject(); + gpu::FramebufferPointer getShadowFramebuffer(); + + /// Returns the ID of the shadow framebuffer object's depth texture. GLuint getShadowDepthTextureID(); @@ -105,9 +119,18 @@ private: gpu::TexturePointer _permutationNormalTexture; gpu::TexturePointer _whiteTexture; gpu::TexturePointer _blueTexture; + QHash > _dilatableNetworkTextures; - + + gpu::TexturePointer _primaryDepthTexture; + gpu::TexturePointer _primaryColorTexture; + gpu::TexturePointer _primaryNormalTexture; + gpu::TexturePointer _primarySpecularTexture; + gpu::FramebufferPointer _primaryOpaqueFramebuffer; + gpu::FramebufferPointer _primaryTransparentFramebuffer; + void createPrimaryFramebuffer(); + GLuint _primaryDepthTextureID; GLuint _primaryNormalTextureID; GLuint _primarySpecularTextureID; @@ -115,9 +138,13 @@ private: QOpenGLFramebufferObject* _secondaryFramebufferObject; QOpenGLFramebufferObject* _tertiaryFramebufferObject; + QOpenGLFramebufferObject* _shadowFramebufferObject; GLuint _shadowDepthTextureID; + gpu::FramebufferPointer _shadowFramebuffer; + gpu::TexturePointer _shadowTexture; + QSize _frameBufferSize; QGLWidget* _associatedWidget; }; From 9262585bab80a823fb88898721f573c60d7f354e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 14 Apr 2015 10:38:22 -0700 Subject: [PATCH 11/31] first cut at moving avatar appearance into separate dialog box --- interface/src/ui/AvatarAppearanceDialog.cpp | 212 +++++++++ interface/src/ui/AvatarAppearanceDialog.h | 63 +++ interface/src/ui/DialogsManager.cpp | 10 + interface/src/ui/DialogsManager.h | 3 + interface/src/ui/PreferencesDialog.cpp | 127 +----- interface/src/ui/PreferencesDialog.h | 15 - interface/ui/avatarAppearance.ui | 471 ++++++++++++++++++++ interface/ui/preferencesDialog.ui | 461 ++++--------------- 8 files changed, 865 insertions(+), 497 deletions(-) create mode 100644 interface/src/ui/AvatarAppearanceDialog.cpp create mode 100644 interface/src/ui/AvatarAppearanceDialog.h create mode 100644 interface/ui/avatarAppearance.ui diff --git a/interface/src/ui/AvatarAppearanceDialog.cpp b/interface/src/ui/AvatarAppearanceDialog.cpp new file mode 100644 index 0000000000..1200c71cac --- /dev/null +++ b/interface/src/ui/AvatarAppearanceDialog.cpp @@ -0,0 +1,212 @@ +// +// AvatarAppearanceDialog.cpp +// interface/src/ui +// +// Created by Stojce Slavkovski on 2/20/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include +#include + +#include +#include +#include +#include +#include + +#include "Application.h" +#include "MainWindow.h" +#include "LODManager.h" +#include "Menu.h" +#include "AvatarAppearanceDialog.h" +#include "Snapshot.h" +#include "UserActivityLogger.h" +#include "UIUtil.h" + + +const int PREFERENCES_HEIGHT_PADDING = 20; + +AvatarAppearanceDialog::AvatarAppearanceDialog(QWidget* parent) : + QDialog(parent) { + + setAttribute(Qt::WA_DeleteOnClose); + + ui.setupUi(this); + + loadAvatarAppearance(); + + connect(ui.defaultButton, &QPushButton::clicked, this, &AvatarAppearanceDialog::accept); + + connect(ui.buttonBrowseHead, &QPushButton::clicked, this, &AvatarAppearanceDialog::openHeadModelBrowser); + connect(ui.buttonBrowseBody, &QPushButton::clicked, this, &AvatarAppearanceDialog::openBodyModelBrowser); + connect(ui.buttonBrowseFullAvatar, &QPushButton::clicked, this, &AvatarAppearanceDialog::openFullAvatarModelBrowser); + + connect(ui.useSeparateBodyAndHead, &QRadioButton::clicked, this, &AvatarAppearanceDialog::useSeparateBodyAndHead); + connect(ui.useFullAvatar, &QRadioButton::clicked, this, &AvatarAppearanceDialog::useFullAvatar); + + connect(Application::getInstance(), &Application::headURLChanged, this, &AvatarAppearanceDialog::headURLChanged); + connect(Application::getInstance(), &Application::bodyURLChanged, this, &AvatarAppearanceDialog::bodyURLChanged); + connect(Application::getInstance(), &Application::fullAvatarURLChanged, this, &AvatarAppearanceDialog::fullAvatarURLChanged); + + // move dialog to left side + //move(parentWidget()->geometry().topLeft()); + //setFixedHeight(parentWidget()->size().height() - PREFERENCES_HEIGHT_PADDING); + + auto myAvatar = DependencyManager::get()->getMyAvatar(); + + ui.bodyNameLabel->setText("Body - " + myAvatar->getBodyModelName()); + ui.headNameLabel->setText("Head - " + myAvatar->getHeadModelName()); + ui.fullAvatarNameLabel->setText("Full Avatar - " + myAvatar->getFullAvartarModelName()); + + UIUtil::scaleWidgetFontSizes(this); +} + +void AvatarAppearanceDialog::useSeparateBodyAndHead(bool checked) { + setUseFullAvatar(!checked); + + QUrl headURL(ui.faceURLEdit->text()); + QUrl bodyURL(ui.skeletonURLEdit->text()); + + DependencyManager::get()->getMyAvatar()->useHeadAndBodyURLs(headURL, bodyURL); +} + +void AvatarAppearanceDialog::useFullAvatar(bool checked) { + setUseFullAvatar(checked); + QUrl fullAvatarURL(ui.fullAvatarURLEdit->text()); + DependencyManager::get()->getMyAvatar()->useFullAvatarURL(fullAvatarURL); +} + +void AvatarAppearanceDialog::setUseFullAvatar(bool useFullAvatar) { + _useFullAvatar = useFullAvatar; + ui.faceURLEdit->setEnabled(!_useFullAvatar); + ui.skeletonURLEdit->setEnabled(!_useFullAvatar); + ui.fullAvatarURLEdit->setEnabled(_useFullAvatar); + + ui.useFullAvatar->setChecked(_useFullAvatar); + ui.useSeparateBodyAndHead->setChecked(!_useFullAvatar); +} + +void AvatarAppearanceDialog::headURLChanged(const QString& newValue, const QString& modelName) { + ui.faceURLEdit->setText(newValue); + setUseFullAvatar(false); + ui.headNameLabel->setText("Head - " + modelName); +} + +void AvatarAppearanceDialog::bodyURLChanged(const QString& newValue, const QString& modelName) { + ui.skeletonURLEdit->setText(newValue); + setUseFullAvatar(false); + ui.bodyNameLabel->setText("Body - " + modelName); +} + +void AvatarAppearanceDialog::fullAvatarURLChanged(const QString& newValue, const QString& modelName) { + ui.fullAvatarURLEdit->setText(newValue); + setUseFullAvatar(true); + ui.fullAvatarNameLabel->setText("Full Avatar - " + modelName); +} + +void AvatarAppearanceDialog::accept() { + saveAvatarAppearance(); + close(); + delete _marketplaceWindow; + _marketplaceWindow = NULL; +} + +void AvatarAppearanceDialog::setHeadUrl(QString modelUrl) { + ui.faceURLEdit->setText(modelUrl); +} + +void AvatarAppearanceDialog::setSkeletonUrl(QString modelUrl) { + ui.skeletonURLEdit->setText(modelUrl); +} + +void AvatarAppearanceDialog::openFullAvatarModelBrowser() { + auto MARKETPLACE_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/marketplace?category=avatars"; + auto WIDTH = 900; + auto HEIGHT = 700; + if (!_marketplaceWindow) { + _marketplaceWindow = new WebWindowClass("Marketplace", MARKETPLACE_URL, WIDTH, HEIGHT, false); + } + _marketplaceWindow->setVisible(true); +} + +void AvatarAppearanceDialog::openHeadModelBrowser() { + auto MARKETPLACE_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/marketplace?category=avatars"; + auto WIDTH = 900; + auto HEIGHT = 700; + if (!_marketplaceWindow) { + _marketplaceWindow = new WebWindowClass("Marketplace", MARKETPLACE_URL, WIDTH, HEIGHT, false); + } + _marketplaceWindow->setVisible(true); +} + +void AvatarAppearanceDialog::openBodyModelBrowser() { + auto MARKETPLACE_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/marketplace?category=avatars"; + auto WIDTH = 900; + auto HEIGHT = 700; + if (!_marketplaceWindow) { + _marketplaceWindow = new WebWindowClass("Marketplace", MARKETPLACE_URL, WIDTH, HEIGHT, false); + } + _marketplaceWindow->setVisible(true); +} + +void AvatarAppearanceDialog::resizeEvent(QResizeEvent *resizeEvent) { + + // keep buttons panel at the bottom + ui.buttonsPanel->setGeometry(0, + size().height() - ui.buttonsPanel->height(), + size().width(), + ui.buttonsPanel->height()); + + // set width and height of srcollarea to match bottom panel and width + ui.scrollArea->setGeometry(ui.scrollArea->geometry().x(), ui.scrollArea->geometry().y(), + size().width(), + size().height() - ui.buttonsPanel->height() - ui.scrollArea->geometry().y()); + +} + +void AvatarAppearanceDialog::loadAvatarAppearance() { + + MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); + + _useFullAvatar = myAvatar->getUseFullAvatar(); + _fullAvatarURLString = myAvatar->getFullAvatarURLFromPreferences().toString(); + _headURLString = myAvatar->getHeadURLFromPreferences().toString(); + _bodyURLString = myAvatar->getBodyURLFromPreferences().toString(); + + ui.fullAvatarURLEdit->setText(_fullAvatarURLString); + ui.faceURLEdit->setText(_headURLString); + ui.skeletonURLEdit->setText(_bodyURLString); + setUseFullAvatar(_useFullAvatar); +} + +void AvatarAppearanceDialog::saveAvatarAppearance() { + + MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); + + QUrl headURL(ui.faceURLEdit->text()); + QString headURLString = headURL.toString(); + + QUrl bodyURL(ui.skeletonURLEdit->text()); + QString bodyURLString = bodyURL.toString(); + + QUrl fullAvatarURL(ui.fullAvatarURLEdit->text()); + QString fullAvatarURLString = fullAvatarURL.toString(); + + bool somethingChanged = + _useFullAvatar != myAvatar->getUseFullAvatar() || + fullAvatarURLString != myAvatar->getFullAvatarURLFromPreferences().toString() || + headURLString != myAvatar->getHeadURLFromPreferences().toString() || + bodyURLString != myAvatar->getBodyURLFromPreferences().toString(); + + if (somethingChanged) { + if (_useFullAvatar) { + myAvatar->useFullAvatarURL(fullAvatarURL); + } else { + myAvatar->useHeadAndBodyURLs(headURL, bodyURL); + } + } +} diff --git a/interface/src/ui/AvatarAppearanceDialog.h b/interface/src/ui/AvatarAppearanceDialog.h new file mode 100644 index 0000000000..f7a735e611 --- /dev/null +++ b/interface/src/ui/AvatarAppearanceDialog.h @@ -0,0 +1,63 @@ +// +// AvatarAppearanceDialog.h +// interface/src/ui +// +// Created by Stojce Slavkovski on 2/20/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_AvatarAppearanceDialog_h +#define hifi_AvatarAppearanceDialog_h + +#include "ui_avatarAppearance.h" + +#include +#include + +#include "scripting/WebWindowClass.h" + +class AvatarAppearanceDialog : public QDialog { + Q_OBJECT + +public: + AvatarAppearanceDialog(QWidget* parent = nullptr); + +protected: + void resizeEvent(QResizeEvent* resizeEvent); + +private: + void loadAvatarAppearance(); + void saveAvatarAppearance(); + void openHeadModelBrowser(); + void openBodyModelBrowser(); + void openFullAvatarModelBrowser(); + void setUseFullAvatar(bool useFullAvatar); + + Ui_AvatarAppearanceDialog ui; + + bool _useFullAvatar; + QString _headURLString; + QString _bodyURLString; + QString _fullAvatarURLString; + + + QString _displayNameString; + + WebWindowClass* _marketplaceWindow = NULL; + +private slots: + void accept(); + void setHeadUrl(QString modelUrl); + void setSkeletonUrl(QString modelUrl); + void headURLChanged(const QString& newValue, const QString& modelName); + void bodyURLChanged(const QString& newValue, const QString& modelName); + void fullAvatarURLChanged(const QString& newValue, const QString& modelName); + void useSeparateBodyAndHead(bool checked); + void useFullAvatar(bool checked); + +}; + +#endif // hifi_AvatarAppearanceDialog_h diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index 701ceb0189..ad86e83ec0 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -18,6 +18,7 @@ #include "AddressBarDialog.h" #include "AnimationsDialog.h" #include "AttachmentsDialog.h" +#include "AvatarAppearanceDialog.h" #include "BandwidthDialog.h" #include "CachesSizeDialog.h" #include "DiskCacheEditor.h" @@ -85,6 +86,15 @@ void DialogsManager::editPreferences() { } } +void DialogsManager::changeAvatarAppearance() { + if (!_avatarAppearanceDialog) { + maybeCreateDialog(_avatarAppearanceDialog); + _avatarAppearanceDialog->show(); + } else { + _avatarAppearanceDialog->close(); + } +} + void DialogsManager::editAttachments() { if (!_attachmentsDialog) { maybeCreateDialog(_attachmentsDialog); diff --git a/interface/src/ui/DialogsManager.h b/interface/src/ui/DialogsManager.h index 897215cbff..e7f017d54d 100644 --- a/interface/src/ui/DialogsManager.h +++ b/interface/src/ui/DialogsManager.h @@ -33,6 +33,7 @@ class OctreeStatsDialog; class PreferencesDialog; class ScriptEditorWindow; class QMessageBox; +class AvatarAppearanceDialog; class DialogsManager : public QObject, public Dependency { Q_OBJECT @@ -59,6 +60,7 @@ public slots: void hmdTools(bool showTools); void showScriptEditor(); void showIRCLink(); + void changeAvatarAppearance(); private slots: void toggleToolWindow(); @@ -94,6 +96,7 @@ private: QPointer _octreeStatsDialog; QPointer _preferencesDialog; QPointer _scriptEditor; + QPointer _avatarAppearanceDialog; }; #endif // hifi_DialogsManager_h \ No newline at end of file diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index bc10109c36..99ad98ef2d 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -19,6 +19,7 @@ #include #include "Application.h" +#include "DialogsManager.h" #include "MainWindow.h" #include "LODManager.h" #include "Menu.h" @@ -41,18 +42,13 @@ PreferencesDialog::PreferencesDialog(QWidget* parent) : ui.outputBufferSizeSpinner->setMinimum(MIN_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES); ui.outputBufferSizeSpinner->setMaximum(MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES); - connect(ui.buttonBrowseHead, &QPushButton::clicked, this, &PreferencesDialog::openHeadModelBrowser); - connect(ui.buttonBrowseBody, &QPushButton::clicked, this, &PreferencesDialog::openBodyModelBrowser); - connect(ui.buttonBrowseFullAvatar, &QPushButton::clicked, this, &PreferencesDialog::openFullAvatarModelBrowser); - connect(ui.buttonBrowseLocation, &QPushButton::clicked, this, &PreferencesDialog::openSnapshotLocationBrowser); connect(ui.buttonBrowseScriptsLocation, &QPushButton::clicked, this, &PreferencesDialog::openScriptsLocationBrowser); connect(ui.buttonReloadDefaultScripts, &QPushButton::clicked, Application::getInstance(), &Application::loadDefaultScripts); - connect(ui.useSeparateBodyAndHead, &QRadioButton::clicked, this, &PreferencesDialog::useSeparateBodyAndHead); - connect(ui.useFullAvatar, &QRadioButton::clicked, this, &PreferencesDialog::useFullAvatar); - - + DialogsManager* dialogsManager = DependencyManager::get().data(); + connect(ui.buttonChangeApperance, &QPushButton::clicked, dialogsManager, &DialogsManager::changeAvatarAppearance); + connect(Application::getInstance(), &Application::headURLChanged, this, &PreferencesDialog::headURLChanged); connect(Application::getInstance(), &Application::bodyURLChanged, this, &PreferencesDialog::bodyURLChanged); connect(Application::getInstance(), &Application::fullAvatarURLChanged, this, &PreferencesDialog::fullAvatarURLChanged); @@ -63,54 +59,21 @@ PreferencesDialog::PreferencesDialog(QWidget* parent) : auto myAvatar = DependencyManager::get()->getMyAvatar(); - ui.bodyNameLabel->setText("Body - " + myAvatar->getBodyModelName()); - ui.headNameLabel->setText("Head - " + myAvatar->getHeadModelName()); - ui.fullAvatarNameLabel->setText("Full Avatar - " + myAvatar->getFullAvartarModelName()); + ui.apperanceDescription->setText("Body - " + myAvatar->getBodyModelName()); UIUtil::scaleWidgetFontSizes(this); } -void PreferencesDialog::useSeparateBodyAndHead(bool checked) { - setUseFullAvatar(!checked); - - QUrl headURL(ui.faceURLEdit->text()); - QUrl bodyURL(ui.skeletonURLEdit->text()); - - DependencyManager::get()->getMyAvatar()->useHeadAndBodyURLs(headURL, bodyURL); -} - -void PreferencesDialog::useFullAvatar(bool checked) { - setUseFullAvatar(checked); - QUrl fullAvatarURL(ui.fullAvatarURLEdit->text()); - DependencyManager::get()->getMyAvatar()->useFullAvatarURL(fullAvatarURL); -} - -void PreferencesDialog::setUseFullAvatar(bool useFullAvatar) { - _useFullAvatar = useFullAvatar; - ui.faceURLEdit->setEnabled(!_useFullAvatar); - ui.skeletonURLEdit->setEnabled(!_useFullAvatar); - ui.fullAvatarURLEdit->setEnabled(_useFullAvatar); - - ui.useFullAvatar->setChecked(_useFullAvatar); - ui.useSeparateBodyAndHead->setChecked(!_useFullAvatar); -} - void PreferencesDialog::headURLChanged(const QString& newValue, const QString& modelName) { - ui.faceURLEdit->setText(newValue); - setUseFullAvatar(false); - ui.headNameLabel->setText("Head - " + modelName); + ui.apperanceDescription->setText("Head - " + modelName); } void PreferencesDialog::bodyURLChanged(const QString& newValue, const QString& modelName) { - ui.skeletonURLEdit->setText(newValue); - setUseFullAvatar(false); - ui.bodyNameLabel->setText("Body - " + modelName); + ui.apperanceDescription->setText("Body - " + modelName); } void PreferencesDialog::fullAvatarURLChanged(const QString& newValue, const QString& modelName) { - ui.fullAvatarURLEdit->setText(newValue); - setUseFullAvatar(true); - ui.fullAvatarNameLabel->setText("Full Avatar - " + modelName); + ui.apperanceDescription->setText("Full Avatar - " + modelName); } void PreferencesDialog::accept() { @@ -120,44 +83,6 @@ void PreferencesDialog::accept() { _marketplaceWindow = NULL; } -void PreferencesDialog::setHeadUrl(QString modelUrl) { - ui.faceURLEdit->setText(modelUrl); -} - -void PreferencesDialog::setSkeletonUrl(QString modelUrl) { - ui.skeletonURLEdit->setText(modelUrl); -} - -void PreferencesDialog::openFullAvatarModelBrowser() { - auto MARKETPLACE_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/marketplace?category=avatars"; - auto WIDTH = 900; - auto HEIGHT = 700; - if (!_marketplaceWindow) { - _marketplaceWindow = new WebWindowClass("Marketplace", MARKETPLACE_URL, WIDTH, HEIGHT, false); - } - _marketplaceWindow->setVisible(true); -} - -void PreferencesDialog::openHeadModelBrowser() { - auto MARKETPLACE_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/marketplace?category=avatars"; - auto WIDTH = 900; - auto HEIGHT = 700; - if (!_marketplaceWindow) { - _marketplaceWindow = new WebWindowClass("Marketplace", MARKETPLACE_URL, WIDTH, HEIGHT, false); - } - _marketplaceWindow->setVisible(true); -} - -void PreferencesDialog::openBodyModelBrowser() { - auto MARKETPLACE_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/marketplace?category=avatars"; - auto WIDTH = 900; - auto HEIGHT = 700; - if (!_marketplaceWindow) { - _marketplaceWindow = new WebWindowClass("Marketplace", MARKETPLACE_URL, WIDTH, HEIGHT, false); - } - _marketplaceWindow->setVisible(true); -} - void PreferencesDialog::openSnapshotLocationBrowser() { QString dir = QFileDialog::getExistingDirectory(this, tr("Snapshots Location"), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation), @@ -199,19 +124,6 @@ void PreferencesDialog::loadPreferences() { _displayNameString = myAvatar->getDisplayName(); ui.displayNameEdit->setText(_displayNameString); - - _useFullAvatar = myAvatar->getUseFullAvatar(); - _fullAvatarURLString = myAvatar->getFullAvatarURLFromPreferences().toString(); - _headURLString = myAvatar->getHeadURLFromPreferences().toString(); - _bodyURLString = myAvatar->getBodyURLFromPreferences().toString(); - - ui.fullAvatarURLEdit->setText(_fullAvatarURLString); - ui.faceURLEdit->setText(_headURLString); - ui.skeletonURLEdit->setText(_bodyURLString); - setUseFullAvatar(_useFullAvatar); - - // TODO: load the names for the models. - ui.sendDataCheckBox->setChecked(!menuInstance->isOptionChecked(MenuOption::DisableActivityLogger)); ui.snapshotLocationEdit->setText(Snapshot::snapshotsLocation.get()); @@ -281,29 +193,6 @@ void PreferencesDialog::savePreferences() { shouldDispatchIdentityPacket = true; } - QUrl headURL(ui.faceURLEdit->text()); - QString headURLString = headURL.toString(); - - QUrl bodyURL(ui.skeletonURLEdit->text()); - QString bodyURLString = bodyURL.toString(); - - QUrl fullAvatarURL(ui.fullAvatarURLEdit->text()); - QString fullAvatarURLString = fullAvatarURL.toString(); - - bool somethingChanged = - _useFullAvatar != myAvatar->getUseFullAvatar() || - fullAvatarURLString != myAvatar->getFullAvatarURLFromPreferences().toString() || - headURLString != myAvatar->getHeadURLFromPreferences().toString() || - bodyURLString != myAvatar->getBodyURLFromPreferences().toString(); - - if (somethingChanged) { - if (_useFullAvatar) { - myAvatar->useFullAvatarURL(fullAvatarURL); - } else { - myAvatar->useHeadAndBodyURLs(headURL, bodyURL); - } - } - if (shouldDispatchIdentityPacket) { myAvatar->sendIdentityPacket(); } diff --git a/interface/src/ui/PreferencesDialog.h b/interface/src/ui/PreferencesDialog.h index 3f097ca9ab..22efe3489d 100644 --- a/interface/src/ui/PreferencesDialog.h +++ b/interface/src/ui/PreferencesDialog.h @@ -31,35 +31,20 @@ protected: private: void loadPreferences(); void savePreferences(); - void openHeadModelBrowser(); - void openBodyModelBrowser(); - void openFullAvatarModelBrowser(); - void setUseFullAvatar(bool useFullAvatar); Ui_PreferencesDialog ui; - bool _useFullAvatar; - QString _headURLString; - QString _bodyURLString; - QString _fullAvatarURLString; - - QString _displayNameString; WebWindowClass* _marketplaceWindow = NULL; private slots: void accept(); - void setHeadUrl(QString modelUrl); - void setSkeletonUrl(QString modelUrl); void openSnapshotLocationBrowser(); void openScriptsLocationBrowser(); void headURLChanged(const QString& newValue, const QString& modelName); void bodyURLChanged(const QString& newValue, const QString& modelName); void fullAvatarURLChanged(const QString& newValue, const QString& modelName); - void useSeparateBodyAndHead(bool checked); - void useFullAvatar(bool checked); - }; #endif // hifi_PreferencesDialog_h diff --git a/interface/ui/avatarAppearance.ui b/interface/ui/avatarAppearance.ui new file mode 100644 index 0000000000..5ebf2c705b --- /dev/null +++ b/interface/ui/avatarAppearance.ui @@ -0,0 +1,471 @@ + + + AvatarAppearanceDialog + + + + 0 + 0 + 500 + 350 + + + + + 0 + 0 + + + + + 500 + 350 + + + + + 500 + 16777215 + + + + + 13 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Plain + + + 0 + + + true + + + + + 0 + -107 + 485 + 1550 + + + + + 0 + + + 30 + + + 0 + + + 30 + + + 10 + + + + + + + 0 + + + 7 + + + 7 + + + + + + + + + Arial + + + + Use single avatar with Body and Head + + + + + + + + + + 0 + + + 10 + + + 0 + + + 0 + + + + + + + + Arial + + + + Full Avatar + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + fullAvatarURLEdit + + + + + + + + + + + + 0 + 0 + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 5 + 0 + + + + + + + + + + Arial + + + + Browse + + + + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + Arial + + + + Use separate Body and Head avatar files + + + + + + + + + 0 + + + 10 + + + 7 + + + 7 + + + + + + + + + Arial + + + + Head + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + + + + + 0 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 5 + 20 + + + + + + + + + Arial + + + + Browse + + + + 0 + 0 + + + + + + + + + + + + + + + 0 + + + 10 + + + 7 + + + 7 + + + + + + + Arial + + + + Body + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + skeletonURLEdit + + + + + + + + 0 + + + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 5 + 20 + + + + + + + + + Arial + + + + Browse + + + + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + Arial + + + + Close + + + true + + + false + + + + + + + + + + + + diff --git a/interface/ui/preferencesDialog.ui b/interface/ui/preferencesDialog.ui index 4a0b1e961a..6f0ec7d792 100644 --- a/interface/ui/preferencesDialog.ui +++ b/interface/ui/preferencesDialog.ui @@ -128,6 +128,8 @@ + + @@ -187,370 +189,98 @@ - - - - 0 - - - 7 - - - 7 - - - - - - - - - 0 - 0 - - - - - 32 - 28 - - - - - 0 - 0 - - - - - Arial - - - - Use single avatar with Body and Head - - - - 0 - 0 - - - - - - - - - - - 0 - - - 10 - - - 7 - - - 7 - - - - - - - - Arial - - - - Full Avatar - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - fullAvatarURLEdit - - - - - - - - 0 - - - - - - 0 - 0 - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 5 - 20 - - - - - - - - - Arial - - - - Browse - - - - 0 - 0 - - - - - - - - - - - - - - 0 - 0 - - - - - 32 - 28 - - - - - 0 - 0 - - - - - Arial - - - - Use separate Body and Head avatar files - - - - 0 - 0 - - - - - - - - - - 0 - - - 10 - - - 7 - - - 7 - - - - - - - - - Arial - - - - Head - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - - - - - 0 - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 5 - 20 - - - - - - - - - Arial - - - - Browse - - - - 0 - 0 - - - - - - - - - - - - - - - 0 - - - 10 - - - 7 - - - 7 - - - - - - - Arial - - - - Body - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - skeletonURLEdit - - - - - - - - 0 - - - - - - 0 - 0 - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 5 - 20 - - - - - - - - - Arial - - - - Browse - - - - 0 - 0 - - - - - - - - - - - - - - - - - - - - + + + + 0 + + + 7 + + + 7 + + + + + + Arial + + + + <html><head/><body><p>Appearance</p></body></html> + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + apperanceDescription + + + + + + + + + + 0 + + + + + + Arial + + + + + false + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 5 + 20 + + + + + + + + + Arial + + + + Change + + + + 0 + 0 + + + + + + + + + + @@ -621,6 +351,7 @@ + @@ -671,6 +402,10 @@ + + + + From 174e9f21333eecb7a9a93f9c1efae3a89e5b7db5 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 14 Apr 2015 12:38:29 -0700 Subject: [PATCH 12/31] more tweaks to preferences UI --- interface/src/avatar/MyAvatar.cpp | 23 +++++++++++++++++++++ interface/src/avatar/MyAvatar.h | 2 ++ interface/src/ui/AvatarAppearanceDialog.cpp | 20 ++++++++---------- interface/src/ui/AvatarAppearanceDialog.h | 1 + interface/src/ui/DialogsManager.h | 1 + interface/src/ui/PreferencesDialog.cpp | 14 +++++++------ interface/src/ui/PreferencesDialog.h | 2 ++ 7 files changed, 46 insertions(+), 17 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 3073bbb219..5a372ae274 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -943,6 +943,29 @@ void MyAvatar::clearJointAnimationPriorities() { } } +QString MyAvatar::getModelDescription() const { + QString result; + if (_useFullAvatar) { + if (!getFullAvartarModelName().isEmpty()) { + result = "Full Avatar \"" + getFullAvartarModelName() + "\""; + } else { + result = "Full Avatar \"" + _fullAvatarURLFromPreferences.fileName() + "\""; + } + } else { + if (!getHeadModelName().isEmpty()) { + result = "Head \"" + getHeadModelName() + "\""; + } else { + result = "Head \"" + _headURLFromPreferences.fileName() + "\""; + } + if (!getBodyModelName().isEmpty()) { + result += " and Body \"" + getBodyModelName() + "\""; + } else { + result += " and Body \"" + _skeletonURLFromPreferences.fileName() + "\""; + } + } + return result; +} + void MyAvatar::setFaceModelURL(const QUrl& faceModelURL) { Avatar::setFaceModelURL(faceModelURL); _billboardValid = false; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 9c1f78c696..066bfdd930 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -131,6 +131,8 @@ public: const QString& getBodyModelName() const { return _bodyModelName; } const QString& getFullAvartarModelName() const { return _fullAvatarModelName; } + QString getModelDescription() const; + virtual void setAttachmentData(const QVector& attachmentData); virtual glm::vec3 getSkeletonPosition() const; diff --git a/interface/src/ui/AvatarAppearanceDialog.cpp b/interface/src/ui/AvatarAppearanceDialog.cpp index 1200c71cac..ceaaf140c4 100644 --- a/interface/src/ui/AvatarAppearanceDialog.cpp +++ b/interface/src/ui/AvatarAppearanceDialog.cpp @@ -26,9 +26,8 @@ #include "Snapshot.h" #include "UserActivityLogger.h" #include "UIUtil.h" - - -const int PREFERENCES_HEIGHT_PADDING = 20; +#include "ui/DialogsManager.h" +#include "ui/PreferencesDialog.h" AvatarAppearanceDialog::AvatarAppearanceDialog(QWidget* parent) : QDialog(parent) { @@ -52,10 +51,6 @@ AvatarAppearanceDialog::AvatarAppearanceDialog(QWidget* parent) : connect(Application::getInstance(), &Application::bodyURLChanged, this, &AvatarAppearanceDialog::bodyURLChanged); connect(Application::getInstance(), &Application::fullAvatarURLChanged, this, &AvatarAppearanceDialog::fullAvatarURLChanged); - // move dialog to left side - //move(parentWidget()->geometry().topLeft()); - //setFixedHeight(parentWidget()->size().height() - PREFERENCES_HEIGHT_PADDING); - auto myAvatar = DependencyManager::get()->getMyAvatar(); ui.bodyNameLabel->setText("Body - " + myAvatar->getBodyModelName()); @@ -66,18 +61,16 @@ AvatarAppearanceDialog::AvatarAppearanceDialog(QWidget* parent) : } void AvatarAppearanceDialog::useSeparateBodyAndHead(bool checked) { - setUseFullAvatar(!checked); - QUrl headURL(ui.faceURLEdit->text()); QUrl bodyURL(ui.skeletonURLEdit->text()); - DependencyManager::get()->getMyAvatar()->useHeadAndBodyURLs(headURL, bodyURL); + setUseFullAvatar(!checked); } void AvatarAppearanceDialog::useFullAvatar(bool checked) { - setUseFullAvatar(checked); QUrl fullAvatarURL(ui.fullAvatarURLEdit->text()); DependencyManager::get()->getMyAvatar()->useFullAvatarURL(fullAvatarURL); + setUseFullAvatar(checked); } void AvatarAppearanceDialog::setUseFullAvatar(bool useFullAvatar) { @@ -88,6 +81,8 @@ void AvatarAppearanceDialog::setUseFullAvatar(bool useFullAvatar) { ui.useFullAvatar->setChecked(_useFullAvatar); ui.useSeparateBodyAndHead->setChecked(!_useFullAvatar); + + DependencyManager::get()->getPreferencesDialog()->avatarDescriptionChanged(); } void AvatarAppearanceDialog::headURLChanged(const QString& newValue, const QString& modelName) { @@ -110,6 +105,9 @@ void AvatarAppearanceDialog::fullAvatarURLChanged(const QString& newValue, const void AvatarAppearanceDialog::accept() { saveAvatarAppearance(); + + DependencyManager::get()->getPreferencesDialog()->avatarDescriptionChanged(); + close(); delete _marketplaceWindow; _marketplaceWindow = NULL; diff --git a/interface/src/ui/AvatarAppearanceDialog.h b/interface/src/ui/AvatarAppearanceDialog.h index f7a735e611..be30caeedb 100644 --- a/interface/src/ui/AvatarAppearanceDialog.h +++ b/interface/src/ui/AvatarAppearanceDialog.h @@ -58,6 +58,7 @@ private slots: void useSeparateBodyAndHead(bool checked); void useFullAvatar(bool checked); + }; #endif // hifi_AvatarAppearanceDialog_h diff --git a/interface/src/ui/DialogsManager.h b/interface/src/ui/DialogsManager.h index e7f017d54d..d5d9c33a9a 100644 --- a/interface/src/ui/DialogsManager.h +++ b/interface/src/ui/DialogsManager.h @@ -44,6 +44,7 @@ public: QPointer getHMDToolsDialog() const { return _hmdToolsDialog; } QPointer getLodToolsDialog() const { return _lodToolsDialog; } QPointer getOctreeStatsDialog() const { return _octreeStatsDialog; } + QPointer getPreferencesDialog() const { return _preferencesDialog; } public slots: void toggleAddressBar(); diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 99ad98ef2d..98f7382097 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -57,23 +57,25 @@ PreferencesDialog::PreferencesDialog(QWidget* parent) : move(parentWidget()->geometry().topLeft()); setFixedHeight(parentWidget()->size().height() - PREFERENCES_HEIGHT_PADDING); - auto myAvatar = DependencyManager::get()->getMyAvatar(); - - ui.apperanceDescription->setText("Body - " + myAvatar->getBodyModelName()); + ui.apperanceDescription->setText(DependencyManager::get()->getMyAvatar()->getModelDescription()); UIUtil::scaleWidgetFontSizes(this); } +void PreferencesDialog::avatarDescriptionChanged() { + ui.apperanceDescription->setText(DependencyManager::get()->getMyAvatar()->getModelDescription()); +} + void PreferencesDialog::headURLChanged(const QString& newValue, const QString& modelName) { - ui.apperanceDescription->setText("Head - " + modelName); + ui.apperanceDescription->setText(DependencyManager::get()->getMyAvatar()->getModelDescription()); } void PreferencesDialog::bodyURLChanged(const QString& newValue, const QString& modelName) { - ui.apperanceDescription->setText("Body - " + modelName); + ui.apperanceDescription->setText(DependencyManager::get()->getMyAvatar()->getModelDescription()); } void PreferencesDialog::fullAvatarURLChanged(const QString& newValue, const QString& modelName) { - ui.apperanceDescription->setText("Full Avatar - " + modelName); + ui.apperanceDescription->setText(DependencyManager::get()->getMyAvatar()->getModelDescription()); } void PreferencesDialog::accept() { diff --git a/interface/src/ui/PreferencesDialog.h b/interface/src/ui/PreferencesDialog.h index 22efe3489d..8e699c80a2 100644 --- a/interface/src/ui/PreferencesDialog.h +++ b/interface/src/ui/PreferencesDialog.h @@ -25,6 +25,8 @@ class PreferencesDialog : public QDialog { public: PreferencesDialog(QWidget* parent = nullptr); + void avatarDescriptionChanged(); + protected: void resizeEvent(QResizeEvent* resizeEvent); From 9388ae42128c8ae9430a32ad192ef95c9956edd5 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 14 Apr 2015 14:52:21 -0700 Subject: [PATCH 13/31] fix warning about unused variable --- libraries/render-utils/src/Model.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index b98123803f..22358f7453 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -151,7 +151,7 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key, // create a new RenderPipeline with the same shader side and the mirrorState auto mirrorPipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, mirrorState)); - auto it = insert(value_type(mirrorKey.getRaw(), RenderPipeline(mirrorPipeline, locations))); + insert(value_type(mirrorKey.getRaw(), RenderPipeline(mirrorPipeline, locations))); } } From da9091a99db023f5c2dddc8687aa245fc4be29af Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 14 Apr 2015 14:54:43 -0700 Subject: [PATCH 14/31] remove SHAPE_TYPE_CONVEX_HULL from libs and tests --- libraries/physics/src/ShapeInfoUtil.cpp | 140 ++++-------------------- libraries/physics/src/ShapeInfoUtil.h | 8 +- libraries/shared/src/ShapeInfo.cpp | 20 ++-- libraries/shared/src/ShapeInfo.h | 2 +- tests/physics/src/ShapeInfoTests.cpp | 16 +-- tests/physics/src/ShapeManagerTests.cpp | 16 +-- 6 files changed, 39 insertions(+), 163 deletions(-) diff --git a/libraries/physics/src/ShapeInfoUtil.cpp b/libraries/physics/src/ShapeInfoUtil.cpp index 8900c5a0dc..c6c76a98eb 100644 --- a/libraries/physics/src/ShapeInfoUtil.cpp +++ b/libraries/physics/src/ShapeInfoUtil.cpp @@ -14,107 +14,6 @@ #include "ShapeInfoUtil.h" #include "BulletUtil.h" -int ShapeInfoUtil::toBulletShapeType(int shapeInfoType) { - int bulletShapeType = INVALID_SHAPE_PROXYTYPE; - switch(shapeInfoType) { - case SHAPE_TYPE_BOX: - bulletShapeType = BOX_SHAPE_PROXYTYPE; - break; - case SHAPE_TYPE_SPHERE: - bulletShapeType = SPHERE_SHAPE_PROXYTYPE; - break; - case SHAPE_TYPE_CAPSULE_Y: - bulletShapeType = CAPSULE_SHAPE_PROXYTYPE; - break; - case SHAPE_TYPE_CONVEX_HULL: - bulletShapeType = CONVEX_HULL_SHAPE_PROXYTYPE; - break; - case SHAPE_TYPE_COMPOUND: - bulletShapeType = COMPOUND_SHAPE_PROXYTYPE; - break; - } - return bulletShapeType; -} - -int ShapeInfoUtil::fromBulletShapeType(int bulletShapeType) { - int shapeInfoType = SHAPE_TYPE_NONE; - switch(bulletShapeType) { - case BOX_SHAPE_PROXYTYPE: - shapeInfoType = SHAPE_TYPE_BOX; - break; - case SPHERE_SHAPE_PROXYTYPE: - shapeInfoType = SHAPE_TYPE_SPHERE; - break; - case CAPSULE_SHAPE_PROXYTYPE: - shapeInfoType = SHAPE_TYPE_CAPSULE_Y; - break; - case CONVEX_HULL_SHAPE_PROXYTYPE: - shapeInfoType = SHAPE_TYPE_CONVEX_HULL; - break; - case COMPOUND_SHAPE_PROXYTYPE: - shapeInfoType = SHAPE_TYPE_COMPOUND; - break; - } - return shapeInfoType; -} - -void ShapeInfoUtil::collectInfoFromShape(const btCollisionShape* shape, ShapeInfo& info) { - if (shape) { - int type = ShapeInfoUtil::fromBulletShapeType(shape->getShapeType()); - switch(type) { - case SHAPE_TYPE_BOX: { - const btBoxShape* boxShape = static_cast(shape); - info.setBox(bulletToGLM(boxShape->getHalfExtentsWithMargin())); - } - break; - case SHAPE_TYPE_SPHERE: { - const btSphereShape* sphereShape = static_cast(shape); - info.setSphere(sphereShape->getRadius()); - } - break; - case SHAPE_TYPE_CONVEX_HULL: { - const btConvexHullShape* convexHullShape = static_cast(shape); - const int numPoints = convexHullShape->getNumPoints(); - const btVector3* btPoints = convexHullShape->getUnscaledPoints(); - QVector> points; - QVector childPoints; - for (int i = 0; i < numPoints; i++) { - glm::vec3 point(btPoints->getX(), btPoints->getY(), btPoints->getZ()); - childPoints << point; - } - points << childPoints; - info.setConvexHulls(points); - } - break; - case SHAPE_TYPE_COMPOUND: { - const btCompoundShape* compoundShape = static_cast(shape); - const int numChildShapes = compoundShape->getNumChildShapes(); - QVector> points; - for (int i = 0; i < numChildShapes; i ++) { - const btCollisionShape* childShape = compoundShape->getChildShape(i); - const btConvexHullShape* convexHullShape = static_cast(childShape); - const int numPoints = convexHullShape->getNumPoints(); - const btVector3* btPoints = convexHullShape->getUnscaledPoints(); - - QVector childPoints; - for (int j = 0; j < numPoints; j++) { - glm::vec3 point(btPoints->getX(), btPoints->getY(), btPoints->getZ()); - childPoints << point; - } - points << childPoints; - } - info.setConvexHulls(points); - } - break; - default: { - info.clear(); - } - break; - } - } else { - info.clear(); - } -} btCollisionShape* ShapeInfoUtil::createShapeFromInfo(const ShapeInfo& info) { btCollisionShape* shape = NULL; @@ -135,33 +34,34 @@ btCollisionShape* ShapeInfoUtil::createShapeFromInfo(const ShapeInfo& info) { shape = new btCapsuleShape(radius, height); } break; - case SHAPE_TYPE_CONVEX_HULL: { - auto hull = new btConvexHullShape(); - const QVector>& points = info.getPoints(); - foreach (glm::vec3 point, points[0]) { - btVector3 btPoint(point[0], point[1], point[2]); - hull->addPoint(btPoint, false); - } - hull->recalcLocalAabb(); - shape = hull; - } - break; case SHAPE_TYPE_COMPOUND: { - auto compound = new btCompoundShape(); const QVector>& points = info.getPoints(); - - btTransform trans; - trans.setIdentity(); - foreach (QVector hullPoints, points) { + uint32_t numSubShapes = info.getNumSubShapes(); + if (numSubShapes == 1) { auto hull = new btConvexHullShape(); - foreach (glm::vec3 point, hullPoints) { + const QVector>& points = info.getPoints(); + foreach (glm::vec3 point, points[0]) { btVector3 btPoint(point[0], point[1], point[2]); hull->addPoint(btPoint, false); } hull->recalcLocalAabb(); - compound->addChildShape (trans, hull); + shape = hull; + } else { + assert(numSubShapes > 1); + auto compound = new btCompoundShape(); + btTransform trans; + trans.setIdentity(); + foreach (QVector hullPoints, points) { + auto hull = new btConvexHullShape(); + foreach (glm::vec3 point, hullPoints) { + btVector3 btPoint(point[0], point[1], point[2]); + hull->addPoint(btPoint, false); + } + hull->recalcLocalAabb(); + compound->addChildShape (trans, hull); + } + shape = compound; } - shape = compound; } break; } diff --git a/libraries/physics/src/ShapeInfoUtil.h b/libraries/physics/src/ShapeInfoUtil.h index 9585161440..39a897019c 100644 --- a/libraries/physics/src/ShapeInfoUtil.h +++ b/libraries/physics/src/ShapeInfoUtil.h @@ -19,16 +19,10 @@ // translates between ShapeInfo and btShape +// TODO: rename this to ShapeFactory namespace ShapeInfoUtil { - // XXX is collectInfoFromShape no longer strictly needed? - void collectInfoFromShape(const btCollisionShape* shape, ShapeInfo& info); - btCollisionShape* createShapeFromInfo(const ShapeInfo& info); - - // TODO? just use bullet shape types everywhere? - int toBulletShapeType(int shapeInfoType); - int fromBulletShapeType(int bulletShapeType); }; #endif // hifi_ShapeInfoUtil_h diff --git a/libraries/shared/src/ShapeInfo.cpp b/libraries/shared/src/ShapeInfo.cpp index 5fe1fc230d..544df35b86 100644 --- a/libraries/shared/src/ShapeInfo.cpp +++ b/libraries/shared/src/ShapeInfo.cpp @@ -37,12 +37,6 @@ void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString _halfExtents = glm::vec3(radius); break; } - case SHAPE_TYPE_CONVEX_HULL: - _url = QUrl(url); - // halfExtents aren't used by convex-hull or compound convex-hull except as part of - // the generation of the key for the ShapeManager. - _halfExtents = halfExtents; - break; case SHAPE_TYPE_COMPOUND: _url = QUrl(url); _halfExtents = halfExtents; @@ -78,12 +72,8 @@ void ShapeInfo::setEllipsoid(const glm::vec3& halfExtents) { } void ShapeInfo::setConvexHulls(const QVector>& points) { - if (points.size() == 1) { - _type = SHAPE_TYPE_CONVEX_HULL; - } else { - _type = SHAPE_TYPE_COMPOUND; - } _points = points; + _type = (_points.size() > 0) ? SHAPE_TYPE_COMPOUND : SHAPE_TYPE_NONE; _doubleHashKey.clear(); } @@ -95,6 +85,14 @@ void ShapeInfo::setCapsuleY(float radius, float halfHeight) { _doubleHashKey.clear(); } +uint32_t ShapeInfo::getNumSubShapes() const { + if (_type == SHAPE_TYPE_NONE) { + return 0; + } else if (_type == SHAPE_TYPE_COMPOUND) { + return _points.size(); + } + return 1; +} float ShapeInfo::computeVolume() const { const float DEFAULT_VOLUME = 1.0f; float volume = DEFAULT_VOLUME; diff --git a/libraries/shared/src/ShapeInfo.h b/libraries/shared/src/ShapeInfo.h index 4dce121d64..8770ef62c7 100644 --- a/libraries/shared/src/ShapeInfo.h +++ b/libraries/shared/src/ShapeInfo.h @@ -24,7 +24,6 @@ enum ShapeType { SHAPE_TYPE_BOX, SHAPE_TYPE_SPHERE, SHAPE_TYPE_ELLIPSOID, - SHAPE_TYPE_CONVEX_HULL, SHAPE_TYPE_PLANE, SHAPE_TYPE_COMPOUND, SHAPE_TYPE_CAPSULE_X, @@ -52,6 +51,7 @@ public: const glm::vec3& getHalfExtents() const { return _halfExtents; } const QVector>& getPoints() const { return _points; } + uint32_t getNumSubShapes() const; void clearPoints () { _points.clear(); } void appendToPoints (const QVector& newPoints) { _points << newPoints; } diff --git a/tests/physics/src/ShapeInfoTests.cpp b/tests/physics/src/ShapeInfoTests.cpp index bf2a98eb10..ef5bd0be39 100644 --- a/tests/physics/src/ShapeInfoTests.cpp +++ b/tests/physics/src/ShapeInfoTests.cpp @@ -147,9 +147,7 @@ void ShapeInfoTests::testBoxShape() { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: NULL Box shape" << std::endl; } - ShapeInfo otherInfo; - ShapeInfoUtil::collectInfoFromShape(shape, otherInfo); - + ShapeInfo otherInfo = info; DoubleHashKey otherKey = otherInfo.getHash(); if (key.getHash() != otherKey.getHash()) { std::cout << __FILE__ << ":" << __LINE__ @@ -172,9 +170,7 @@ void ShapeInfoTests::testSphereShape() { btCollisionShape* shape = ShapeInfoUtil::createShapeFromInfo(info); - ShapeInfo otherInfo; - ShapeInfoUtil::collectInfoFromShape(shape, otherInfo); - + ShapeInfo otherInfo = info; DoubleHashKey otherKey = otherInfo.getHash(); if (key.getHash() != otherKey.getHash()) { std::cout << __FILE__ << ":" << __LINE__ @@ -198,9 +194,7 @@ void ShapeInfoTests::testCylinderShape() { btCollisionShape* shape = ShapeInfoUtil::createShapeFromInfo(info); - ShapeInfo otherInfo; - ShapeInfoUtil::collectInfoFromShape(shape, otherInfo); - + ShapeInfo otherInfo = info; DoubleHashKey otherKey = otherInfo.getHash(); if (key.getHash() != otherKey.getHash()) { std::cout << __FILE__ << ":" << __LINE__ @@ -225,9 +219,7 @@ void ShapeInfoTests::testCapsuleShape() { btCollisionShape* shape = ShapeInfoUtil::createShapeFromInfo(info); - ShapeInfo otherInfo; - ShapeInfoUtil::collectInfoFromShape(shape, otherInfo); - + ShapeInfo otherInfo = info; DoubleHashKey otherKey = otherInfo.getHash(); if (key.getHash() != otherKey.getHash()) { std::cout << __FILE__ << ":" << __LINE__ diff --git a/tests/physics/src/ShapeManagerTests.cpp b/tests/physics/src/ShapeManagerTests.cpp index d86f296d0e..d2b4ca70fa 100644 --- a/tests/physics/src/ShapeManagerTests.cpp +++ b/tests/physics/src/ShapeManagerTests.cpp @@ -187,9 +187,7 @@ void ShapeManagerTests::addBoxShape() { ShapeManager shapeManager; btCollisionShape* shape = shapeManager.getShape(info); - ShapeInfo otherInfo; - ShapeInfoUtil::collectInfoFromShape(shape, otherInfo); - + ShapeInfo otherInfo = info; btCollisionShape* otherShape = shapeManager.getShape(otherInfo); if (shape != otherShape) { std::cout << __FILE__ << ":" << __LINE__ @@ -205,9 +203,7 @@ void ShapeManagerTests::addSphereShape() { ShapeManager shapeManager; btCollisionShape* shape = shapeManager.getShape(info); - ShapeInfo otherInfo; - ShapeInfoUtil::collectInfoFromShape(shape, otherInfo); - + ShapeInfo otherInfo = info; btCollisionShape* otherShape = shapeManager.getShape(otherInfo); if (shape != otherShape) { std::cout << __FILE__ << ":" << __LINE__ @@ -225,9 +221,7 @@ void ShapeManagerTests::addCylinderShape() { ShapeManager shapeManager; btCollisionShape* shape = shapeManager.getShape(info); - ShapeInfo otherInfo; - ShapeInfoUtil::collectInfoFromShape(shape, otherInfo); - + ShapeInfo otherInfo = info; btCollisionShape* otherShape = shapeManager.getShape(otherInfo); if (shape != otherShape) { std::cout << __FILE__ << ":" << __LINE__ @@ -246,9 +240,7 @@ void ShapeManagerTests::addCapsuleShape() { ShapeManager shapeManager; btCollisionShape* shape = shapeManager.getShape(info); - ShapeInfo otherInfo; - ShapeInfoUtil::collectInfoFromShape(shape, otherInfo); - + ShapeInfo otherInfo = info; btCollisionShape* otherShape = shapeManager.getShape(otherInfo); if (shape != otherShape) { std::cout << __FILE__ << ":" << __LINE__ From 7da1c518771b6d2d875b68ca6e264bd363777594 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 14 Apr 2015 14:55:42 -0700 Subject: [PATCH 15/31] whoops, missed a file --- libraries/physics/src/ShapeManager.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libraries/physics/src/ShapeManager.cpp b/libraries/physics/src/ShapeManager.cpp index 2a73f5d28f..dd67c2c73a 100644 --- a/libraries/physics/src/ShapeManager.cpp +++ b/libraries/physics/src/ShapeManager.cpp @@ -35,7 +35,7 @@ btCollisionShape* ShapeManager::getShape(const ShapeInfo& info) { // Very small or large objects are not supported. float diagonal = 4.0f * glm::length2(info.getHalfExtents()); const float MIN_SHAPE_DIAGONAL_SQUARED = 3.0e-4f; // 1 cm cube - const float MAX_SHAPE_DIAGONAL_SQUARED = 3.0e6f; // 1000 m cube + //const float MAX_SHAPE_DIAGONAL_SQUARED = 3.0e6f; // 1000 m cube if (diagonal < MIN_SHAPE_DIAGONAL_SQUARED /* || diagonal > MAX_SHAPE_DIAGONAL_SQUARED*/ ) { // qCDebug(physics) << "ShapeManager::getShape -- not making shape due to size" << diagonal; return NULL; @@ -104,11 +104,9 @@ void ShapeManager::collectGarbage() { ShapeReference* shapeRef = _shapeMap.find(key); if (shapeRef && shapeRef->refCount == 0) { // if the shape we're about to delete is compound, delete the children first. - auto shapeType = ShapeInfoUtil::fromBulletShapeType(shapeRef->shape->getShapeType()); - if (shapeType == SHAPE_TYPE_COMPOUND) { + if (shapeRef->shape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) { const btCompoundShape* compoundShape = static_cast(shapeRef->shape); const int numChildShapes = compoundShape->getNumChildShapes(); - QVector> points; for (int i = 0; i < numChildShapes; i ++) { const btCollisionShape* childShape = compoundShape->getChildShape(i); delete childShape; From 5b81b5b11b5236247044d065afc080609b084d5a Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 14 Apr 2015 14:56:32 -0700 Subject: [PATCH 16/31] removing SHAPE_TYPE_CONVEX_HULL from entities lib --- .../src/RenderableModelEntityItem.cpp | 86 ++++++++----------- .../src/RenderableModelEntityItem.h | 3 - .../entities/src/EntityItemProperties.cpp | 2 +- libraries/entities/src/ModelEntityItem.cpp | 10 +++ libraries/entities/src/ModelEntityItem.h | 4 +- 5 files changed, 49 insertions(+), 56 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 1d601d1294..3dd8f79fff 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -274,54 +274,50 @@ void RenderableModelEntityItem::setCollisionModelURL(const QString& url) { } } -bool RenderableModelEntityItem::hasCollisionModel() const { - if (_model) { - return ! _model->getCollisionURL().isEmpty(); - } else { - return !_collisionModelURL.isEmpty(); - } -} - -const QString& RenderableModelEntityItem::getCollisionModelURL() const { - // assert (!_model || _collisionModelURL == _model->getCollisionURL().toString()); - return _collisionModelURL; -} - bool RenderableModelEntityItem::isReadyToComputeShape() { + ShapeType type = getShapeType(); + if (type == SHAPE_TYPE_COMPOUND) { - if (!_model) { - return false; // hmm... + if (!_model) { + return false; // hmm... + } + + assert(!_model->getCollisionURL().isEmpty()); + + if (_model->getURL().isEmpty()) { + // we need a render geometry with a scale to proceed, so give up. + return false; + } + + const QSharedPointer collisionNetworkGeometry = _model->getCollisionGeometry(); + const QSharedPointer renderNetworkGeometry = _model->getGeometry(); + + if ((! collisionNetworkGeometry.isNull() && collisionNetworkGeometry->isLoadedWithTextures()) && + (! renderNetworkGeometry.isNull() && renderNetworkGeometry->isLoadedWithTextures())) { + // we have both URLs AND both geometries AND they are both fully loaded. + return true; + } + + // the model is still being downloaded. + std::cout << "adebug still being downloaded" << std::endl; // adebug + return false; } - - if (_model->getCollisionURL().isEmpty()) { - // no collision-model url, so we're ready to compute a shape (of type None). - return true; - } - if (_model->getURL().isEmpty()) { - // we need a render geometry with a scale to proceed, so give up. - return true; - } - - const QSharedPointer collisionNetworkGeometry = _model->getCollisionGeometry(); - const QSharedPointer renderNetworkGeometry = _model->getGeometry(); - - if ((! collisionNetworkGeometry.isNull() && collisionNetworkGeometry->isLoadedWithTextures()) && - (! renderNetworkGeometry.isNull() && renderNetworkGeometry->isLoadedWithTextures())) { - // we have both URLs AND both geometries AND they are both fully loaded. - return true; - } - - // the model is still being downloaded. - return false; + return true; } void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) { - if (_model->getCollisionURL().isEmpty() || _model->getURL().isEmpty()) { - info.setParams(getShapeType(), 0.5f * getDimensions()); + ShapeType type = getShapeType(); + if (type != SHAPE_TYPE_COMPOUND) { + ModelEntityItem::computeShapeInfo(info); + info.setParams(_shapeType, 0.5f * getDimensions()); } else { const QSharedPointer collisionNetworkGeometry = _model->getCollisionGeometry(); - const FBXGeometry& collisionGeometry = collisionNetworkGeometry->getFBXGeometry(); + // should never fall in here when collision model not fully loaded + // hence we assert collisionNetworkGeometry is not NULL + assert(!collisionNetworkGeometry.isNull()); + + const FBXGeometry& collisionGeometry = collisionNetworkGeometry->getFBXGeometry(); const QSharedPointer renderNetworkGeometry = _model->getGeometry(); const FBXGeometry& renderGeometry = renderNetworkGeometry->getFBXGeometry(); @@ -415,18 +411,8 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) { } glm::vec3 collisionModelDimensions = box.getDimensions(); - info.setParams(getShapeType(), collisionModelDimensions, _collisionModelURL); + info.setParams(_shapeType, collisionModelDimensions, _collisionModelURL); info.setConvexHulls(_points); } } -ShapeType RenderableModelEntityItem::getShapeType() const { - // XXX make hull an option in edit.js ? - if (!_model || _model->getCollisionURL().isEmpty()) { - return _shapeType; - } else if (_points.size() == 1) { - return SHAPE_TYPE_CONVEX_HULL; - } else { - return SHAPE_TYPE_COMPOUND; - } -} diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 9146a04cf8..b632357942 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -53,12 +53,9 @@ public: bool needsToCallUpdate() const; virtual void setCollisionModelURL(const QString& url); - virtual bool hasCollisionModel() const; - virtual const QString& getCollisionModelURL() const; bool isReadyToComputeShape(); void computeShapeInfo(ShapeInfo& info); - ShapeType getShapeType() const; private: void remapTextures(); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index bf2ea640f1..8a25d59f26 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -192,7 +192,7 @@ void buildStringToShapeTypeLookup() { stringToShapeTypeLookup["box"] = SHAPE_TYPE_BOX; stringToShapeTypeLookup["sphere"] = SHAPE_TYPE_SPHERE; stringToShapeTypeLookup["ellipsoid"] = SHAPE_TYPE_ELLIPSOID; - stringToShapeTypeLookup["convex-hull"] = SHAPE_TYPE_CONVEX_HULL; + stringToShapeTypeLookup["convex-hull"] = SHAPE_TYPE_COMPOUND; stringToShapeTypeLookup["plane"] = SHAPE_TYPE_PLANE; stringToShapeTypeLookup["compound"] = SHAPE_TYPE_COMPOUND; stringToShapeTypeLookup["capsule-x"] = SHAPE_TYPE_CAPSULE_X; diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index cdbc3d9441..acee2a594f 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -282,6 +282,16 @@ void ModelEntityItem::updateShapeType(ShapeType type) { } } +// virtual +ShapeType ModelEntityItem::getShapeType() const { + if (_shapeType == SHAPE_TYPE_COMPOUND) { + return hasCollisionModel() ? SHAPE_TYPE_COMPOUND : SHAPE_TYPE_NONE; + } + else { + return _shapeType; + } +} + void ModelEntityItem::setCollisionModelURL(const QString& url) { if (_collisionModelURL != url) { _collisionModelURL = url; diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 9e34de445b..057c5babaf 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -49,7 +49,7 @@ public: virtual void debugDump() const; void updateShapeType(ShapeType type); - virtual ShapeType getShapeType() const { return _shapeType; } + virtual ShapeType getShapeType() const; // TODO: Move these to subclasses, or other appropriate abstraction // getters/setters applicable to models and particles @@ -63,7 +63,7 @@ public: const QString& getModelURL() const { return _modelURL; } static const QString DEFAULT_COLLISION_MODEL_URL; - virtual const QString& getCollisionModelURL() const { return _collisionModelURL; } + const QString& getCollisionModelURL() const { return _collisionModelURL; } bool hasAnimation() const { return !_animationURL.isEmpty(); } static const QString DEFAULT_ANIMATION_URL; From 8623a0606cd48be6fa43ec7095419a40b9a85bc2 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 14 Apr 2015 15:39:24 -0700 Subject: [PATCH 17/31] remove accidentally commited debug code --- libraries/entities-renderer/src/RenderableModelEntityItem.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 3dd8f79fff..c67e1f04e5 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -299,7 +299,6 @@ bool RenderableModelEntityItem::isReadyToComputeShape() { } // the model is still being downloaded. - std::cout << "adebug still being downloaded" << std::endl; // adebug return false; } return true; From aec42cf2dc64935fa22dfc4beb422d207b86c330 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 14 Apr 2015 15:39:49 -0700 Subject: [PATCH 18/31] enforce ShapeType agreement for ModeEntityItem --- libraries/entities/src/ModelEntityItem.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index acee2a594f..e98f784765 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -276,6 +276,16 @@ void ModelEntityItem::debugDump() const { } void ModelEntityItem::updateShapeType(ShapeType type) { + // BEGIN_TEMPORARY_WORKAROUND + // we have allowed inconsistent ShapeType's to be stored in SVO files in the past (this was a bug) + // but we are now enforcing the entity properties to be consistent. To make the possible we're + // introducing a temporary workaround: we will ignore ShapeType updates that conflict with the + // _collisionModelURL. + if (hasCollisionModel()) { + type = SHAPE_TYPE_COMPOUND; + } + // END_TEMPORARY_WORKAROUND + if (type != _shapeType) { _shapeType = type; _dirtyFlags |= EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS; @@ -296,6 +306,7 @@ void ModelEntityItem::setCollisionModelURL(const QString& url) { if (_collisionModelURL != url) { _collisionModelURL = url; _dirtyFlags |= EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS; + _shapeType = _collisionModelURL.isEmpty() ? SHAPE_TYPE_NONE : SHAPE_TYPE_COMPOUND; } } From 87030236cbfda76af44eefc8036fac425ea3609e Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 14 Apr 2015 15:53:24 -0700 Subject: [PATCH 19/31] working version with the gpu::SAmpler and the gpu::Framebuffer --- libraries/gpu/src/gpu/Format.h | 14 ++ libraries/gpu/src/gpu/Framebuffer.cpp | 13 +- libraries/gpu/src/gpu/GLBackend.h | 4 + libraries/gpu/src/gpu/GLBackendState.cpp | 20 +- libraries/gpu/src/gpu/GLBackendTexture.cpp | 186 ++++++++++++------ libraries/gpu/src/gpu/State.h | 16 +- libraries/gpu/src/gpu/Texture.cpp | 25 ++- libraries/gpu/src/gpu/Texture.h | 99 +++++++++- .../src/DeferredLightingEffect.cpp | 2 +- libraries/render-utils/src/Model.cpp | 2 +- libraries/render-utils/src/TextureCache.cpp | 33 +--- 11 files changed, 292 insertions(+), 122 deletions(-) diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index d3330fd147..e982f27ec2 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -179,6 +179,20 @@ public: uint8 _type : 4; }; + +enum ComparisonFunction { + NEVER = 0, + LESS, + EQUAL, + LESS_EQUAL, + GREATER, + NOT_EQUAL, + GREATER_EQUAL, + ALWAYS, + + NUM_COMPARISON_FUNCS, +}; + }; diff --git a/libraries/gpu/src/gpu/Framebuffer.cpp b/libraries/gpu/src/gpu/Framebuffer.cpp index f671dba28e..84e0fcca7a 100755 --- a/libraries/gpu/src/gpu/Framebuffer.cpp +++ b/libraries/gpu/src/gpu/Framebuffer.cpp @@ -32,8 +32,8 @@ Framebuffer* Framebuffer::create() { Framebuffer* Framebuffer::create( const Format& colorBufferFormat, const Format& depthStencilBufferFormat, uint16 width, uint16 height, uint16 numSamples) { auto framebuffer = Framebuffer::create(); - auto colorTexture = TexturePointer(Texture::create2D(colorBufferFormat, width, height)); - auto depthTexture = TexturePointer(Texture::create2D(depthStencilBufferFormat, width, height)); + auto colorTexture = TexturePointer(Texture::create2D(colorBufferFormat, width, height, Sampler(Sampler::FILTER_MIN_MAG_POINT))); + auto depthTexture = TexturePointer(Texture::create2D(depthStencilBufferFormat, width, height, Sampler(Sampler::FILTER_MIN_MAG_POINT))); framebuffer->setRenderBuffer(0, colorTexture); framebuffer->setDepthStencilBuffer(depthTexture, depthStencilBufferFormat); @@ -44,6 +44,15 @@ Framebuffer* Framebuffer::create( const Format& colorBufferFormat, const Format& Framebuffer* Framebuffer::createShadowmap(uint16 width) { auto framebuffer = Framebuffer::create(); auto depthTexture = TexturePointer(Texture::create2D(Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH), width, width)); + + Sampler::Desc samplerDesc; + samplerDesc._borderColor = glm::vec4(1.0f); + samplerDesc._wrapModeU = Sampler::WRAP_BORDER; + samplerDesc._wrapModeV = Sampler::WRAP_BORDER; + samplerDesc._filter = Sampler::FILTER_MIN_MAG_LINEAR; + samplerDesc._comparisonFunc = LESS_EQUAL; + + depthTexture->setSampler(Sampler(samplerDesc)); framebuffer->setDepthStencilBuffer(depthTexture, Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH)); diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index e3069f5205..b725fa46d0 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -53,6 +53,7 @@ public: Stamp _storageStamp; Stamp _contentStamp; GLuint _texture; + GLenum _target; GLuint _size; GLTexture(); @@ -61,6 +62,9 @@ public: static GLTexture* syncGPUObject(const Texture& texture); static GLuint getTextureID(const TexturePointer& texture); + // very specific for now + static void syncSampler(const Sampler& sampler, Texture::Type type, GLTexture* object); + class GLShader : public GPUObject { public: GLuint _shader; diff --git a/libraries/gpu/src/gpu/GLBackendState.cpp b/libraries/gpu/src/gpu/GLBackendState.cpp index 7707922b81..fb85d30fe2 100644 --- a/libraries/gpu/src/gpu/GLBackendState.cpp +++ b/libraries/gpu/src/gpu/GLBackendState.cpp @@ -237,26 +237,26 @@ void GLBackend::resetPipelineState(State::Signature nextSignature) { } } -State::ComparisonFunction comparisonFuncFromGL(GLenum func) { +ComparisonFunction comparisonFuncFromGL(GLenum func) { if (func == GL_NEVER) { - return State::NEVER; + return NEVER; } else if (func == GL_LESS) { - return State::LESS; + return LESS; } else if (func == GL_EQUAL) { - return State::EQUAL; + return EQUAL; } else if (func == GL_LEQUAL) { - return State::LESS_EQUAL; + return LESS_EQUAL; } else if (func == GL_GREATER) { - return State::GREATER; + return GREATER; } else if (func == GL_NOTEQUAL) { - return State::NOT_EQUAL; + return NOT_EQUAL; } else if (func == GL_GEQUAL) { - return State::GREATER_EQUAL; + return GREATER_EQUAL; } else if (func == GL_ALWAYS) { - return State::ALWAYS; + return ALWAYS; } - return State::ALWAYS; + return ALWAYS; } State::StencilOp stencilOpFromGL(GLenum stencilOp) { diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index da6d993171..b8f9ab0bf1 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -16,7 +16,8 @@ GLBackend::GLTexture::GLTexture() : _storageStamp(0), _contentStamp(0), _texture(0), - _size(0) + _size(0), + _target(GL_TEXTURE_2D) {} GLBackend::GLTexture::~GLTexture() { @@ -285,69 +286,77 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) { // GO through the process of allocating the correct storage and/or update the content switch (texture.getType()) { case Texture::TEX_2D: { - if (needUpdate) { - if (texture.isStoredMipAvailable(0)) { - GLint boundTex = -1; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTex); - - Texture::PixelsPointer mip = texture.accessStoredMip(0); - const GLvoid* bytes = mip->_sysmem.read(); - Element srcFormat = mip->_format; - - GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), srcFormat); - - glBindTexture(GL_TEXTURE_2D, object->_texture); - glTexSubImage2D(GL_TEXTURE_2D, 0, - texelFormat.internalFormat, texture.getWidth(), texture.getHeight(), 0, - texelFormat.format, texelFormat.type, bytes); - - if (texture.isAutogenerateMips()) { - glGenerateMipmap(GL_TEXTURE_2D); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - } - - // At this point the mip piels have been loaded, we can notify - texture.notifyGPULoaded(0); - - glBindTexture(GL_TEXTURE_2D, boundTex); - object->_contentStamp = texture.getDataStamp(); - } - } else { - const GLvoid* bytes = 0; - Element srcFormat = texture.getTexelFormat(); - if (texture.isStoredMipAvailable(0)) { - Texture::PixelsPointer mip = texture.accessStoredMip(0); - - bytes = mip->_sysmem.read(); - srcFormat = mip->_format; - - object->_contentStamp = texture.getDataStamp(); - } - + if (texture.getNumSlices() == 1) { GLint boundTex = -1; glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTex); glBindTexture(GL_TEXTURE_2D, object->_texture); - GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), srcFormat); - - glTexImage2D(GL_TEXTURE_2D, 0, - texelFormat.internalFormat, texture.getWidth(), texture.getHeight(), 0, - texelFormat.format, texelFormat.type, bytes); + if (needUpdate) { + if (texture.isStoredMipAvailable(0)) { + Texture::PixelsPointer mip = texture.accessStoredMip(0); + const GLvoid* bytes = mip->_sysmem.read(); + Element srcFormat = mip->_format; + + GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), srcFormat); - if (bytes && texture.isAutogenerateMips()) { - glGenerateMipmap(GL_TEXTURE_2D); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glBindTexture(GL_TEXTURE_2D, object->_texture); + glTexSubImage2D(GL_TEXTURE_2D, 0, + texelFormat.internalFormat, texture.getWidth(), texture.getHeight(), 0, + texelFormat.format, texelFormat.type, bytes); + + if (texture.isAutogenerateMips()) { + glGenerateMipmap(GL_TEXTURE_2D); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + } + + object->_target = GL_TEXTURE_2D; + + syncSampler(texture.getSampler(), texture.getType(), object); + + + // At this point the mip piels have been loaded, we can notify + texture.notifyGPULoaded(0); + + object->_contentStamp = texture.getDataStamp(); + } } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + const GLvoid* bytes = 0; + Element srcFormat = texture.getTexelFormat(); + if (texture.isStoredMipAvailable(0)) { + Texture::PixelsPointer mip = texture.accessStoredMip(0); + + bytes = mip->_sysmem.read(); + srcFormat = mip->_format; + + object->_contentStamp = texture.getDataStamp(); + } + + GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), srcFormat); + + glTexImage2D(GL_TEXTURE_2D, 0, + texelFormat.internalFormat, texture.getWidth(), texture.getHeight(), 0, + texelFormat.format, texelFormat.type, bytes); + + if (bytes && texture.isAutogenerateMips()) { + glGenerateMipmap(GL_TEXTURE_2D); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + + object->_target = GL_TEXTURE_2D; + + syncSampler(texture.getSampler(), texture.getType(), object); + + // At this point the mip piels have been loaded, we can notify + texture.notifyGPULoaded(0); + + object->_storageStamp = texture.getStamp(); + object->_size = texture.getSize(); } - // At this point the mip piels have been loaded, we can notify - texture.notifyGPULoaded(0); - glBindTexture(GL_TEXTURE_2D, boundTex); - object->_storageStamp = texture.getStamp(); - object->_size = texture.getSize(); } break; } @@ -373,3 +382,70 @@ GLuint GLBackend::getTextureID(const TexturePointer& texture) { } } +void GLBackend::syncSampler(const Sampler& sampler, Texture::Type type, GLTexture* object) { + if (!object) return; + if (!object->_texture) return; + + class GLFilterMode { + public: + GLint minFilter; + GLint magFilter; + }; + static const GLFilterMode filterModes[] = { + {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, + {GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR}, //FILTER_MIN_POINT_MAG_MIP_LINEAR, + {GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST}, //FILTER_MIN_LINEAR_MAG_MIP_POINT, + {GL_LINEAR_MIPMAP_LINEAR, GL_NEAREST}, //FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR, + {GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR}, //FILTER_MIN_MAG_LINEAR_MIP_POINT, + {GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}, //FILTER_MIN_MAG_MIP_LINEAR, + {GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR} //FILTER_ANISOTROPIC, + }; + + auto fm = filterModes[sampler.getFilter()]; + glTexParameteri(object->_target, GL_TEXTURE_MIN_FILTER, fm.minFilter); + glTexParameteri(object->_target, GL_TEXTURE_MAG_FILTER, fm.magFilter); + + static const GLenum comparisonFuncs[] = { + GL_NEVER, + GL_LESS, + GL_EQUAL, + GL_LEQUAL, + GL_GREATER, + GL_NOTEQUAL, + GL_GEQUAL, + GL_ALWAYS }; + + if (sampler.doComparison()) { + glTexParameteri(object->_target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); + glTexParameteri(object->_target, GL_TEXTURE_COMPARE_FUNC, comparisonFuncs[sampler.getComparisonFunction()]); + } else { + glTexParameteri(object->_target, GL_TEXTURE_COMPARE_MODE, GL_NONE); + } + + static const GLenum wrapModes[] = { + GL_REPEAT, // WRAP_REPEAT, + GL_MIRRORED_REPEAT, // WRAP_MIRROR, + GL_CLAMP_TO_EDGE, // WRAP_CLAMP, + GL_CLAMP_TO_BORDER, // WRAP_BORDER, + GL_MIRROR_CLAMP_TO_EDGE_EXT }; // WRAP_MIRROR_ONCE, + + glTexParameteri(object->_target, GL_TEXTURE_WRAP_S, wrapModes[sampler.getWrapModeU()]); + glTexParameteri(object->_target, GL_TEXTURE_WRAP_T, wrapModes[sampler.getWrapModeV()]); + glTexParameteri(object->_target, GL_TEXTURE_WRAP_R, wrapModes[sampler.getWrapModeW()]); + + glTexParameterfv(object->_target, GL_TEXTURE_BORDER_COLOR, (const float*) &sampler.getBorderColor()); + glTexParameteri(object->_target, GL_TEXTURE_BASE_LEVEL, sampler.getMipOffset()); + glTexParameterf(object->_target, GL_TEXTURE_MIN_LOD, (float) sampler.getMinMip()); + glTexParameterf(object->_target, GL_TEXTURE_MAX_LOD, (sampler.getMaxMip() == Sampler::MAX_MIP_LEVEL ? 1000.f : sampler.getMaxMip())); + glTexParameterf(object->_target, GL_TEXTURE_MAX_ANISOTROPY_EXT, sampler.getMaxAnisotropy()); + CHECK_GL_ERROR(); + +} diff --git a/libraries/gpu/src/gpu/State.h b/libraries/gpu/src/gpu/State.h index 84f44d8efd..9307882bab 100755 --- a/libraries/gpu/src/gpu/State.h +++ b/libraries/gpu/src/gpu/State.h @@ -42,19 +42,8 @@ public: virtual ~State(); const Stamp getStamp() const { return _stamp; } - - enum ComparisonFunction { - NEVER = 0, - LESS, - EQUAL, - LESS_EQUAL, - GREATER, - NOT_EQUAL, - GREATER_EQUAL, - ALWAYS, - - NUM_COMPARISON_FUNCS, - }; + + typedef ::gpu::ComparisonFunction ComparisonFunction; enum FillMode { FILL_POINT = 0, @@ -415,5 +404,4 @@ typedef std::vector< StatePointer > States; }; - #endif diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index 43d8c991b6..76cac74a59 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -93,23 +93,23 @@ bool Texture::Storage::assignMipData(uint16 level, const Element& format, Size s return allocated == size; } -Texture* Texture::create1D(const Element& texelFormat, uint16 width) { - return create(TEX_1D, texelFormat, width, 1, 1, 1, 1); +Texture* Texture::create1D(const Element& texelFormat, uint16 width, const Sampler& sampler) { + return create(TEX_1D, texelFormat, width, 1, 1, 1, 1, sampler); } -Texture* Texture::create2D(const Element& texelFormat, uint16 width, uint16 height) { - return create(TEX_2D, texelFormat, width, height, 1, 1, 1); +Texture* Texture::create2D(const Element& texelFormat, uint16 width, uint16 height, const Sampler& sampler) { + return create(TEX_2D, texelFormat, width, height, 1, 1, 1, sampler); } -Texture* Texture::create3D(const Element& texelFormat, uint16 width, uint16 height, uint16 depth) { - return create(TEX_3D, texelFormat, width, height, depth, 1, 1); +Texture* Texture::create3D(const Element& texelFormat, uint16 width, uint16 height, uint16 depth, const Sampler& sampler) { + return create(TEX_3D, texelFormat, width, height, depth, 1, 1, sampler); } -Texture* Texture::createCube(const Element& texelFormat, uint16 width) { - return create(TEX_CUBE, texelFormat, width, width, 1, 1, 1); +Texture* Texture::createCube(const Element& texelFormat, uint16 width, const Sampler& sampler) { + return create(TEX_CUBE, texelFormat, width, width, 1, 1, 1, sampler); } -Texture* Texture::create(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices) +Texture* Texture::create(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices, const Sampler& sampler) { Texture* tex = new Texture(); tex->_storage.reset(new Storage()); @@ -118,6 +118,8 @@ Texture* Texture::create(Type type, const Element& texelFormat, uint16 width, ui tex->_maxMip = 0; tex->resize(type, texelFormat, width, height, depth, numSamples, numSlices); + tex->_sampler = sampler; + return tex; } @@ -346,3 +348,8 @@ uint16 Texture::evalNumSamplesUsed(uint16 numSamplesTried) { return sample; } + +void Texture::setSampler(const Sampler& sampler) { + _sampler = sampler; + _samplerStamp++; +} diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index cb124b7b08..1d1e82123a 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -16,6 +16,85 @@ namespace gpu { +class Sampler { +public: + + enum Filter { + FILTER_MIN_MAG_POINT, // top mip only + FILTER_MIN_POINT_MAG_LINEAR, // top mip only + FILTER_MIN_LINEAR_MAG_POINT, // top mip only + FILTER_MIN_MAG_LINEAR, // top mip only + + FILTER_MIN_MAG_MIP_POINT, + FILTER_MIN_MAG_POINT_MIP_LINEAR, + FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT, + FILTER_MIN_POINT_MAG_MIP_LINEAR, + FILTER_MIN_LINEAR_MAG_MIP_POINT, + FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR, + FILTER_MIN_MAG_LINEAR_MIP_POINT, + FILTER_MIN_MAG_MIP_LINEAR, + FILTER_ANISOTROPIC, + + NUM_FILTERS, + }; + + enum WrapMode { + WRAP_REPEAT = 0, + WRAP_MIRROR, + WRAP_CLAMP, + WRAP_BORDER, + WRAP_MIRROR_ONCE, + + NUM_WRAP_MODES + }; + + static const uint8 MAX_MIP_LEVEL = 0xFF; + + class Desc { + public: + glm::vec4 _borderColor{ 1.0f }; + uint32 _maxAnisotropy = 16; + + uint8 _wrapModeU = WRAP_REPEAT; + uint8 _wrapModeV = WRAP_REPEAT; + uint8 _wrapModeW = WRAP_REPEAT; + + uint8 _filter = FILTER_MIN_MAG_POINT; + uint8 _comparisonFunc = ALWAYS; + + uint8 _mipOffset = 0; + uint8 _minMip = 0; + uint8 _maxMip = MAX_MIP_LEVEL; + + Desc() {} + Desc(const Filter filter) : _filter(filter) {} + }; + + Sampler() {} + Sampler(const Filter filter) : _desc(filter) {} + Sampler(const Desc& desc) : _desc(desc) {} + ~Sampler() {} + + const glm::vec4& getBorderColor() const { return _desc._borderColor; } + + uint32 getMaxAnisotropy() const { return _desc._maxAnisotropy; } + + WrapMode getWrapModeU() const { return WrapMode(_desc._wrapModeU); } + WrapMode getWrapModeV() const { return WrapMode(_desc._wrapModeV); } + WrapMode getWrapModeW() const { return WrapMode(_desc._wrapModeW); } + + Filter getFilter() const { return Filter(_desc._filter); } + ComparisonFunction getComparisonFunction() const { return ComparisonFunction(_desc._comparisonFunc); } + bool doComparison() const { return getComparisonFunction() != ALWAYS; } + + uint8 getMipOffset() const { return _desc._mipOffset; } + uint8 getMinMip() const { return _desc._minMip; } + uint8 getMaxMip() const { return _desc._maxMip; } + +protected: + Desc _desc; +}; + class Texture : public Resource { public: @@ -61,10 +140,10 @@ public: TEX_CUBE, }; - static Texture* create1D(const Element& texelFormat, uint16 width); - static Texture* create2D(const Element& texelFormat, uint16 width, uint16 height); - static Texture* create3D(const Element& texelFormat, uint16 width, uint16 height, uint16 depth); - static Texture* createCube(const Element& texelFormat, uint16 width); + static Texture* create1D(const Element& texelFormat, uint16 width, const Sampler& sampler = Sampler()); + static Texture* create2D(const Element& texelFormat, uint16 width, uint16 height, const Sampler& sampler = Sampler()); + static Texture* create3D(const Element& texelFormat, uint16 width, uint16 height, uint16 depth, const Sampler& sampler = Sampler()); + static Texture* createCube(const Element& texelFormat, uint16 width, const Sampler& sampler = Sampler()); static Texture* createFromStorage(Storage* storage); @@ -181,11 +260,21 @@ public: bool isDefined() const { return _defined; } + + // Own sampler + void setSampler(const Sampler& sampler); + const Sampler& getSampler() const { return _sampler; } + const Stamp getSamplerStamp() const { return _samplerStamp; } + protected: std::unique_ptr< Storage > _storage; Stamp _stamp; + Sampler _sampler; + Stamp _samplerStamp; + + uint32 _size; Element _texelFormat; @@ -202,7 +291,7 @@ protected: bool _autoGenerateMips; bool _defined; - static Texture* create(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices); + static Texture* create(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices, const Sampler& sampler); Texture(); Size resize(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices); diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index c5a09a4f0f..f1eb0e129f 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -253,7 +253,7 @@ void DeferredLightingEffect::render() { program->bind(); } program->setUniformValue(locations->shadowScale, - 1.0f / textureCache->getShadowFramebufferObject()->width()); + 1.0f / textureCache->getShadowFramebuffer()->getWidth()); } else { if (_ambientLightMode > -1) { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index bddbc2a0ff..cf6ceaa1f1 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -130,7 +130,7 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key, } // Z test depends if transparent or not - state->setDepthTest(true, !key.isTranslucent(), gpu::State::LESS_EQUAL); + state->setDepthTest(true, !key.isTranslucent(), gpu::LESS_EQUAL); // Blend on transparent state->setBlendFunction(key.isTranslucent(), diff --git a/libraries/render-utils/src/TextureCache.cpp b/libraries/render-utils/src/TextureCache.cpp index 28da6977f2..8e251d77ec 100644 --- a/libraries/render-utils/src/TextureCache.cpp +++ b/libraries/render-utils/src/TextureCache.cpp @@ -259,9 +259,11 @@ void TextureCache::createPrimaryFramebuffer() { auto colorFormat = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); auto width = _frameBufferSize.width(); auto height = _frameBufferSize.height(); - _primaryColorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height)); - _primaryNormalTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height)); - _primarySpecularTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height)); + + auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); + _primaryColorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); + _primaryNormalTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); + _primarySpecularTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); _primaryOpaqueFramebuffer->setRenderBuffer(0, _primaryColorTexture); _primaryOpaqueFramebuffer->setRenderBuffer(1, _primaryNormalTexture); @@ -270,7 +272,7 @@ void TextureCache::createPrimaryFramebuffer() { _primaryTransparentFramebuffer->setRenderBuffer(0, _primaryColorTexture); auto depthFormat = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH); - _primaryDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(depthFormat, width, height)); + _primaryDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(depthFormat, width, height, defaultSampler)); _primaryOpaqueFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); @@ -380,25 +382,6 @@ gpu::FramebufferPointer TextureCache::getShadowFramebuffer() { _shadowFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::createShadowmap(SHADOW_MAP_SIZE)); _shadowTexture = _shadowFramebuffer->getDepthStencilBuffer(); - /* - glGenTextures(1, &_shadowDepthTextureID); - glBindTexture(GL_TEXTURE_2D, _shadowDepthTextureID); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE, - 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - const float DISTANT_BORDER[] = { 1.0f, 1.0f, 1.0f, 1.0f }; - glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, DISTANT_BORDER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); - glBindTexture(GL_TEXTURE_2D, 0); - - _shadowFramebufferObject->bind(); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _shadowDepthTextureID, 0); - _shadowFramebufferObject->release(); - */ } return _shadowFramebuffer; } @@ -675,7 +658,7 @@ void NetworkTexture::setImage(const QImage& image, bool translucent, const QColo formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA)); formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA)); } - _gpuTexture = gpu::TexturePointer(gpu::Texture::create2D(formatGPU, image.width(), image.height())); + _gpuTexture = gpu::TexturePointer(gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); _gpuTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); _gpuTexture->autoGenerateMips(-1); } @@ -714,7 +697,7 @@ QSharedPointer DilatableNetworkTexture::getDilatedTexture(float dilatio formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA)); formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::BGRA : gpu::BGRA)); } - texture->_gpuTexture = gpu::TexturePointer(gpu::Texture::create2D(formatGPU, dilatedImage.width(), dilatedImage.height())); + texture->_gpuTexture = gpu::TexturePointer(gpu::Texture::create2D(formatGPU, dilatedImage.width(), dilatedImage.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); texture->_gpuTexture->assignStoredMip(0, formatMip, dilatedImage.byteCount(), dilatedImage.constBits()); texture->_gpuTexture->autoGenerateMips(-1); From 2c5201f116880c072e4f1b60f4ce6d09bc2a558b Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 14 Apr 2015 16:54:14 -0700 Subject: [PATCH 20/31] Fix animation not automatically starting at start-up --- interface/src/avatar/MyAvatar.cpp | 6 +----- libraries/render-utils/src/AnimationHandle.cpp | 5 +++-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 6b70577754..201dc3d48d 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -640,7 +640,6 @@ void MyAvatar::saveData() { settings.setValue("firstFrame", pointer->getFirstFrame()); settings.setValue("lastFrame", pointer->getLastFrame()); settings.setValue("maskedJoints", pointer->getMaskedJoints()); - settings.setValue("running", pointer->getLoop() && pointer->isRunning()); } settings.endArray(); @@ -710,13 +709,10 @@ void MyAvatar::loadData() { handle->setPriority(loadSetting(settings, "priority", 1.0f)); handle->setLoop(settings.value("loop", true).toBool()); handle->setHold(settings.value("hold", false).toBool()); - handle->setStartAutomatically(settings.value("startAutomatically", true).toBool()); handle->setFirstFrame(settings.value("firstFrame", 0.0f).toFloat()); handle->setLastFrame(settings.value("lastFrame", INT_MAX).toFloat()); handle->setMaskedJoints(settings.value("maskedJoints").toStringList()); - if (settings.value("loop", true).toBool() && settings.value("running", false).toBool()) { - handle->setRunning(true); - } + handle->setStartAutomatically(settings.value("startAutomatically", true).toBool()); } settings.endArray(); diff --git a/libraries/render-utils/src/AnimationHandle.cpp b/libraries/render-utils/src/AnimationHandle.cpp index 1cb3d4654f..037c84ae02 100644 --- a/libraries/render-utils/src/AnimationHandle.cpp +++ b/libraries/render-utils/src/AnimationHandle.cpp @@ -47,10 +47,11 @@ void AnimationHandle::setPriority(float priority) { } void AnimationHandle::setStartAutomatically(bool startAutomatically) { - _animationLoop.setStartAutomatically(startAutomatically); - if (getStartAutomatically() && !isRunning()) { + if (startAutomatically && !isRunning()) { + // Start before setting _animationLoop value so that code in setRunning() is executed start(); } + _animationLoop.setStartAutomatically(startAutomatically); } void AnimationHandle::setMaskedJoints(const QStringList& maskedJoints) { From 85e5216fc1b713113e29ed74dfeb6a4620dbdab5 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 14 Apr 2015 16:54:29 -0700 Subject: [PATCH 21/31] Condense logic --- libraries/render-utils/src/AnimationHandle.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/libraries/render-utils/src/AnimationHandle.cpp b/libraries/render-utils/src/AnimationHandle.cpp index 037c84ae02..55995b87d8 100644 --- a/libraries/render-utils/src/AnimationHandle.cpp +++ b/libraries/render-utils/src/AnimationHandle.cpp @@ -60,13 +60,10 @@ void AnimationHandle::setMaskedJoints(const QStringList& maskedJoints) { } void AnimationHandle::setRunning(bool running) { - if (isRunning() == running) { + if (running && isRunning()) { // if we're already running, this is the same as a restart - if (running) { - // move back to the beginning - setFrameIndex(getFirstFrame()); - return; - } + setFrameIndex(getFirstFrame()); + return; } _animationLoop.setRunning(running); if (isRunning()) { From fec52f6b102ba1dfd533b461100d10b3fea9fa4c Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 14 Apr 2015 18:27:24 -0700 Subject: [PATCH 22/31] Removing almost all the QFramebufferObject (instead in overlay layer) in favor of gpu::Framebuffer, eveyrthing seems to work properly --- interface/src/Application.cpp | 12 +- interface/src/devices/OculusManager.cpp | 14 +- interface/src/devices/TV3DManager.cpp | 2 - libraries/gpu/src/gpu/Format.h | 2 + libraries/gpu/src/gpu/Framebuffer.cpp | 13 +- libraries/gpu/src/gpu/Framebuffer.h | 3 +- libraries/gpu/src/gpu/Resource.cpp | 2 + .../src/AmbientOcclusionEffect.cpp | 29 ++- .../src/DeferredLightingEffect.cpp | 24 +- libraries/render-utils/src/GlowEffect.cpp | 56 +++-- libraries/render-utils/src/GlowEffect.h | 7 +- libraries/render-utils/src/TextureCache.cpp | 224 +++--------------- libraries/render-utils/src/TextureCache.h | 33 +-- 13 files changed, 133 insertions(+), 288 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3fe03476a3..3fcdfd8c4e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -798,7 +797,6 @@ void Application::paintGL() { DependencyManager::get()->prepare(); // Viewport is assigned to the size of the framebuffer - // QSize size = DependencyManager::get()->getPrimaryFramebufferObject()->size(); QSize size = DependencyManager::get()->getFrameBufferSize(); glViewport(0, 0, size.width(), size.height()); @@ -2637,11 +2635,8 @@ void Application::updateShadowMap() { activeRenderingThread = QThread::currentThread(); PerformanceTimer perfTimer("shadowMap"); -// QOpenGLFramebufferObject* fbo = DependencyManager::get()->getShadowFramebufferObject(); -// fbo->bind(); auto shadowFramebuffer = DependencyManager::get()->getShadowFramebuffer(); - GLuint shadowFBO = gpu::GLBackend::getFramebufferID(shadowFramebuffer); - glBindFramebuffer(GL_FRAMEBUFFER, shadowFBO); + glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(shadowFramebuffer)); glEnable(GL_DEPTH_TEST); glClear(GL_DEPTH_BUFFER_BIT); @@ -2838,7 +2833,8 @@ PickRay Application::computePickRay(float x, float y) { } QImage Application::renderAvatarBillboard() { - DependencyManager::get()->getPrimaryFramebufferObject()->bind(); + auto primaryFramebuffer = DependencyManager::get()->getPrimaryFramebuffer(); + glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFramebuffer)); // the "glow" here causes an alpha of one Glower glower; @@ -2851,7 +2847,7 @@ QImage Application::renderAvatarBillboard() { QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32); glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits()); - DependencyManager::get()->getPrimaryFramebufferObject()->release(); + glBindFramebuffer(GL_FRAMEBUFFER, 0); return image; } diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index d56ece12fb..0b4e3c1e73 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -17,7 +17,6 @@ #include #include -#include #include #include @@ -35,6 +34,8 @@ #include "InterfaceLogging.h" #include "Application.h" +#include + template void for_each_eye(Function function) { for (ovrEyeType eye = ovrEyeType::ovrEye_Left; @@ -521,7 +522,8 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) { DependencyManager::get()->prepare(); } else { - DependencyManager::get()->getPrimaryFramebufferObject()->bind(); + auto primaryFBO = DependencyManager::get()->getPrimaryFramebuffer(); + glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFBO)); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } @@ -612,15 +614,15 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p glPopMatrix(); - QOpenGLFramebufferObject * finalFbo = nullptr; + gpu::FramebufferPointer finalFbo; //Bind the output texture from the glow shader. If glow effect is disabled, we just grab the texture if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) { //Full texture viewport for glow effect glViewport(0, 0, _renderTargetSize.w, _renderTargetSize.h); finalFbo = DependencyManager::get()->render(true); } else { - finalFbo = DependencyManager::get()->getPrimaryFramebufferObject(); - finalFbo->release(); + finalFbo = DependencyManager::get()->getPrimaryFramebuffer(); + glBindFramebuffer(GL_FRAMEBUFFER, 0); } glMatrixMode(GL_PROJECTION); @@ -644,7 +646,7 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p //Left over from when OR was not connected. glClear(GL_COLOR_BUFFER_BIT); - glBindTexture(GL_TEXTURE_2D, finalFbo->texture()); + glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(finalFbo->getRenderBuffer(0))); //Renders the distorted mesh onto the screen renderDistortionMesh(eyeRenderPose); diff --git a/interface/src/devices/TV3DManager.cpp b/interface/src/devices/TV3DManager.cpp index f082c6de47..4311e0092f 100644 --- a/interface/src/devices/TV3DManager.cpp +++ b/interface/src/devices/TV3DManager.cpp @@ -11,8 +11,6 @@ #include "InterfaceConfig.h" -#include - #include #include diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index e982f27ec2..15c218a577 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -173,6 +173,8 @@ public: return getRaw() != right.getRaw(); } + static const Element COLOR_RGBA_32; + protected: uint8 _semantic; uint8 _dimension : 4; diff --git a/libraries/gpu/src/gpu/Framebuffer.cpp b/libraries/gpu/src/gpu/Framebuffer.cpp index 84e0fcca7a..bc263494a1 100755 --- a/libraries/gpu/src/gpu/Framebuffer.cpp +++ b/libraries/gpu/src/gpu/Framebuffer.cpp @@ -29,7 +29,18 @@ Framebuffer* Framebuffer::create() { return framebuffer; } -Framebuffer* Framebuffer::create( const Format& colorBufferFormat, const Format& depthStencilBufferFormat, uint16 width, uint16 height, uint16 numSamples) { + +Framebuffer* Framebuffer::create( const Format& colorBufferFormat, uint16 width, uint16 height) { + auto framebuffer = Framebuffer::create(); + + auto colorTexture = TexturePointer(Texture::create2D(colorBufferFormat, width, height, Sampler(Sampler::FILTER_MIN_MAG_POINT))); + + framebuffer->setRenderBuffer(0, colorTexture); + + return framebuffer; +} + +Framebuffer* Framebuffer::create( const Format& colorBufferFormat, const Format& depthStencilBufferFormat, uint16 width, uint16 height) { auto framebuffer = Framebuffer::create(); auto colorTexture = TexturePointer(Texture::create2D(colorBufferFormat, width, height, Sampler(Sampler::FILTER_MIN_MAG_POINT))); diff --git a/libraries/gpu/src/gpu/Framebuffer.h b/libraries/gpu/src/gpu/Framebuffer.h index 8028d1b478..a6fc127b17 100755 --- a/libraries/gpu/src/gpu/Framebuffer.h +++ b/libraries/gpu/src/gpu/Framebuffer.h @@ -115,7 +115,8 @@ public: static Framebuffer* create(const SwapchainPointer& swapchain); static Framebuffer* create(); - static Framebuffer* create(const Format& colorBufferFormat, const Format& depthStencilBufferFormat, uint16 width, uint16 height, uint16 samples ); + static Framebuffer* create(const Format& colorBufferFormat, uint16 width, uint16 height); + static Framebuffer* create(const Format& colorBufferFormat, const Format& depthStencilBufferFormat, uint16 width, uint16 height); static Framebuffer* createShadowmap(uint16 width); bool isSwapchain() const; diff --git a/libraries/gpu/src/gpu/Resource.cpp b/libraries/gpu/src/gpu/Resource.cpp index 708ca0f627..7d2757e15c 100644 --- a/libraries/gpu/src/gpu/Resource.cpp +++ b/libraries/gpu/src/gpu/Resource.cpp @@ -16,6 +16,8 @@ using namespace gpu; +const Element Element::COLOR_RGBA_32 = Element(VEC4, UINT8, RGBA); + Resource::Size Resource::Sysmem::allocateMemory(Byte** dataAllocated, Size size) { if ( !dataAllocated ) { qWarning() << "Buffer::Sysmem::allocateMemory() : Must have a valid dataAllocated pointer."; diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index 40a02a60a4..f58419ec6e 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -12,7 +12,7 @@ // include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL #include -#include +#include #include @@ -107,8 +107,8 @@ void AmbientOcclusionEffect::render() { glBindTexture(GL_TEXTURE_2D, _rotationTextureID); // render with the occlusion shader to the secondary/tertiary buffer - QOpenGLFramebufferObject* freeFBO = DependencyManager::get()->getFreeFramebufferObject(); - freeFBO->bind(); + auto freeFramebuffer = DependencyManager::get()->getFreeFramebuffer(); + glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(freeFramebuffer)); float left, right, bottom, top, nearVal, farVal; glm::vec4 nearClipPlane, farClipPlane; @@ -118,9 +118,10 @@ void AmbientOcclusionEffect::render() { glGetIntegerv(GL_VIEWPORT, viewport); const int VIEWPORT_X_INDEX = 0; const int VIEWPORT_WIDTH_INDEX = 2; - QOpenGLFramebufferObject* primaryFBO = DependencyManager::get()->getPrimaryFramebufferObject(); - float sMin = viewport[VIEWPORT_X_INDEX] / (float)primaryFBO->width(); - float sWidth = viewport[VIEWPORT_WIDTH_INDEX] / (float)primaryFBO->width(); + + auto framebufferSize = DependencyManager::get()->getFrameBufferSize(); + float sMin = viewport[VIEWPORT_X_INDEX] / (float)framebufferSize.width(); + float sWidth = viewport[VIEWPORT_WIDTH_INDEX] / (float)framebufferSize.width(); _occlusionProgram->bind(); _occlusionProgram->setUniformValue(_nearLocation, nearVal); @@ -128,7 +129,7 @@ void AmbientOcclusionEffect::render() { _occlusionProgram->setUniformValue(_leftBottomLocation, left, bottom); _occlusionProgram->setUniformValue(_rightTopLocation, right, top); _occlusionProgram->setUniformValue(_noiseScaleLocation, viewport[VIEWPORT_WIDTH_INDEX] / (float)ROTATION_WIDTH, - primaryFBO->height() / (float)ROTATION_HEIGHT); + framebufferSize.height() / (float)ROTATION_HEIGHT); _occlusionProgram->setUniformValue(_texCoordOffsetLocation, sMin, 0.0f); _occlusionProgram->setUniformValue(_texCoordScaleLocation, sWidth, 1.0f); @@ -136,22 +137,24 @@ void AmbientOcclusionEffect::render() { _occlusionProgram->release(); - freeFBO->release(); - + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0); // now render secondary to primary with 4x4 blur - DependencyManager::get()->getPrimaryFramebufferObject()->bind(); - + auto primaryFramebuffer = DependencyManager::get()->getPrimaryFramebuffer(); + glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFramebuffer)); + glEnable(GL_BLEND); glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE); - glBindTexture(GL_TEXTURE_2D, freeFBO->texture()); + auto freeFramebufferTexture = freeFramebuffer->getRenderBuffer(0); + glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(freeFramebufferTexture)); _blurProgram->bind(); - _blurProgram->setUniformValue(_blurScaleLocation, 1.0f / primaryFBO->width(), 1.0f / primaryFBO->height()); + _blurProgram->setUniformValue(_blurScaleLocation, 1.0f / framebufferSize.width(), 1.0f / framebufferSize.height()); renderFullscreenQuad(sMin, sMin + sWidth); diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index f1eb0e129f..440f75e32e 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -12,7 +12,6 @@ // include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL #include -#include #include #include @@ -183,12 +182,13 @@ void DeferredLightingEffect::render() { auto textureCache = DependencyManager::get(); - // QOpenGLFramebufferObject* primaryFBO = textureCache->getPrimaryFramebufferObject(); - // primaryFBO->release(); + glBindFramebuffer(GL_FRAMEBUFFER, 0 ); + QSize framebufferSize = textureCache->getFrameBufferSize(); - QOpenGLFramebufferObject* freeFBO = DependencyManager::get()->getFreeFramebufferObject(); - freeFBO->bind(); + auto freeFBO = DependencyManager::get()->getFreeFramebuffer(); + glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(freeFBO)); + glClear(GL_COLOR_BUFFER_BIT); // glEnable(GL_FRAMEBUFFER_SRGB); @@ -211,11 +211,7 @@ void DeferredLightingEffect::render() { const int VIEWPORT_Y_INDEX = 1; const int VIEWPORT_WIDTH_INDEX = 2; const int VIEWPORT_HEIGHT_INDEX = 3; - /* float sMin = viewport[VIEWPORT_X_INDEX] / (float)primaryFBO->width(); - float sWidth = viewport[VIEWPORT_WIDTH_INDEX] / (float)primaryFBO->width(); - float tMin = viewport[VIEWPORT_Y_INDEX] / (float)primaryFBO->height(); - float tHeight = viewport[VIEWPORT_HEIGHT_INDEX] / (float)primaryFBO->height(); - */ + float sMin = viewport[VIEWPORT_X_INDEX] / (float)framebufferSize.width(); float sWidth = viewport[VIEWPORT_WIDTH_INDEX] / (float)framebufferSize.width(); float tMin = viewport[VIEWPORT_Y_INDEX] / (float)framebufferSize.height(); @@ -436,7 +432,9 @@ void DeferredLightingEffect::render() { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0); - freeFBO->release(); + //freeFBO->release(); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + // glDisable(GL_FRAMEBUFFER_SRGB); glDisable(GL_CULL_FACE); @@ -445,12 +443,12 @@ void DeferredLightingEffect::render() { glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); glColorMask(true, true, true, false); - auto primaryFBO = gpu::GLBackend::getFramebufferID(textureCache->getPrimaryOpaqueFramebuffer()); + auto primaryFBO = gpu::GLBackend::getFramebufferID(textureCache->getPrimaryFramebuffer()); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, primaryFBO); //primaryFBO->bind(); - glBindTexture(GL_TEXTURE_2D, freeFBO->texture()); + glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(freeFBO->getRenderBuffer(0))); glEnable(GL_TEXTURE_2D); glPushMatrix(); diff --git a/libraries/render-utils/src/GlowEffect.cpp b/libraries/render-utils/src/GlowEffect.cpp index 2399cfa1a7..6addd84da6 100644 --- a/libraries/render-utils/src/GlowEffect.cpp +++ b/libraries/render-utils/src/GlowEffect.cpp @@ -46,10 +46,10 @@ GlowEffect::~GlowEffect() { } } -QOpenGLFramebufferObject* GlowEffect::getFreeFramebufferObject() const { +gpu::FramebufferPointer GlowEffect::getFreeFramebuffer() const { return (_isOddFrame ? - DependencyManager::get()->getSecondaryFramebufferObject(): - DependencyManager::get()->getTertiaryFramebufferObject()); + DependencyManager::get()->getSecondaryFramebuffer(): + DependencyManager::get()->getTertiaryFramebuffer()); } static ProgramObject* createProgram(const QString& name) { @@ -106,8 +106,7 @@ int GlowEffect::getDeviceHeight() const { void GlowEffect::prepare() { - //DependencyManager::get()->getPrimaryFramebufferObject()->bind(); - auto primaryFBO = DependencyManager::get()->getPrimaryOpaqueFramebuffer(); + auto primaryFBO = DependencyManager::get()->getPrimaryFramebuffer(); GLuint fbo = gpu::GLBackend::getFramebufferID(primaryFBO); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); @@ -129,25 +128,26 @@ void GlowEffect::end() { glBlendColor(0.0f, 0.0f, 0.0f, _intensity = _intensityStack.pop()); } -static void maybeBind(QOpenGLFramebufferObject* fbo) { +static void maybeBind(const gpu::FramebufferPointer& fbo) { if (fbo) { - fbo->bind(); + glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(fbo)); } } -static void maybeRelease(QOpenGLFramebufferObject* fbo) { +static void maybeRelease(const gpu::FramebufferPointer& fbo) { if (fbo) { - fbo->release(); + glBindFramebuffer(GL_FRAMEBUFFER, 0); } } -QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { +gpu::FramebufferPointer GlowEffect::render(bool toTexture) { PerformanceTimer perfTimer("glowEffect"); auto textureCache = DependencyManager::get(); - // QOpenGLFramebufferObject* primaryFBO = textureCache->getPrimaryFramebufferObject(); - // primaryFBO->release(); - auto primaryFBO = gpu::GLBackend::getFramebufferID(textureCache->getPrimaryOpaqueFramebuffer()); + + auto primaryFBO = gpu::GLBackend::getFramebufferID(textureCache->getPrimaryFramebuffer()); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindTexture(GL_TEXTURE_2D, textureCache->getPrimaryColorTextureID()); auto framebufferSize = textureCache->getFrameBufferSize(); @@ -162,15 +162,14 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); - QOpenGLFramebufferObject* destFBO = toTexture ? - textureCache->getSecondaryFramebufferObject() : NULL; + gpu::FramebufferPointer destFBO = toTexture ? + textureCache->getSecondaryFramebuffer() : nullptr; if (!_enabled || _isEmpty) { // copy the primary to the screen if (destFBO && QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) { glBindFramebuffer(GL_READ_FRAMEBUFFER, primaryFBO); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, destFBO->handle()); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(destFBO)); glBlitFramebuffer(0, 0, framebufferSize.width(), framebufferSize.height(), 0, 0, framebufferSize.width(), framebufferSize.height(), GL_COLOR_BUFFER_BIT, GL_NEAREST); - // QOpenGLFramebufferObject::blitFramebuffer(destFBO, primaryFBO); } else { maybeBind(destFBO); if (!destFBO) { @@ -185,36 +184,35 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { } } else { // diffuse into the secondary/tertiary (alternating between frames) - QOpenGLFramebufferObject* oldDiffusedFBO = - textureCache->getSecondaryFramebufferObject(); - QOpenGLFramebufferObject* newDiffusedFBO = - textureCache->getTertiaryFramebufferObject(); + auto oldDiffusedFBO = + textureCache->getSecondaryFramebuffer(); + auto newDiffusedFBO = + textureCache->getTertiaryFramebuffer(); if (_isOddFrame) { qSwap(oldDiffusedFBO, newDiffusedFBO); } - newDiffusedFBO->bind(); + glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(newDiffusedFBO)); if (_isFirstFrame) { glClear(GL_COLOR_BUFFER_BIT); } else { glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, oldDiffusedFBO->texture()); + glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(oldDiffusedFBO->getRenderBuffer(0))); _diffuseProgram->bind(); - //QSize size = primaryFBO->size(); - QSize size = framebufferSize; - _diffuseProgram->setUniformValue(_diffusionScaleLocation, 1.0f / size.width(), 1.0f / size.height()); + + _diffuseProgram->setUniformValue(_diffusionScaleLocation, 1.0f / framebufferSize.width(), 1.0f / framebufferSize.height()); renderFullscreenQuad(); _diffuseProgram->release(); } - newDiffusedFBO->release(); - + glBindFramebuffer(GL_FRAMEBUFFER, 0); + // add diffused texture to the primary - glBindTexture(GL_TEXTURE_2D, newDiffusedFBO->texture()); + glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(newDiffusedFBO->getRenderBuffer(0))); if (toTexture) { destFBO = oldDiffusedFBO; diff --git a/libraries/render-utils/src/GlowEffect.h b/libraries/render-utils/src/GlowEffect.h index 895cd4bbce..6b7bad7689 100644 --- a/libraries/render-utils/src/GlowEffect.h +++ b/libraries/render-utils/src/GlowEffect.h @@ -13,6 +13,7 @@ #define hifi_GlowEffect_h #include +#include #include #include @@ -20,8 +21,6 @@ #include -class QOpenGLFramebufferObject; - class ProgramObject; /// A generic full screen glow effect. @@ -33,7 +32,7 @@ public: /// Returns a pointer to the framebuffer object that the glow effect is *not* using for persistent state /// (either the secondary or the tertiary). - QOpenGLFramebufferObject* getFreeFramebufferObject() const; + gpu::FramebufferPointer getFreeFramebuffer() const; void init(QGLWidget* widget, bool enabled); @@ -53,7 +52,7 @@ public: /// Renders the glow effect. To be called after rendering the scene. /// \param toTexture whether to render to a texture, rather than to the frame buffer /// \return the framebuffer object to which we rendered, or NULL if to the frame buffer - QOpenGLFramebufferObject* render(bool toTexture = false); + gpu::FramebufferPointer render(bool toTexture = false); public slots: void toggleGlowEffect(bool enabled); diff --git a/libraries/render-utils/src/TextureCache.cpp b/libraries/render-utils/src/TextureCache.cpp index 8e251d77ec..63ca43725b 100644 --- a/libraries/render-utils/src/TextureCache.cpp +++ b/libraries/render-utils/src/TextureCache.cpp @@ -32,13 +32,6 @@ TextureCache::TextureCache() : _permutationNormalTexture(0), _whiteTexture(0), _blueTexture(0), - _primaryDepthTextureID(0), - _primaryNormalTextureID(0), - _primarySpecularTextureID(0), - _primaryFramebufferObject(NULL), - _secondaryFramebufferObject(NULL), - _tertiaryFramebufferObject(NULL), - _shadowFramebufferObject(NULL), _frameBufferSize(100, 100), _associatedWidget(NULL) { @@ -47,24 +40,6 @@ TextureCache::TextureCache() : } TextureCache::~TextureCache() { - - if (_primaryFramebufferObject) { - glDeleteTextures(1, &_primaryDepthTextureID); - glDeleteTextures(1, &_primaryNormalTextureID); - glDeleteTextures(1, &_primarySpecularTextureID); - } - - if (_primaryFramebufferObject) { - delete _primaryFramebufferObject; - } - - if (_secondaryFramebufferObject) { - delete _secondaryFramebufferObject; - } - - if (_tertiaryFramebufferObject) { - delete _tertiaryFramebufferObject; - } } void TextureCache::setFrameBufferSize(QSize frameBufferSize) { @@ -72,35 +47,15 @@ void TextureCache::setFrameBufferSize(QSize frameBufferSize) { if (_frameBufferSize != frameBufferSize) { _frameBufferSize = frameBufferSize; - if (_primaryOpaqueFramebuffer) { - _primaryOpaqueFramebuffer.reset(); - _primaryTransparentFramebuffer.reset(); - _primaryDepthTexture.reset(); - _primaryColorTexture.reset(); - _primaryNormalTexture.reset(); - _primarySpecularTexture.reset(); - } + _primaryFramebuffer.reset(); + _primaryDepthTexture.reset(); + _primaryColorTexture.reset(); + _primaryNormalTexture.reset(); + _primarySpecularTexture.reset(); - if (_primaryFramebufferObject) { - delete _primaryFramebufferObject; - _primaryFramebufferObject = NULL; - glDeleteTextures(1, &_primaryDepthTextureID); - _primaryDepthTextureID = 0; - glDeleteTextures(1, &_primaryNormalTextureID); - _primaryNormalTextureID = 0; - glDeleteTextures(1, &_primarySpecularTextureID); - _primarySpecularTextureID = 0; - } + _secondaryFramebuffer.reset(); - if (_secondaryFramebufferObject) { - delete _secondaryFramebufferObject; - _secondaryFramebufferObject = NULL; - } - - if (_tertiaryFramebufferObject) { - delete _tertiaryFramebufferObject; - _tertiaryFramebufferObject = NULL; - } + _tertiaryFramebuffer.reset(); } } @@ -215,46 +170,8 @@ NetworkTexturePointer TextureCache::getTexture(const QUrl& url, TextureType type return texture; } -QOpenGLFramebufferObject* TextureCache::getPrimaryFramebufferObject() { - - if (!_primaryFramebufferObject) { - _primaryFramebufferObject = createFramebufferObject(); - - glGenTextures(1, &_primaryDepthTextureID); - glBindTexture(GL_TEXTURE_2D, _primaryDepthTextureID); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, _frameBufferSize.width(), _frameBufferSize.height(), - 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - glGenTextures(1, &_primaryNormalTextureID); - glBindTexture(GL_TEXTURE_2D, _primaryNormalTextureID); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _frameBufferSize.width(), _frameBufferSize.height(), - 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glBindTexture(GL_TEXTURE_2D, 0); - - glGenTextures(1, &_primarySpecularTextureID); - glBindTexture(GL_TEXTURE_2D, _primarySpecularTextureID); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _frameBufferSize.width(), _frameBufferSize.height(), - 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glBindTexture(GL_TEXTURE_2D, 0); - - _primaryFramebufferObject->bind(); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _primaryDepthTextureID, 0); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, _primaryNormalTextureID, 0); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, _primarySpecularTextureID, 0); - _primaryFramebufferObject->release(); - } - return _primaryFramebufferObject; -} - void TextureCache::createPrimaryFramebuffer() { - _primaryOpaqueFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); - _primaryTransparentFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); + _primaryFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); auto colorFormat = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); auto width = _frameBufferSize.width(); @@ -265,32 +182,22 @@ void TextureCache::createPrimaryFramebuffer() { _primaryNormalTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); _primarySpecularTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); - _primaryOpaqueFramebuffer->setRenderBuffer(0, _primaryColorTexture); - _primaryOpaqueFramebuffer->setRenderBuffer(1, _primaryNormalTexture); - _primaryOpaqueFramebuffer->setRenderBuffer(2, _primarySpecularTexture); + _primaryFramebuffer->setRenderBuffer(0, _primaryColorTexture); + _primaryFramebuffer->setRenderBuffer(1, _primaryNormalTexture); + _primaryFramebuffer->setRenderBuffer(2, _primarySpecularTexture); - _primaryTransparentFramebuffer->setRenderBuffer(0, _primaryColorTexture); auto depthFormat = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH); _primaryDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(depthFormat, width, height, defaultSampler)); - _primaryOpaqueFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); - - _primaryTransparentFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); + _primaryFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); } -gpu::FramebufferPointer TextureCache::getPrimaryOpaqueFramebuffer() { - if (!_primaryOpaqueFramebuffer) { +gpu::FramebufferPointer TextureCache::getPrimaryFramebuffer() { + if (!_primaryFramebuffer) { createPrimaryFramebuffer(); } - return _primaryOpaqueFramebuffer; -} - -gpu::FramebufferPointer TextureCache::getPrimaryTransparentFramebuffer() { - if (!_primaryTransparentFramebuffer) { - createPrimaryFramebuffer(); - } - return _primaryTransparentFramebuffer; + return _primaryFramebuffer; } gpu::TexturePointer TextureCache::getPrimaryDepthTexture() { @@ -322,28 +229,19 @@ gpu::TexturePointer TextureCache::getPrimarySpecularTexture() { } GLuint TextureCache::getPrimaryDepthTextureID() { - // ensure that the primary framebuffer object is initialized before returning the depth texture id - //getPrimaryFramebufferObject(); - - _primaryDepthTextureID = gpu::GLBackend::getTextureID(_primaryDepthTexture); - return _primaryDepthTextureID; + return gpu::GLBackend::getTextureID(getPrimaryDepthTexture()); } GLuint TextureCache::getPrimaryColorTextureID() { - return gpu::GLBackend::getTextureID(_primaryColorTexture); + return gpu::GLBackend::getTextureID(getPrimaryColorTexture()); } GLuint TextureCache::getPrimaryNormalTextureID() { - // ensure that the primary framebuffer object is initialized before returning the normal texture id - //getPrimaryFramebufferObject(); - _primaryNormalTextureID = gpu::GLBackend::getTextureID(_primaryNormalTexture); - return _primaryNormalTextureID; + return gpu::GLBackend::getTextureID(getPrimaryNormalTexture()); } GLuint TextureCache::getPrimarySpecularTextureID() { - //getPrimaryFramebufferObject(); - _primarySpecularTextureID = gpu::GLBackend::getTextureID(_primarySpecularTexture); - return _primarySpecularTextureID; + return gpu::GLBackend::getTextureID(getPrimarySpecularTexture()); } void TextureCache::setPrimaryDrawBuffers(bool color, bool normal, bool specular) { @@ -361,18 +259,18 @@ void TextureCache::setPrimaryDrawBuffers(bool color, bool normal, bool specular) glDrawBuffers(bufferCount, buffers); } -QOpenGLFramebufferObject* TextureCache::getSecondaryFramebufferObject() { - if (!_secondaryFramebufferObject) { - _secondaryFramebufferObject = createFramebufferObject(); +gpu::FramebufferPointer TextureCache::getSecondaryFramebuffer() { + if (!_secondaryFramebuffer) { + _secondaryFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, _frameBufferSize.width(), _frameBufferSize.height())); } - return _secondaryFramebufferObject; + return _secondaryFramebuffer; } -QOpenGLFramebufferObject* TextureCache::getTertiaryFramebufferObject() { - if (!_tertiaryFramebufferObject) { - _tertiaryFramebufferObject = createFramebufferObject(); +gpu::FramebufferPointer TextureCache::getTertiaryFramebuffer() { + if (!_tertiaryFramebuffer) { + _tertiaryFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, _frameBufferSize.width(), _frameBufferSize.height())); } - return _tertiaryFramebufferObject; + return _tertiaryFramebuffer; } @@ -386,58 +284,25 @@ gpu::FramebufferPointer TextureCache::getShadowFramebuffer() { return _shadowFramebuffer; } -QOpenGLFramebufferObject* TextureCache::getShadowFramebufferObject() { - if (!_shadowFramebufferObject) { - const int SHADOW_MAP_SIZE = 2048; - _shadowFramebufferObject = new QOpenGLFramebufferObject(SHADOW_MAP_SIZE, SHADOW_MAP_SIZE, - QOpenGLFramebufferObject::NoAttachment, GL_TEXTURE_2D, GL_RGB); - - glGenTextures(1, &_shadowDepthTextureID); - glBindTexture(GL_TEXTURE_2D, _shadowDepthTextureID); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE, - 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - const float DISTANT_BORDER[] = { 1.0f, 1.0f, 1.0f, 1.0f }; - glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, DISTANT_BORDER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); - glBindTexture(GL_TEXTURE_2D, 0); - - _shadowFramebufferObject->bind(); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _shadowDepthTextureID, 0); - _shadowFramebufferObject->release(); - } - return _shadowFramebufferObject; -} - GLuint TextureCache::getShadowDepthTextureID() { // ensure that the shadow framebuffer object is initialized before returning the depth texture id - //getShadowFramebufferObject(); - _shadowDepthTextureID = gpu::GLBackend::getTextureID(_shadowTexture); - - return _shadowDepthTextureID; + getShadowFramebuffer(); + return gpu::GLBackend::getTextureID(_shadowTexture); } bool TextureCache::eventFilter(QObject* watched, QEvent* event) { if (event->type() == QEvent::Resize) { QSize size = static_cast(event)->size(); - if (_primaryFramebufferObject && _primaryFramebufferObject->size() != size) { - delete _primaryFramebufferObject; - _primaryFramebufferObject = NULL; - glDeleteTextures(1, &_primaryDepthTextureID); - glDeleteTextures(1, &_primaryNormalTextureID); - glDeleteTextures(1, &_primarySpecularTextureID); - } - if (_secondaryFramebufferObject && _secondaryFramebufferObject->size() != size) { - delete _secondaryFramebufferObject; - _secondaryFramebufferObject = NULL; - } - if (_tertiaryFramebufferObject && _tertiaryFramebufferObject->size() != size) { - delete _tertiaryFramebufferObject; - _tertiaryFramebufferObject = NULL; + if (_frameBufferSize != size) { + _primaryFramebuffer.reset(); + _primaryColorTexture.reset(); + _primaryDepthTexture.reset(); + _primaryNormalTexture.reset(); + _primarySpecularTexture.reset(); + + _secondaryFramebuffer.reset(); + + _tertiaryFramebuffer.reset(); } } return false; @@ -458,17 +323,6 @@ void TextureCache::associateWithWidget(QGLWidget* widget) { _associatedWidget->installEventFilter(this); } -QOpenGLFramebufferObject* TextureCache::createFramebufferObject() { - QOpenGLFramebufferObject* fbo = new QOpenGLFramebufferObject(_frameBufferSize); - - glBindTexture(GL_TEXTURE_2D, fbo->texture()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glBindTexture(GL_TEXTURE_2D, 0); - - return fbo; -} - Texture::Texture() { } diff --git a/libraries/render-utils/src/TextureCache.h b/libraries/render-utils/src/TextureCache.h index 0d0cfc40aa..42c1cecde3 100644 --- a/libraries/render-utils/src/TextureCache.h +++ b/libraries/render-utils/src/TextureCache.h @@ -23,8 +23,6 @@ #include #include -class QOpenGLFramebufferObject; - class NetworkTexture; typedef QSharedPointer NetworkTexturePointer; @@ -61,10 +59,7 @@ public: /// Returns a pointer to the primary framebuffer object. This render target includes a depth component, and is /// used for scene rendering. - QOpenGLFramebufferObject* getPrimaryFramebufferObject(); - - gpu::FramebufferPointer getPrimaryOpaqueFramebuffer(); - gpu::FramebufferPointer getPrimaryTransparentFramebuffer(); + gpu::FramebufferPointer getPrimaryFramebuffer(); gpu::TexturePointer getPrimaryDepthTexture(); gpu::TexturePointer getPrimaryColorTexture(); @@ -86,16 +81,13 @@ public: /// Returns a pointer to the secondary framebuffer object, used as an additional render target when performing full /// screen effects. - QOpenGLFramebufferObject* getSecondaryFramebufferObject(); + gpu::FramebufferPointer getSecondaryFramebuffer(); - /// Returns a pointer to the tertiary framebuffer object, used as an additional render target when performing full /// screen effects. - QOpenGLFramebufferObject* getTertiaryFramebufferObject(); - - /// Returns a pointer to the framebuffer object used to render shadow maps. - QOpenGLFramebufferObject* getShadowFramebufferObject(); + gpu::FramebufferPointer getTertiaryFramebuffer(); + /// Returns the framebuffer object used to render shadow maps; gpu::FramebufferPointer getShadowFramebuffer(); @@ -113,8 +105,6 @@ private: TextureCache(); virtual ~TextureCache(); friend class DilatableNetworkTexture; - - QOpenGLFramebufferObject* createFramebufferObject(); gpu::TexturePointer _permutationNormalTexture; gpu::TexturePointer _whiteTexture; @@ -127,20 +117,11 @@ private: gpu::TexturePointer _primaryColorTexture; gpu::TexturePointer _primaryNormalTexture; gpu::TexturePointer _primarySpecularTexture; - gpu::FramebufferPointer _primaryOpaqueFramebuffer; - gpu::FramebufferPointer _primaryTransparentFramebuffer; + gpu::FramebufferPointer _primaryFramebuffer; void createPrimaryFramebuffer(); - GLuint _primaryDepthTextureID; - GLuint _primaryNormalTextureID; - GLuint _primarySpecularTextureID; - QOpenGLFramebufferObject* _primaryFramebufferObject; - QOpenGLFramebufferObject* _secondaryFramebufferObject; - QOpenGLFramebufferObject* _tertiaryFramebufferObject; - - - QOpenGLFramebufferObject* _shadowFramebufferObject; - GLuint _shadowDepthTextureID; + gpu::FramebufferPointer _secondaryFramebuffer; + gpu::FramebufferPointer _tertiaryFramebuffer; gpu::FramebufferPointer _shadowFramebuffer; gpu::TexturePointer _shadowTexture; From 598abe672249b436c5cce028795457662d8d11bf Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 14 Apr 2015 18:48:06 -0700 Subject: [PATCH 23/31] Cleaning up Frambuffer.h --- libraries/gpu/src/gpu/Format.h | 1 + libraries/gpu/src/gpu/Framebuffer.h | 49 ++++++----------------------- 2 files changed, 10 insertions(+), 40 deletions(-) diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index 15c218a577..e43c190819 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -35,6 +35,7 @@ typedef glm::vec4 Vec4; typedef glm::vec3 Vec3; typedef glm::vec2 Vec2; typedef glm::ivec2 Vec2i; +typedef glm::uvec2 Vec2u; // Description of a scalar type enum Type { diff --git a/libraries/gpu/src/gpu/Framebuffer.h b/libraries/gpu/src/gpu/Framebuffer.h index a6fc127b17..ef77df7ceb 100755 --- a/libraries/gpu/src/gpu/Framebuffer.h +++ b/libraries/gpu/src/gpu/Framebuffer.h @@ -18,35 +18,6 @@ namespace gpu { typedef Element Format; -class Viewport { -public: - int32 width = 1; - int32 height = 1; - int32 top = 0; - int32 left = 0; - float zmin = 0.f; - float zmax = 1.f; - - Viewport() {} - Viewport(int32 w, int32 h, int32 t = 0, int32 l = 0, float zin = 0.f, float zax = 1.f): - width(w), - height(h), - top(t), - left(l), - zmin(zin), - zmax(zax) - {} - Viewport(const Vec2i& wh, const Vec2i& tl = Vec2i(0), const Vec2& zrange = Vec2(0.f, 1.f)): - width(wh.x), - height(wh.y), - top(tl.x), - left(tl.y), - zmin(zrange.x), - zmax(zrange.y) - {} - ~Viewport() {} -}; - class Swapchain { public: // Properties @@ -147,6 +118,7 @@ public: bool validateTargetCompatibility(const Texture& texture, uint32 subresource = 0) const; + Vec2u getSize() const { return Vec2u(getWidth(), getHeight()); } uint16 getWidth() const; uint16 getHeight() const; uint16 getNumSamples() const; @@ -157,24 +129,21 @@ public: void resize( uint16 width, uint16 height, uint16 samples = 1 ); static const uint32 MAX_NUM_RENDER_BUFFERS = 8; - static uint32 getMaxNumRenderBuffers() { return MAX_NUM_RENDER_BUFFERS; } - - // Get viewport covering the ful Canvas - Viewport getViewport() const { return Viewport(getWidth(), getHeight(), 0, 0); } + static uint32 getMaxNumRenderBuffers() { return MAX_NUM_RENDER_BUFFERS; } protected: - uint16 _width = 0; - uint16 _height = 0; - uint16 _numSamples = 0; + SwapchainPointer _swapchain; + + TextureViews _renderBuffers; + TextureView _depthStencilBuffer; uint32 _bufferMask = 0; uint32 _frameCount = 0; - SwapchainPointer _swapchain; - - TextureViews _renderBuffers; - TextureView _depthStencilBuffer; + uint16 _width = 0; + uint16 _height = 0; + uint16 _numSamples = 0; void updateSize(const TexturePointer& texture); From 1046356abb3f5da1f1f8092f489f67cef6fbafae Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 15 Apr 2015 09:00:20 -0700 Subject: [PATCH 24/31] FIx the include that was using the wrong \ in the path... --- interface/src/devices/OculusManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 0b4e3c1e73..2141127a3b 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -34,7 +34,7 @@ #include "InterfaceLogging.h" #include "Application.h" -#include +#include template void for_each_eye(Function function) { From 8b97d2585af25618ab5ba39ad7402ae42f3964a9 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 15 Apr 2015 10:16:04 -0700 Subject: [PATCH 25/31] fixing syntax issues --- libraries/gpu/src/gpu/Framebuffer.cpp | 7 +------ libraries/gpu/src/gpu/Framebuffer.h | 2 +- libraries/gpu/src/gpu/GLBackendOutput.cpp | 3 +-- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/libraries/gpu/src/gpu/Framebuffer.cpp b/libraries/gpu/src/gpu/Framebuffer.cpp index bc263494a1..96bd3d3002 100755 --- a/libraries/gpu/src/gpu/Framebuffer.cpp +++ b/libraries/gpu/src/gpu/Framebuffer.cpp @@ -15,12 +15,7 @@ using namespace gpu; -Framebuffer::Framebuffer() -{ -} - -Framebuffer::~Framebuffer() -{ +Framebuffer::~Framebuffer() { } Framebuffer* Framebuffer::create() { diff --git a/libraries/gpu/src/gpu/Framebuffer.h b/libraries/gpu/src/gpu/Framebuffer.h index ef77df7ceb..69e507f824 100755 --- a/libraries/gpu/src/gpu/Framebuffer.h +++ b/libraries/gpu/src/gpu/Framebuffer.h @@ -149,7 +149,7 @@ protected: // Non exposed Framebuffer(const Framebuffer& framebuffer) {} - Framebuffer(); + Framebuffer() {} // This shouldn't be used by anything else than the Backend class with the proper casting. mutable GPUObject* _gpuObject = NULL; diff --git a/libraries/gpu/src/gpu/GLBackendOutput.cpp b/libraries/gpu/src/gpu/GLBackendOutput.cpp index 9b3fb5fe34..bd8a2ab457 100755 --- a/libraries/gpu/src/gpu/GLBackendOutput.cpp +++ b/libraries/gpu/src/gpu/GLBackendOutput.cpp @@ -12,8 +12,7 @@ #include "GLBackendShared.h" -GLBackend::GLFramebuffer::GLFramebuffer() -{} +GLBackend::GLFramebuffer::GLFramebuffer() {} GLBackend::GLFramebuffer::~GLFramebuffer() { if (_fbo != 0) { From 9213561977ba1c9c2d4744c8b461b0b129a92906 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 15 Apr 2015 11:34:59 -0700 Subject: [PATCH 26/31] add vim plugin files to gitignore --- .gitignore | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 3b44b99e68..f2f259a0c2 100644 --- a/.gitignore +++ b/.gitignore @@ -46,4 +46,8 @@ libraries/audio-client/external/*/* gvr-interface/assets/oculussig* gvr-interface/libs/* -TAGS \ No newline at end of file +# ignore files for various dev environments +TAGS +.ycm_extra_conf.* +*.taghl +*.swp From faf7850d7c0af3e36754f22fa98822460bf8f402 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 15 Apr 2015 12:38:24 -0700 Subject: [PATCH 27/31] remove plugin specific ignored files --- .gitignore | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitignore b/.gitignore index f2f259a0c2..44561daabc 100644 --- a/.gitignore +++ b/.gitignore @@ -48,6 +48,4 @@ gvr-interface/libs/* # ignore files for various dev environments TAGS -.ycm_extra_conf.* -*.taghl *.swp From 1a1fe11111658d59a886593ac37be57c271c3d4e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 15 Apr 2015 17:00:20 -0700 Subject: [PATCH 28/31] switch HMD tools hot-key --- interface/src/Menu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index da0c669f35..d50cb48118 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -256,7 +256,7 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FullscreenMirror, Qt::Key_H, false, qApp, SLOT(cameraMenuChanged())); - addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::HMDTools, Qt::META | Qt::Key_H, + addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::HMDTools, Qt::CTRL | Qt::Key_H, false, dialogsManager.data(), SLOT(hmdTools(bool))); From ffb5ea50b1240882d6b1aa272c0b313117d6692d Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 15 Apr 2015 17:00:50 -0700 Subject: [PATCH 29/31] expose avatar settings to JS --- interface/src/avatar/MyAvatar.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index f12941d748..886d8ad590 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -117,21 +117,21 @@ public: virtual void clearJointData(int index); virtual void clearJointsData(); - void useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelName = QString()); - void useHeadURL(const QUrl& headURL, const QString& modelName = QString()); - void useBodyURL(const QUrl& bodyURL, const QString& modelName = QString()); - void useHeadAndBodyURLs(const QUrl& headURL, const QUrl& bodyURL, const QString& headName = QString(), const QString& bodyName = QString()); + Q_INVOKABLE void useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelName = QString()); + Q_INVOKABLE void useHeadURL(const QUrl& headURL, const QString& modelName = QString()); + Q_INVOKABLE void useBodyURL(const QUrl& bodyURL, const QString& modelName = QString()); + Q_INVOKABLE void useHeadAndBodyURLs(const QUrl& headURL, const QUrl& bodyURL, const QString& headName = QString(), const QString& bodyName = QString()); - bool getUseFullAvatar() const { return _useFullAvatar; } - const QUrl& getFullAvatarURLFromPreferences() const { return _fullAvatarURLFromPreferences; } - const QUrl& getHeadURLFromPreferences() const { return _headURLFromPreferences; } - const QUrl& getBodyURLFromPreferences() const { return _skeletonURLFromPreferences; } + Q_INVOKABLE bool getUseFullAvatar() const { return _useFullAvatar; } + Q_INVOKABLE const QUrl& getFullAvatarURLFromPreferences() const { return _fullAvatarURLFromPreferences; } + Q_INVOKABLE const QUrl& getHeadURLFromPreferences() const { return _headURLFromPreferences; } + Q_INVOKABLE const QUrl& getBodyURLFromPreferences() const { return _skeletonURLFromPreferences; } - const QString& getHeadModelName() const { return _headModelName; } - const QString& getBodyModelName() const { return _bodyModelName; } - const QString& getFullAvartarModelName() const { return _fullAvatarModelName; } + Q_INVOKABLE const QString& getHeadModelName() const { return _headModelName; } + Q_INVOKABLE const QString& getBodyModelName() const { return _bodyModelName; } + Q_INVOKABLE const QString& getFullAvartarModelName() const { return _fullAvatarModelName; } - QString getModelDescription() const; + Q_INVOKABLE QString getModelDescription() const; virtual void setAttachmentData(const QVector& attachmentData); From 21d669f2f13e0395f47e72a32d6e7dbd0771a308 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 16 Apr 2015 12:13:41 -0700 Subject: [PATCH 30/31] use computed shape type --- libraries/entities-renderer/src/RenderableModelEntityItem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index c67e1f04e5..86b0be4dd8 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -308,7 +308,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) { ShapeType type = getShapeType(); if (type != SHAPE_TYPE_COMPOUND) { ModelEntityItem::computeShapeInfo(info); - info.setParams(_shapeType, 0.5f * getDimensions()); + info.setParams(type, 0.5f * getDimensions()); } else { const QSharedPointer collisionNetworkGeometry = _model->getCollisionGeometry(); @@ -410,7 +410,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) { } glm::vec3 collisionModelDimensions = box.getDimensions(); - info.setParams(_shapeType, collisionModelDimensions, _collisionModelURL); + info.setParams(type, collisionModelDimensions, _collisionModelURL); info.setConvexHulls(_points); } } From 94c6053d5259b07917e99a04c55a79ed2cef823a Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 16 Apr 2015 12:15:03 -0700 Subject: [PATCH 31/31] fix formatting --- libraries/entities/src/ModelEntityItem.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index e98f784765..f95eeea8e4 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -296,8 +296,7 @@ void ModelEntityItem::updateShapeType(ShapeType type) { ShapeType ModelEntityItem::getShapeType() const { if (_shapeType == SHAPE_TYPE_COMPOUND) { return hasCollisionModel() ? SHAPE_TYPE_COMPOUND : SHAPE_TYPE_NONE; - } - else { + } else { return _shapeType; } }