mirror of
https://github.com/overte-org/overte.git
synced 2025-04-07 15:34:05 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into head-controller
This commit is contained in:
commit
b1c7c251ac
100 changed files with 1124 additions and 1039 deletions
38
BUILD_WIN.md
38
BUILD_WIN.md
|
@ -1,5 +1,7 @@
|
|||
This is a stand-alone guide for creating your first High Fidelity build for Windows 64-bit.
|
||||
|
||||
## Building High Fidelity
|
||||
|
||||
### Step 1. Installing Visual Studio 2013
|
||||
|
||||
If you don't already have the Community or Professional edition of Visual Studio 2013, download and install [Visual Studio Community 2013](https://www.visualstudio.com/en-us/news/releasenotes/vs2013-community-vs). You do not need to install any of the optional components when going through the installer.
|
||||
|
@ -18,8 +20,8 @@ Keep the default components checked when going through the installer.
|
|||
|
||||
### Step 4. Setting Qt Environment Variable
|
||||
|
||||
Go to "Control Panel > System > Advanced System Settings > Environment Variables > New..." (or search “Environment Variables” in Start Search).
|
||||
* Set "Variable name": QT_CMAKE_PREFIX_PATH
|
||||
Go to `Control Panel > System > Advanced System Settings > Environment Variables > New...` (or search “Environment Variables” in Start Search).
|
||||
* Set "Variable name": `QT_CMAKE_PREFIX_PATH`
|
||||
* Set "Variable value": `%QT_DIR%\5.6\msvc2013_64\lib\cmake`
|
||||
|
||||
### Step 5. Installing OpenSSL
|
||||
|
@ -29,34 +31,36 @@ Download and install the [Win64 OpenSSL v1.0.2L Installer](https://slproweb.com/
|
|||
### Step 6. Running CMake to Generate Build Files
|
||||
|
||||
Run Command Prompt from Start and run the following commands:
|
||||
cd "%HIFI_DIR%"
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G "Visual Studio 12 Win64"
|
||||
````
|
||||
cd "%HIFI_DIR%"
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G "Visual Studio 12 Win64"
|
||||
````
|
||||
|
||||
Where %HIFI_DIR% is the directory for the highfidelity repository.
|
||||
Where `%HIFI_DIR%` is the directory for the highfidelity repository.
|
||||
|
||||
### Step 7. Making a Build
|
||||
|
||||
Open '%HIFI_DIR%\build\hifi.sln' using Visual Studio.
|
||||
Open `%HIFI_DIR%\build\hifi.sln` using Visual Studio.
|
||||
|
||||
Change the Solution Configuration (next to the green play button) from "Debug" to "Release" for best performance.
|
||||
|
||||
Run Build > Build Solution.
|
||||
Run `Build > Build Solution`.
|
||||
|
||||
### Step 8. Testing Interface
|
||||
|
||||
Create another environment variable (see Step #4)
|
||||
* Set "Variable name": _NO_DEBUG_HEAP
|
||||
* Set "Variable value": 1
|
||||
* Set "Variable name": `_NO_DEBUG_HEAP`
|
||||
* Set "Variable value": `1`
|
||||
|
||||
In Visual Studio, right+click "interface" under the Apps folder in Solution Explorer and select "Set as Startup Project". Run Debug > Start Debugging.
|
||||
In Visual Studio, right+click "interface" under the Apps folder in Solution Explorer and select "Set as Startup Project". Run `Debug > Start Debugging`.
|
||||
|
||||
Now, you should have a full build of High Fidelity and be able to run the Interface using Visual Studio. Please check our [Docs](https://wiki.highfidelity.com/wiki/Main_Page) for more information regarding the programming workflow.
|
||||
|
||||
Note: You can also run Interface by launching it from command line or File Explorer from %HIFI_DIR%\build\interface\Release\interface.exe
|
||||
Note: You can also run Interface by launching it from command line or File Explorer from `%HIFI_DIR%\build\interface\Release\interface.exe`
|
||||
|
||||
### Troubleshooting
|
||||
## Troubleshooting
|
||||
|
||||
For any problems after Step #6, first try this:
|
||||
* Delete your locally cloned copy of the highfidelity repository
|
||||
|
@ -66,16 +70,16 @@ For any problems after Step #6, first try this:
|
|||
|
||||
#### CMake gives you the same error message repeatedly after the build fails
|
||||
|
||||
Remove `CMakeCache.txt` found in the '%HIFI_DIR%\build' directory
|
||||
Remove `CMakeCache.txt` found in the `%HIFI_DIR%\build` directory.
|
||||
|
||||
#### nmake cannot be found
|
||||
|
||||
Make sure nmake.exe is located at the following path:
|
||||
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin
|
||||
|
||||
If not, add the directory where nmake is located to the PATH environment variable.
|
||||
|
||||
#### Qt is throwing an error
|
||||
|
||||
Make sure you have the correct version (5.6.2) installed and 'QT_CMAKE_PREFIX_PATH' environment variable is set correctly.
|
||||
|
||||
Make sure you have the correct version (5.6.2) installed and `QT_CMAKE_PREFIX_PATH` environment variable is set correctly.
|
||||
|
|
8
cmake/externals/nvtt/CMakeLists.txt
vendored
8
cmake/externals/nvtt/CMakeLists.txt
vendored
|
@ -8,8 +8,8 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
|||
if (WIN32)
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL http://s3.amazonaws.com/hifi-public/dependencies/nvtt-win-2.1.0.zip
|
||||
URL_MD5 3ea6eeadbcc69071acf9c49ba565760e
|
||||
URL http://s3.amazonaws.com/hifi-public/dependencies/nvtt-win-2.1.0.hifi.zip
|
||||
URL_MD5 10da01cf601f88f6dc12a6bc13c89136
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
|
@ -29,8 +29,8 @@ else ()
|
|||
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL http://hifi-public.s3.amazonaws.com/dependencies/nvidia-texture-tools-2.1.0.zip
|
||||
URL_MD5 81b8fa6a9ee3f986088eb6e2215d6a57
|
||||
URL http://hifi-public.s3.amazonaws.com/dependencies/nvidia-texture-tools-2.1.0.hifi.zip
|
||||
URL_MD5 5794b950f8b265a9a41b2839b3bf7ebb
|
||||
CONFIGURE_COMMAND CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DNVTT_SHARED=1 -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
|
||||
LOG_DOWNLOAD 1
|
||||
LOG_CONFIGURE 1
|
||||
|
|
|
@ -2,7 +2,6 @@ import QtQuick 2.5
|
|||
import QtQuick.Controls 1.2
|
||||
import QtWebChannel 1.0
|
||||
import QtWebEngine 1.2
|
||||
import FileTypeProfile 1.0
|
||||
|
||||
import "controls-uit"
|
||||
import "styles" as HifiStyles
|
||||
|
@ -209,6 +208,7 @@ ScrollingWindow {
|
|||
WebView {
|
||||
id: webview
|
||||
url: "https://highfidelity.com/"
|
||||
profile: FileTypeProfile;
|
||||
|
||||
property alias eventBridgeWrapper: eventBridgeWrapper
|
||||
|
||||
|
@ -218,10 +218,6 @@ ScrollingWindow {
|
|||
property var eventBridge;
|
||||
}
|
||||
|
||||
profile: FileTypeProfile {
|
||||
id: webviewProfile
|
||||
storageName: "qmlWebEngine"
|
||||
}
|
||||
|
||||
webChannel.registeredObjects: [eventBridgeWrapper]
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ import "controls-uit" as HifiControls
|
|||
import "styles" as HifiStyles
|
||||
import "styles-uit"
|
||||
import "windows"
|
||||
import HFTabletWebEngineProfile 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
@ -47,10 +46,7 @@ Item {
|
|||
width: parent.width
|
||||
height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height
|
||||
|
||||
profile: HFTabletWebEngineProfile {
|
||||
id: webviewTabletProfile
|
||||
storageName: "qmlTabletWebEngine"
|
||||
}
|
||||
profile: HFTabletWebEngineProfile;
|
||||
|
||||
property string userScriptUrl: ""
|
||||
|
||||
|
|
|
@ -10,13 +10,10 @@
|
|||
|
||||
import QtQuick 2.5
|
||||
import QtWebEngine 1.2
|
||||
import HFWebEngineProfile 1.0
|
||||
|
||||
WebEngineView {
|
||||
id: root
|
||||
|
||||
// profile: desktop.browserProfile
|
||||
|
||||
Component.onCompleted: {
|
||||
console.log("Connecting JS messaging to Hifi Logging")
|
||||
// Ensure the JS from the web-engine makes it to our logging
|
||||
|
|
|
@ -2,7 +2,6 @@ import QtQuick 2.5
|
|||
import QtWebEngine 1.1
|
||||
import QtWebChannel 1.0
|
||||
import "../controls-uit" as HiFiControls
|
||||
import HFTabletWebEngineProfile 1.0
|
||||
|
||||
Item {
|
||||
property alias url: root.url
|
||||
|
@ -39,10 +38,7 @@ Item {
|
|||
width: parent.width
|
||||
height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height
|
||||
|
||||
profile: HFTabletWebEngineProfile {
|
||||
id: webviewProfile
|
||||
storageName: "qmlTabletWebEngine"
|
||||
}
|
||||
profile: HFTabletWebEngineProfile;
|
||||
|
||||
property string userScriptUrl: ""
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ import QtQuick 2.5
|
|||
import QtQuick.Controls 1.4
|
||||
import QtWebEngine 1.2
|
||||
import QtWebChannel 1.0
|
||||
import HFTabletWebEngineProfile 1.0
|
||||
import "../controls-uit" as HiFiControls
|
||||
import "../styles" as HifiStyles
|
||||
import "../styles-uit"
|
||||
|
@ -150,10 +149,7 @@ Item {
|
|||
width: parent.width
|
||||
height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height - web.headerHeight : parent.height - web.headerHeight
|
||||
anchors.top: buttons.bottom
|
||||
profile: HFTabletWebEngineProfile {
|
||||
id: webviewTabletProfile
|
||||
storageName: "qmlTabletWebEngine"
|
||||
}
|
||||
profile: HFTabletWebEngineProfile;
|
||||
|
||||
property string userScriptUrl: ""
|
||||
|
||||
|
|
|
@ -10,13 +10,9 @@
|
|||
|
||||
import QtQuick 2.5
|
||||
import "."
|
||||
import FileTypeProfile 1.0
|
||||
|
||||
WebView {
|
||||
viewProfile: FileTypeProfile {
|
||||
id: webviewProfile
|
||||
storageName: "qmlWebEngine"
|
||||
}
|
||||
viewProfile: FileTypeProfile;
|
||||
|
||||
urlTag: "noDownload=true";
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ import QtQuick 2.5
|
|||
import QtWebEngine 1.1
|
||||
import QtWebChannel 1.0
|
||||
import "../controls-uit" as HiFiControls
|
||||
import HFWebEngineProfile 1.0
|
||||
|
||||
Item {
|
||||
property alias url: root.url
|
||||
|
@ -39,10 +38,7 @@ Item {
|
|||
width: parent.width
|
||||
height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height
|
||||
|
||||
profile: HFWebEngineProfile {
|
||||
id: webviewProfile
|
||||
storageName: "qmlWebEngine"
|
||||
}
|
||||
profile: HFWebEngineProfile;
|
||||
|
||||
property string userScriptUrl: ""
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ import QtQuick 2.5
|
|||
import QtQuick.Controls 1.4
|
||||
import QtWebEngine 1.1;
|
||||
import Qt.labs.settings 1.0
|
||||
import HFWebEngineProfile 1.0
|
||||
|
||||
import "../desktop" as OriginalDesktop
|
||||
import ".."
|
||||
|
@ -27,11 +26,6 @@ OriginalDesktop.Desktop {
|
|||
property alias toolWindow: toolWindow
|
||||
ToolWindow { id: toolWindow }
|
||||
|
||||
property var browserProfile: HFWebEngineProfile {
|
||||
id: webviewProfile
|
||||
storageName: "qmlWebEngine"
|
||||
}
|
||||
|
||||
Action {
|
||||
text: "Open Browser"
|
||||
shortcut: "Ctrl+B"
|
||||
|
|
|
@ -5,7 +5,6 @@ import QtWebChannel 1.0
|
|||
import QtQuick.Controls.Styles 1.4
|
||||
import "../../controls"
|
||||
import "../toolbars"
|
||||
import HFWebEngineProfile 1.0
|
||||
import QtGraphicalEffects 1.0
|
||||
import "../../controls-uit" as HifiControls
|
||||
import "../../styles-uit"
|
||||
|
|
|
@ -4,7 +4,6 @@ import QtQuick.Controls 1.4
|
|||
import QtQml 2.2
|
||||
import QtWebChannel 1.0
|
||||
import QtWebEngine 1.1
|
||||
import HFWebEngineProfile 1.0
|
||||
|
||||
|
||||
import "."
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import QtQuick 2.0
|
||||
import Hifi 1.0
|
||||
import QtQuick.Controls 1.4
|
||||
import HFTabletWebEngineProfile 1.0
|
||||
import "../../dialogs"
|
||||
import "../../controls"
|
||||
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
#include <ErrorDialog.h>
|
||||
#include <FileScriptingInterface.h>
|
||||
#include <Finally.h>
|
||||
#include <FingerprintUtils.h>
|
||||
#include <FramebufferCache.h>
|
||||
#include <gpu/Batch.h>
|
||||
#include <gpu/Context.h>
|
||||
|
@ -114,6 +115,7 @@
|
|||
#include <RenderDeferredTask.h>
|
||||
#include <RenderForwardTask.h>
|
||||
#include <ResourceCache.h>
|
||||
#include <ResourceRequest.h>
|
||||
#include <SandboxUtils.h>
|
||||
#include <SceneScriptingInterface.h>
|
||||
#include <ScriptEngines.h>
|
||||
|
@ -148,9 +150,6 @@
|
|||
#include "LODManager.h"
|
||||
#include "ModelPackager.h"
|
||||
#include "networking/CloseEventSender.h"
|
||||
#include "networking/HFWebEngineProfile.h"
|
||||
#include "networking/HFTabletWebEngineProfile.h"
|
||||
#include "networking/FileTypeProfile.h"
|
||||
#include "scripting/TestScriptingInterface.h"
|
||||
#include "scripting/AccountScriptingInterface.h"
|
||||
#include "scripting/AssetMappingsScriptingInterface.h"
|
||||
|
@ -248,6 +247,8 @@ static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStanda
|
|||
Setting::Handle<int> maxOctreePacketsPerSecond("maxOctreePPS", DEFAULT_MAX_OCTREE_PPS);
|
||||
|
||||
static const QString MARKETPLACE_CDN_HOSTNAME = "mpassets.highfidelity.com";
|
||||
static const int INTERVAL_TO_CHECK_HMD_WORN_STATUS = 500; // milliseconds
|
||||
static const QString DESKTOP_DISPLAY_PLUGIN_NAME = "Desktop";
|
||||
|
||||
const QHash<QString, Application::AcceptURLMethod> Application::_acceptedExtensions {
|
||||
{ SVO_EXTENSION, &Application::importSVOFromURL },
|
||||
|
@ -951,6 +952,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
properties["processor_l3_cache_count"] = procInfo.numProcessorCachesL3;
|
||||
}
|
||||
|
||||
// add firstRun flag from settings to launch event
|
||||
Setting::Handle<bool> firstRun { Settings::firstRun, true };
|
||||
properties["first_run"] = firstRun.get();
|
||||
|
||||
// add the user's machine ID to the launch event
|
||||
properties["machine_fingerprint"] = uuidStringWithoutCurlyBraces(FingerprintUtils::getMachineFingerprint());
|
||||
|
||||
UserActivityLogger::getInstance().logAction("launch", properties);
|
||||
|
||||
// Tell our entity edit sender about our known jurisdictions
|
||||
|
@ -1310,6 +1318,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
properties["kbps_in"] = bandwidthRecorder->getCachedTotalAverageInputKilobitsPerSecond();
|
||||
properties["kbps_out"] = bandwidthRecorder->getCachedTotalAverageOutputKilobitsPerSecond();
|
||||
|
||||
properties["atp_in_kbps"] = bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AssetServer);
|
||||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
SharedNodePointer entityServerNode = nodeList->soloNodeOfType(NodeType::EntityServer);
|
||||
SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer);
|
||||
|
@ -1323,8 +1333,61 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
properties["messages_ping"] = messagesMixerNode ? messagesMixerNode->getPingMs() : -1;
|
||||
|
||||
auto loadingRequests = ResourceCache::getLoadingRequests();
|
||||
|
||||
QJsonArray loadingRequestsStats;
|
||||
for (const auto& request : loadingRequests) {
|
||||
QJsonObject requestStats;
|
||||
requestStats["filename"] = request->getURL().fileName();
|
||||
requestStats["received"] = request->getBytesReceived();
|
||||
requestStats["total"] = request->getBytesTotal();
|
||||
requestStats["attempts"] = (int)request->getDownloadAttempts();
|
||||
loadingRequestsStats.append(requestStats);
|
||||
}
|
||||
|
||||
properties["active_downloads"] = loadingRequests.size();
|
||||
properties["pending_downloads"] = ResourceCache::getPendingRequestCount();
|
||||
properties["active_downloads_details"] = loadingRequestsStats;
|
||||
|
||||
auto statTracker = DependencyManager::get<StatTracker>();
|
||||
|
||||
properties["processing_resources"] = statTracker->getStat("Processing").toInt();
|
||||
properties["pending_processing_resources"] = statTracker->getStat("PendingProcessing").toInt();
|
||||
|
||||
QJsonObject startedRequests;
|
||||
startedRequests["atp"] = statTracker->getStat(STAT_ATP_REQUEST_STARTED).toInt();
|
||||
startedRequests["http"] = statTracker->getStat(STAT_HTTP_REQUEST_STARTED).toInt();
|
||||
startedRequests["file"] = statTracker->getStat(STAT_FILE_REQUEST_STARTED).toInt();
|
||||
startedRequests["total"] = startedRequests["atp"].toInt() + startedRequests["http"].toInt()
|
||||
+ startedRequests["file"].toInt();
|
||||
properties["started_requests"] = startedRequests;
|
||||
|
||||
QJsonObject successfulRequests;
|
||||
successfulRequests["atp"] = statTracker->getStat(STAT_ATP_REQUEST_SUCCESS).toInt();
|
||||
successfulRequests["http"] = statTracker->getStat(STAT_HTTP_REQUEST_SUCCESS).toInt();
|
||||
successfulRequests["file"] = statTracker->getStat(STAT_FILE_REQUEST_SUCCESS).toInt();
|
||||
successfulRequests["total"] = successfulRequests["atp"].toInt() + successfulRequests["http"].toInt()
|
||||
+ successfulRequests["file"].toInt();
|
||||
properties["successful_requests"] = successfulRequests;
|
||||
|
||||
QJsonObject failedRequests;
|
||||
failedRequests["atp"] = statTracker->getStat(STAT_ATP_REQUEST_FAILED).toInt();
|
||||
failedRequests["http"] = statTracker->getStat(STAT_HTTP_REQUEST_FAILED).toInt();
|
||||
failedRequests["file"] = statTracker->getStat(STAT_FILE_REQUEST_FAILED).toInt();
|
||||
failedRequests["total"] = failedRequests["atp"].toInt() + failedRequests["http"].toInt()
|
||||
+ failedRequests["file"].toInt();
|
||||
properties["failed_requests"] = failedRequests;
|
||||
|
||||
QJsonObject cacheRequests;
|
||||
cacheRequests["atp"] = statTracker->getStat(STAT_ATP_REQUEST_CACHE).toInt();
|
||||
cacheRequests["http"] = statTracker->getStat(STAT_HTTP_REQUEST_CACHE).toInt();
|
||||
cacheRequests["total"] = cacheRequests["atp"].toInt() + cacheRequests["http"].toInt();
|
||||
properties["cache_requests"] = cacheRequests;
|
||||
|
||||
QJsonObject atpMappingRequests;
|
||||
atpMappingRequests["started"] = statTracker->getStat(STAT_ATP_MAPPING_REQUEST_STARTED).toInt();
|
||||
atpMappingRequests["failed"] = statTracker->getStat(STAT_ATP_MAPPING_REQUEST_FAILED).toInt();
|
||||
atpMappingRequests["successful"] = statTracker->getStat(STAT_ATP_MAPPING_REQUEST_SUCCESS).toInt();
|
||||
properties["atp_mapping_requests"] = atpMappingRequests;
|
||||
|
||||
properties["throttled"] = _displayPlugin ? _displayPlugin->isThrottled() : false;
|
||||
|
||||
|
@ -1340,9 +1403,43 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
properties["deleted_entity_cnt"] = entityActivityTracking.deletedEntityCount;
|
||||
properties["edited_entity_cnt"] = entityActivityTracking.editedEntityCount;
|
||||
|
||||
NodeToOctreeSceneStats* octreeServerSceneStats = getOcteeSceneStats();
|
||||
unsigned long totalServerOctreeElements = 0;
|
||||
for (NodeToOctreeSceneStatsIterator i = octreeServerSceneStats->begin(); i != octreeServerSceneStats->end(); i++) {
|
||||
totalServerOctreeElements += i->second.getTotalElements();
|
||||
}
|
||||
|
||||
properties["local_octree_elements"] = (qint64) OctreeElement::getInternalNodeCount();
|
||||
properties["server_octree_elements"] = (qint64) totalServerOctreeElements;
|
||||
|
||||
properties["active_display_plugin"] = getActiveDisplayPlugin()->getName();
|
||||
properties["using_hmd"] = isHMDMode();
|
||||
|
||||
_autoSwitchDisplayModeSupportedHMDPlugin = nullptr;
|
||||
foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) {
|
||||
if (displayPlugin->isHmd() &&
|
||||
displayPlugin->getSupportsAutoSwitch()) {
|
||||
_autoSwitchDisplayModeSupportedHMDPlugin = displayPlugin;
|
||||
_autoSwitchDisplayModeSupportedHMDPluginName =
|
||||
_autoSwitchDisplayModeSupportedHMDPlugin->getName();
|
||||
_previousHMDWornStatus =
|
||||
_autoSwitchDisplayModeSupportedHMDPlugin->isDisplayVisible();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (_autoSwitchDisplayModeSupportedHMDPlugin) {
|
||||
if (getActiveDisplayPlugin() != _autoSwitchDisplayModeSupportedHMDPlugin &&
|
||||
!_autoSwitchDisplayModeSupportedHMDPlugin->isSessionActive()) {
|
||||
startHMDStandBySession();
|
||||
}
|
||||
// Poll periodically to check whether the user has worn HMD or not. Switch Display mode accordingly.
|
||||
// If the user wears HMD then switch to VR mode. If the user removes HMD then switch to Desktop mode.
|
||||
QTimer* autoSwitchDisplayModeTimer = new QTimer(this);
|
||||
connect(autoSwitchDisplayModeTimer, SIGNAL(timeout()), this, SLOT(switchDisplayMode()));
|
||||
autoSwitchDisplayModeTimer->start(INTERVAL_TO_CHECK_HMD_WORN_STATUS);
|
||||
}
|
||||
|
||||
auto glInfo = getGLContextData();
|
||||
properties["gl_info"] = glInfo;
|
||||
properties["gpu_used_memory"] = (int)BYTES_TO_MB(gpu::Context::getUsedGPUMemSize());
|
||||
|
@ -1365,6 +1462,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
lastLeftHandPose = leftHandPose;
|
||||
lastRightHandPose = rightHandPose;
|
||||
|
||||
properties["local_socket_changes"] = DependencyManager::get<StatTracker>()->getStat(LOCAL_SOCKET_CHANGE_STAT).toInt();
|
||||
|
||||
UserActivityLogger::getInstance().logAction("stats", properties);
|
||||
});
|
||||
sendStatsTimer->start();
|
||||
|
@ -1574,7 +1673,10 @@ void Application::aboutToQuit() {
|
|||
}
|
||||
|
||||
getActiveDisplayPlugin()->deactivate();
|
||||
|
||||
if (_autoSwitchDisplayModeSupportedHMDPlugin
|
||||
&& _autoSwitchDisplayModeSupportedHMDPlugin->isSessionActive()) {
|
||||
_autoSwitchDisplayModeSupportedHMDPlugin->endSession();
|
||||
}
|
||||
// use the CloseEventSender via a QThread to send an event that says the user asked for the app to close
|
||||
auto closeEventSender = DependencyManager::get<CloseEventSender>();
|
||||
QThread* closureEventThread = new QThread(this);
|
||||
|
@ -1852,14 +1954,10 @@ void Application::initializeUi() {
|
|||
UpdateDialog::registerType();
|
||||
qmlRegisterType<Preference>("Hifi", 1, 0, "Preference");
|
||||
|
||||
qmlRegisterType<HFWebEngineProfile>("HFWebEngineProfile", 1, 0, "HFWebEngineProfile");
|
||||
qmlRegisterType<HFTabletWebEngineProfile>("HFTabletWebEngineProfile", 1, 0, "HFTabletWebEngineProfile");
|
||||
qmlRegisterType<FileTypeProfile>("FileTypeProfile", 1, 0, "FileTypeProfile");
|
||||
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
offscreenUi->create(_glWidget->qglContext());
|
||||
|
||||
auto rootContext = offscreenUi->getRootContext();
|
||||
auto surfaceContext = offscreenUi->getSurfaceContext();
|
||||
|
||||
offscreenUi->setProxyWindow(_window->windowHandle());
|
||||
offscreenUi->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/"));
|
||||
|
@ -1871,7 +1969,7 @@ void Application::initializeUi() {
|
|||
// do better detection in the offscreen UI of what has focus
|
||||
offscreenUi->setNavigationFocused(false);
|
||||
|
||||
auto engine = rootContext->engine();
|
||||
auto engine = surfaceContext->engine();
|
||||
connect(engine, &QQmlEngine::quit, [] {
|
||||
qApp->quit();
|
||||
});
|
||||
|
@ -1880,79 +1978,78 @@ void Application::initializeUi() {
|
|||
|
||||
// For some reason there is already an "Application" object in the QML context,
|
||||
// though I can't find it. Hence, "ApplicationInterface"
|
||||
rootContext->setContextProperty("ApplicationInterface", this);
|
||||
rootContext->setContextProperty("Audio", DependencyManager::get<AudioScriptingInterface>().data());
|
||||
rootContext->setContextProperty("AudioStats", DependencyManager::get<AudioClient>()->getStats().data());
|
||||
rootContext->setContextProperty("AudioScope", DependencyManager::get<AudioScope>().data());
|
||||
surfaceContext->setContextProperty("Audio", DependencyManager::get<AudioScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("AudioStats", DependencyManager::get<AudioClient>()->getStats().data());
|
||||
surfaceContext->setContextProperty("AudioScope", DependencyManager::get<AudioScope>().data());
|
||||
|
||||
rootContext->setContextProperty("Controller", DependencyManager::get<controller::ScriptingInterface>().data());
|
||||
rootContext->setContextProperty("Entities", DependencyManager::get<EntityScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("Controller", DependencyManager::get<controller::ScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("Entities", DependencyManager::get<EntityScriptingInterface>().data());
|
||||
_fileDownload = new FileScriptingInterface(engine);
|
||||
rootContext->setContextProperty("File", _fileDownload);
|
||||
surfaceContext->setContextProperty("File", _fileDownload);
|
||||
connect(_fileDownload, &FileScriptingInterface::unzipResult, this, &Application::handleUnzip);
|
||||
rootContext->setContextProperty("MyAvatar", getMyAvatar().get());
|
||||
rootContext->setContextProperty("Messages", DependencyManager::get<MessagesClient>().data());
|
||||
rootContext->setContextProperty("Recording", DependencyManager::get<RecordingScriptingInterface>().data());
|
||||
rootContext->setContextProperty("Preferences", DependencyManager::get<Preferences>().data());
|
||||
rootContext->setContextProperty("AddressManager", DependencyManager::get<AddressManager>().data());
|
||||
rootContext->setContextProperty("FrameTimings", &_frameTimingsScriptingInterface);
|
||||
rootContext->setContextProperty("Rates", new RatesScriptingInterface(this));
|
||||
rootContext->setContextProperty("pathToFonts", "../../");
|
||||
surfaceContext->setContextProperty("MyAvatar", getMyAvatar().get());
|
||||
surfaceContext->setContextProperty("Messages", DependencyManager::get<MessagesClient>().data());
|
||||
surfaceContext->setContextProperty("Recording", DependencyManager::get<RecordingScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("Preferences", DependencyManager::get<Preferences>().data());
|
||||
surfaceContext->setContextProperty("AddressManager", DependencyManager::get<AddressManager>().data());
|
||||
surfaceContext->setContextProperty("FrameTimings", &_frameTimingsScriptingInterface);
|
||||
surfaceContext->setContextProperty("Rates", new RatesScriptingInterface(this));
|
||||
|
||||
rootContext->setContextProperty("TREE_SCALE", TREE_SCALE);
|
||||
rootContext->setContextProperty("Quat", new Quat());
|
||||
rootContext->setContextProperty("Vec3", new Vec3());
|
||||
rootContext->setContextProperty("Uuid", new ScriptUUID());
|
||||
rootContext->setContextProperty("Assets", DependencyManager::get<AssetMappingsScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("TREE_SCALE", TREE_SCALE);
|
||||
// FIXME Quat and Vec3 won't work with QJSEngine used by QML
|
||||
surfaceContext->setContextProperty("Quat", new Quat());
|
||||
surfaceContext->setContextProperty("Vec3", new Vec3());
|
||||
surfaceContext->setContextProperty("Uuid", new ScriptUUID());
|
||||
surfaceContext->setContextProperty("Assets", DependencyManager::get<AssetMappingsScriptingInterface>().data());
|
||||
|
||||
rootContext->setContextProperty("AvatarList", DependencyManager::get<AvatarManager>().data());
|
||||
rootContext->setContextProperty("Users", DependencyManager::get<UsersScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("AvatarList", DependencyManager::get<AvatarManager>().data());
|
||||
surfaceContext->setContextProperty("Users", DependencyManager::get<UsersScriptingInterface>().data());
|
||||
|
||||
rootContext->setContextProperty("UserActivityLogger", DependencyManager::get<UserActivityLoggerScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("UserActivityLogger", DependencyManager::get<UserActivityLoggerScriptingInterface>().data());
|
||||
|
||||
rootContext->setContextProperty("Camera", &_myCamera);
|
||||
surfaceContext->setContextProperty("Camera", &_myCamera);
|
||||
|
||||
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
|
||||
rootContext->setContextProperty("SpeechRecognizer", DependencyManager::get<SpeechRecognizer>().data());
|
||||
surfaceContext->setContextProperty("SpeechRecognizer", DependencyManager::get<SpeechRecognizer>().data());
|
||||
#endif
|
||||
|
||||
rootContext->setContextProperty("Overlays", &_overlays);
|
||||
rootContext->setContextProperty("Window", DependencyManager::get<WindowScriptingInterface>().data());
|
||||
rootContext->setContextProperty("MenuInterface", MenuScriptingInterface::getInstance());
|
||||
rootContext->setContextProperty("Stats", Stats::getInstance());
|
||||
rootContext->setContextProperty("Settings", SettingsScriptingInterface::getInstance());
|
||||
rootContext->setContextProperty("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());
|
||||
rootContext->setContextProperty("AudioDevice", AudioDeviceScriptingInterface::getInstance());
|
||||
rootContext->setContextProperty("AvatarBookmarks", DependencyManager::get<AvatarBookmarks>().data());
|
||||
rootContext->setContextProperty("LocationBookmarks", DependencyManager::get<LocationBookmarks>().data());
|
||||
surfaceContext->setContextProperty("Overlays", &_overlays);
|
||||
surfaceContext->setContextProperty("Window", DependencyManager::get<WindowScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("MenuInterface", MenuScriptingInterface::getInstance());
|
||||
surfaceContext->setContextProperty("Stats", Stats::getInstance());
|
||||
surfaceContext->setContextProperty("Settings", SettingsScriptingInterface::getInstance());
|
||||
surfaceContext->setContextProperty("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());
|
||||
surfaceContext->setContextProperty("AudioDevice", AudioDeviceScriptingInterface::getInstance());
|
||||
surfaceContext->setContextProperty("AvatarBookmarks", DependencyManager::get<AvatarBookmarks>().data());
|
||||
surfaceContext->setContextProperty("LocationBookmarks", DependencyManager::get<LocationBookmarks>().data());
|
||||
|
||||
// Caches
|
||||
rootContext->setContextProperty("AnimationCache", DependencyManager::get<AnimationCache>().data());
|
||||
rootContext->setContextProperty("TextureCache", DependencyManager::get<TextureCache>().data());
|
||||
rootContext->setContextProperty("ModelCache", DependencyManager::get<ModelCache>().data());
|
||||
rootContext->setContextProperty("SoundCache", DependencyManager::get<SoundCache>().data());
|
||||
surfaceContext->setContextProperty("AnimationCache", DependencyManager::get<AnimationCache>().data());
|
||||
surfaceContext->setContextProperty("TextureCache", DependencyManager::get<TextureCache>().data());
|
||||
surfaceContext->setContextProperty("ModelCache", DependencyManager::get<ModelCache>().data());
|
||||
surfaceContext->setContextProperty("SoundCache", DependencyManager::get<SoundCache>().data());
|
||||
|
||||
rootContext->setContextProperty("Account", AccountScriptingInterface::getInstance());
|
||||
rootContext->setContextProperty("Tablet", DependencyManager::get<TabletScriptingInterface>().data());
|
||||
rootContext->setContextProperty("DialogsManager", _dialogsManagerScriptingInterface);
|
||||
rootContext->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance());
|
||||
rootContext->setContextProperty("FaceTracker", DependencyManager::get<DdeFaceTracker>().data());
|
||||
rootContext->setContextProperty("AvatarManager", DependencyManager::get<AvatarManager>().data());
|
||||
rootContext->setContextProperty("UndoStack", &_undoStackScriptingInterface);
|
||||
rootContext->setContextProperty("LODManager", DependencyManager::get<LODManager>().data());
|
||||
rootContext->setContextProperty("Paths", DependencyManager::get<PathUtils>().data());
|
||||
rootContext->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
|
||||
rootContext->setContextProperty("Scene", DependencyManager::get<SceneScriptingInterface>().data());
|
||||
rootContext->setContextProperty("Render", _renderEngine->getConfiguration().get());
|
||||
rootContext->setContextProperty("Reticle", getApplicationCompositor().getReticleInterface());
|
||||
rootContext->setContextProperty("Snapshot", DependencyManager::get<Snapshot>().data());
|
||||
surfaceContext->setContextProperty("Account", AccountScriptingInterface::getInstance());
|
||||
surfaceContext->setContextProperty("Tablet", DependencyManager::get<TabletScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("DialogsManager", _dialogsManagerScriptingInterface);
|
||||
surfaceContext->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance());
|
||||
surfaceContext->setContextProperty("FaceTracker", DependencyManager::get<DdeFaceTracker>().data());
|
||||
surfaceContext->setContextProperty("AvatarManager", DependencyManager::get<AvatarManager>().data());
|
||||
surfaceContext->setContextProperty("UndoStack", &_undoStackScriptingInterface);
|
||||
surfaceContext->setContextProperty("LODManager", DependencyManager::get<LODManager>().data());
|
||||
surfaceContext->setContextProperty("Paths", DependencyManager::get<PathUtils>().data());
|
||||
surfaceContext->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("Scene", DependencyManager::get<SceneScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("Render", _renderEngine->getConfiguration().get());
|
||||
surfaceContext->setContextProperty("Reticle", getApplicationCompositor().getReticleInterface());
|
||||
surfaceContext->setContextProperty("Snapshot", DependencyManager::get<Snapshot>().data());
|
||||
|
||||
rootContext->setContextProperty("ApplicationCompositor", &getApplicationCompositor());
|
||||
surfaceContext->setContextProperty("ApplicationCompositor", &getApplicationCompositor());
|
||||
|
||||
rootContext->setContextProperty("AvatarInputs", AvatarInputs::getInstance());
|
||||
surfaceContext->setContextProperty("AvatarInputs", AvatarInputs::getInstance());
|
||||
|
||||
if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
|
||||
rootContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get()));
|
||||
surfaceContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get()));
|
||||
}
|
||||
|
||||
|
||||
|
@ -2211,6 +2308,9 @@ void Application::paintGL() {
|
|||
});
|
||||
renderArgs._context->setStereoProjections(eyeProjections);
|
||||
renderArgs._context->setStereoViews(eyeOffsets);
|
||||
|
||||
// Configure the type of display / stereo
|
||||
renderArgs._displayMode = (isHMDMode() ? RenderArgs::STEREO_HMD : RenderArgs::STEREO_MONITOR);
|
||||
}
|
||||
renderArgs._blitFramebuffer = finalFramebuffer;
|
||||
displaySide(&renderArgs, _myCamera);
|
||||
|
@ -6787,6 +6887,35 @@ void Application::updateDisplayMode() {
|
|||
Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin");
|
||||
}
|
||||
|
||||
void Application::switchDisplayMode() {
|
||||
if (!_autoSwitchDisplayModeSupportedHMDPlugin) {
|
||||
return;
|
||||
}
|
||||
bool currentHMDWornStatus = _autoSwitchDisplayModeSupportedHMDPlugin->isDisplayVisible();
|
||||
if (currentHMDWornStatus != _previousHMDWornStatus) {
|
||||
// Switch to respective mode as soon as currentHMDWornStatus changes
|
||||
if (currentHMDWornStatus) {
|
||||
qCDebug(interfaceapp) << "Switching from Desktop to HMD mode";
|
||||
endHMDSession();
|
||||
setActiveDisplayPlugin(_autoSwitchDisplayModeSupportedHMDPluginName);
|
||||
} else {
|
||||
qCDebug(interfaceapp) << "Switching from HMD to desktop mode";
|
||||
setActiveDisplayPlugin(DESKTOP_DISPLAY_PLUGIN_NAME);
|
||||
startHMDStandBySession();
|
||||
}
|
||||
emit activeDisplayPluginChanged();
|
||||
}
|
||||
_previousHMDWornStatus = currentHMDWornStatus;
|
||||
}
|
||||
|
||||
void Application::startHMDStandBySession() {
|
||||
_autoSwitchDisplayModeSupportedHMDPlugin->startStandBySession();
|
||||
}
|
||||
|
||||
void Application::endHMDSession() {
|
||||
_autoSwitchDisplayModeSupportedHMDPlugin->endSession();
|
||||
}
|
||||
|
||||
mat4 Application::getEyeProjection(int eye) const {
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
if (isHMDMode()) {
|
||||
|
|
|
@ -442,7 +442,7 @@ private slots:
|
|||
void addAssetToWorldErrorTimeout();
|
||||
|
||||
void handleSandboxStatus(QNetworkReply* reply);
|
||||
|
||||
void switchDisplayMode();
|
||||
private:
|
||||
static void initDisplay();
|
||||
void init();
|
||||
|
@ -680,7 +680,11 @@ private:
|
|||
FileScriptingInterface* _fileDownload;
|
||||
AudioInjector* _snapshotSoundInjector { nullptr };
|
||||
SharedSoundPointer _snapshotSound;
|
||||
|
||||
DisplayPluginPointer _autoSwitchDisplayModeSupportedHMDPlugin;
|
||||
QString _autoSwitchDisplayModeSupportedHMDPluginName;
|
||||
bool _previousHMDWornStatus;
|
||||
void startHMDStandBySession();
|
||||
void endHMDSession();
|
||||
};
|
||||
|
||||
|
||||
#endif // hifi_Application_h
|
||||
|
|
|
@ -51,6 +51,16 @@ Text3DOverlay::~Text3DOverlay() {
|
|||
}
|
||||
}
|
||||
|
||||
const QString Text3DOverlay::getText() const {
|
||||
QMutexLocker lock(&_mutex);
|
||||
return _text;
|
||||
}
|
||||
|
||||
void Text3DOverlay::setText(const QString& text) {
|
||||
QMutexLocker lock(&_mutex);
|
||||
_text = text;
|
||||
}
|
||||
|
||||
xColor Text3DOverlay::getBackgroundColor() {
|
||||
if (_colorPulse == 0.0f) {
|
||||
return _backgroundColor;
|
||||
|
@ -125,7 +135,7 @@ void Text3DOverlay::render(RenderArgs* args) {
|
|||
// FIXME: Factor out textRenderer so that Text3DOverlay overlay parts can be grouped by pipeline
|
||||
// for a gpu performance increase. Currently,
|
||||
// Text renderer sets its own pipeline,
|
||||
_textRenderer->draw(batch, 0, 0, _text, textColor, glm::vec2(-1.0f), getDrawInFront());
|
||||
_textRenderer->draw(batch, 0, 0, getText(), textColor, glm::vec2(-1.0f), getDrawInFront());
|
||||
// so before we continue, we must reset the pipeline
|
||||
batch.setPipeline(args->_pipeline->pipeline);
|
||||
args->_pipeline->prepare(batch);
|
||||
|
@ -188,7 +198,7 @@ void Text3DOverlay::setProperties(const QVariantMap& properties) {
|
|||
|
||||
QVariant Text3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "text") {
|
||||
return _text;
|
||||
return getText();
|
||||
}
|
||||
if (property == "textAlpha") {
|
||||
return _textAlpha;
|
||||
|
@ -231,7 +241,7 @@ QSizeF Text3DOverlay::textSize(const QString& text) const {
|
|||
return QSizeF(extents.x, extents.y) * pointToWorldScale;
|
||||
}
|
||||
|
||||
bool Text3DOverlay::findRayIntersection(const glm::vec3 &origin, const glm::vec3 &direction, float &distance,
|
||||
bool Text3DOverlay::findRayIntersection(const glm::vec3 &origin, const glm::vec3 &direction, float &distance,
|
||||
BoxFace &face, glm::vec3& surfaceNormal) {
|
||||
Transform transform = getTransform();
|
||||
applyTransformTo(transform, true);
|
||||
|
|
|
@ -12,14 +12,14 @@
|
|||
#define hifi_Text3DOverlay_h
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include <QtCore/QMutex>
|
||||
#include "Billboard3DOverlay.h"
|
||||
|
||||
class TextRenderer3D;
|
||||
|
||||
class Text3DOverlay : public Billboard3DOverlay {
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
public:
|
||||
static QString const TYPE;
|
||||
virtual QString getType() const override { return TYPE; }
|
||||
|
@ -34,7 +34,7 @@ public:
|
|||
virtual const render::ShapeKey getShapeKey() override;
|
||||
|
||||
// getters
|
||||
const QString& getText() const { return _text; }
|
||||
const QString getText() const;
|
||||
float getLineHeight() const { return _lineHeight; }
|
||||
float getLeftMargin() const { return _leftMargin; }
|
||||
float getTopMargin() const { return _topMargin; }
|
||||
|
@ -45,7 +45,7 @@ public:
|
|||
float getBackgroundAlpha() { return getAlpha(); }
|
||||
|
||||
// setters
|
||||
void setText(const QString& text) { _text = text; }
|
||||
void setText(const QString& text);
|
||||
void setTextAlpha(float alpha) { _textAlpha = alpha; }
|
||||
void setLineHeight(float value) { _lineHeight = value; }
|
||||
void setLeftMargin(float margin) { _leftMargin = margin; }
|
||||
|
@ -58,15 +58,16 @@ public:
|
|||
|
||||
QSizeF textSize(const QString& test) const; // Meters
|
||||
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal) override;
|
||||
|
||||
virtual Text3DOverlay* createClone() const override;
|
||||
|
||||
private:
|
||||
TextRenderer3D* _textRenderer = nullptr;
|
||||
|
||||
|
||||
QString _text;
|
||||
mutable QMutex _mutex; // used to make get/setText threadsafe, mutable so can be used in const functions
|
||||
xColor _backgroundColor = xColor { 0, 0, 0 };
|
||||
float _textAlpha { 1.0f };
|
||||
float _lineHeight { 1.0f };
|
||||
|
|
|
@ -135,7 +135,7 @@ Web3DOverlay::~Web3DOverlay() {
|
|||
void Web3DOverlay::update(float deltatime) {
|
||||
if (_webSurface) {
|
||||
// update globalPosition
|
||||
_webSurface->getRootContext()->setContextProperty("globalPosition", vec3toVariant(getPosition()));
|
||||
_webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(getPosition()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,57 +163,56 @@ void Web3DOverlay::loadSourceURL() {
|
|||
_webSurface->resume();
|
||||
_webSurface->getRootItem()->setProperty("url", _url);
|
||||
_webSurface->getRootItem()->setProperty("scriptURL", _scriptURL);
|
||||
_webSurface->getRootContext()->setContextProperty("ApplicationInterface", qApp);
|
||||
|
||||
} else {
|
||||
_webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath()));
|
||||
_webSurface->load(_url, [&](QQmlContext* context, QObject* obj) {});
|
||||
_webSurface->resume();
|
||||
|
||||
_webSurface->getRootContext()->setContextProperty("Users", DependencyManager::get<UsersScriptingInterface>().data());
|
||||
_webSurface->getRootContext()->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
|
||||
_webSurface->getRootContext()->setContextProperty("UserActivityLogger", DependencyManager::get<UserActivityLoggerScriptingInterface>().data());
|
||||
_webSurface->getRootContext()->setContextProperty("Preferences", DependencyManager::get<Preferences>().data());
|
||||
_webSurface->getRootContext()->setContextProperty("Vec3", new Vec3());
|
||||
_webSurface->getRootContext()->setContextProperty("Quat", new Quat());
|
||||
_webSurface->getRootContext()->setContextProperty("MyAvatar", DependencyManager::get<AvatarManager>()->getMyAvatar().get());
|
||||
_webSurface->getRootContext()->setContextProperty("Entities", DependencyManager::get<EntityScriptingInterface>().data());
|
||||
_webSurface->getRootContext()->setContextProperty("Snapshot", DependencyManager::get<Snapshot>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("Users", DependencyManager::get<UsersScriptingInterface>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("UserActivityLogger", DependencyManager::get<UserActivityLoggerScriptingInterface>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("Preferences", DependencyManager::get<Preferences>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("Vec3", new Vec3());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("Quat", new Quat());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("MyAvatar", DependencyManager::get<AvatarManager>()->getMyAvatar().get());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("Entities", DependencyManager::get<EntityScriptingInterface>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("Snapshot", DependencyManager::get<Snapshot>().data());
|
||||
|
||||
if (_webSurface->getRootItem() && _webSurface->getRootItem()->objectName() == "tabletRoot") {
|
||||
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||
auto flags = tabletScriptingInterface->getFlags();
|
||||
_webSurface->getRootContext()->setContextProperty("offscreenFlags", flags);
|
||||
_webSurface->getRootContext()->setContextProperty("AddressManager", DependencyManager::get<AddressManager>().data());
|
||||
_webSurface->getRootContext()->setContextProperty("Account", AccountScriptingInterface::getInstance());
|
||||
_webSurface->getRootContext()->setContextProperty("AudioStats", DependencyManager::get<AudioClient>()->getStats().data());
|
||||
_webSurface->getRootContext()->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
|
||||
_webSurface->getRootContext()->setContextProperty("fileDialogHelper", new FileDialogHelper());
|
||||
_webSurface->getRootContext()->setContextProperty("MyAvatar", DependencyManager::get<AvatarManager>()->getMyAvatar().get());
|
||||
_webSurface->getRootContext()->setContextProperty("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());
|
||||
_webSurface->getRootContext()->setContextProperty("Tablet", DependencyManager::get<TabletScriptingInterface>().data());
|
||||
_webSurface->getRootContext()->setContextProperty("Assets", DependencyManager::get<AssetMappingsScriptingInterface>().data());
|
||||
_webSurface->getRootContext()->setContextProperty("LODManager", DependencyManager::get<LODManager>().data());
|
||||
_webSurface->getRootContext()->setContextProperty("OctreeStats", DependencyManager::get<OctreeStatsProvider>().data());
|
||||
_webSurface->getRootContext()->setContextProperty("DCModel", DependencyManager::get<DomainConnectionModel>().data());
|
||||
_webSurface->getRootContext()->setContextProperty("AudioDevice", AudioDeviceScriptingInterface::getInstance());
|
||||
_webSurface->getRootContext()->setContextProperty("AvatarInputs", AvatarInputs::getInstance());
|
||||
_webSurface->getRootContext()->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance());
|
||||
_webSurface->getRootContext()->setContextProperty("AvatarList", DependencyManager::get<AvatarManager>().data());
|
||||
_webSurface->getRootContext()->setContextProperty("DialogsManager", DialogsManagerScriptingInterface::getInstance());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("offscreenFlags", flags);
|
||||
_webSurface->getSurfaceContext()->setContextProperty("AddressManager", DependencyManager::get<AddressManager>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("Account", AccountScriptingInterface::getInstance());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("AudioStats", DependencyManager::get<AudioClient>()->getStats().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("fileDialogHelper", new FileDialogHelper());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("MyAvatar", DependencyManager::get<AvatarManager>()->getMyAvatar().get());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("Tablet", DependencyManager::get<TabletScriptingInterface>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("Assets", DependencyManager::get<AssetMappingsScriptingInterface>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("LODManager", DependencyManager::get<LODManager>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("OctreeStats", DependencyManager::get<OctreeStatsProvider>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("DCModel", DependencyManager::get<DomainConnectionModel>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("AudioDevice", AudioDeviceScriptingInterface::getInstance());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("AvatarInputs", AvatarInputs::getInstance());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("AvatarList", DependencyManager::get<AvatarManager>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("DialogsManager", DialogsManagerScriptingInterface::getInstance());
|
||||
|
||||
_webSurface->getRootContext()->setContextProperty("pathToFonts", "../../");
|
||||
_webSurface->getSurfaceContext()->setContextProperty("pathToFonts", "../../");
|
||||
tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface->getRootItem(), _webSurface.data());
|
||||
|
||||
// mark the TabletProxy object as cpp ownership.
|
||||
QObject* tablet = tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system");
|
||||
_webSurface->getRootContext()->engine()->setObjectOwnership(tablet, QQmlEngine::CppOwnership);
|
||||
_webSurface->getSurfaceContext()->engine()->setObjectOwnership(tablet, QQmlEngine::CppOwnership);
|
||||
|
||||
// Override min fps for tablet UI, for silky smooth scrolling
|
||||
setMaxFPS(90);
|
||||
}
|
||||
}
|
||||
_webSurface->getRootContext()->setContextProperty("globalPosition", vec3toVariant(getPosition()));
|
||||
_webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(getPosition()));
|
||||
}
|
||||
|
||||
void Web3DOverlay::setMaxFPS(uint8_t maxFPS) {
|
||||
|
|
|
@ -1135,9 +1135,9 @@ void Rig::updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm
|
|||
}
|
||||
|
||||
glm::vec3 headUp = headQuat * Vectors::UNIT_Y;
|
||||
glm::vec3 z, y, x;
|
||||
generateBasisVectors(lookAtVector, headUp, z, y, x);
|
||||
glm::mat3 m(glm::cross(y, z), y, z);
|
||||
glm::vec3 z, y, zCrossY;
|
||||
generateBasisVectors(lookAtVector, headUp, z, y, zCrossY);
|
||||
glm::mat3 m(-zCrossY, y, z);
|
||||
glm::quat desiredQuat = glm::normalize(glm::quat_cast(m));
|
||||
|
||||
glm::quat deltaQuat = desiredQuat * glm::inverse(headQuat);
|
||||
|
|
|
@ -339,6 +339,18 @@ void OpenGLDisplayPlugin::deactivate() {
|
|||
Parent::deactivate();
|
||||
}
|
||||
|
||||
bool OpenGLDisplayPlugin::startStandBySession() {
|
||||
if (!activateStandBySession()) {
|
||||
return false;
|
||||
}
|
||||
return Parent::startStandBySession();
|
||||
}
|
||||
|
||||
void OpenGLDisplayPlugin::endSession() {
|
||||
deactivateSession();
|
||||
Parent::endSession();
|
||||
}
|
||||
|
||||
void OpenGLDisplayPlugin::customizeContext() {
|
||||
auto presentThread = DependencyManager::get<PresentThread>();
|
||||
Q_ASSERT(thread() == presentThread->thread());
|
||||
|
|
|
@ -42,6 +42,8 @@ public:
|
|||
// between the main thread and the presentation thread
|
||||
bool activate() override final;
|
||||
void deactivate() override final;
|
||||
bool startStandBySession() override final;
|
||||
void endSession() override final;
|
||||
bool eventFilter(QObject* receiver, QEvent* event) override;
|
||||
bool isDisplayVisible() const override { return true; }
|
||||
|
||||
|
@ -99,6 +101,10 @@ protected:
|
|||
// Returns true on successful activation
|
||||
virtual bool internalActivate() { return true; }
|
||||
virtual void internalDeactivate() {}
|
||||
|
||||
// Returns true on successful activation of standby session
|
||||
virtual bool activateStandBySession() { return true; }
|
||||
virtual void deactivateSession() {}
|
||||
|
||||
// Plugin specific functionality to send the composed scene to the output window or device
|
||||
virtual void internalPresent();
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <DependencyManager.h>
|
||||
#include <PerfStat.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <StencilMaskPass.h>
|
||||
#include <AbstractViewStateInterface.h>
|
||||
#include "EntitiesRendererLogging.h"
|
||||
|
||||
|
@ -292,6 +293,7 @@ void RenderableParticleEffectEntityItem::createPipelines() {
|
|||
state->setDepthTest(true, false, gpu::LESS_EQUAL);
|
||||
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
PrepareStencil::testMask(*state);
|
||||
|
||||
auto vertShader = gpu::Shader::createVertex(std::string(untextured_particle_vert));
|
||||
auto fragShader = gpu::Shader::createPixel(std::string(untextured_particle_frag));
|
||||
|
@ -305,6 +307,7 @@ void RenderableParticleEffectEntityItem::createPipelines() {
|
|||
state->setDepthTest(true, false, gpu::LESS_EQUAL);
|
||||
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
PrepareStencil::testMask(*state);
|
||||
|
||||
auto vertShader = gpu::Shader::createVertex(std::string(textured_particle_vert));
|
||||
auto fragShader = gpu::Shader::createPixel(std::string(textured_particle_frag));
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
#include <GeometryCache.h>
|
||||
#include <StencilMaskPass.h>
|
||||
#include <TextureCache.h>
|
||||
#include <PathUtils.h>
|
||||
#include <PerfStat.h>
|
||||
|
@ -69,6 +70,7 @@ void RenderablePolyLineEntityItem::createPipeline() {
|
|||
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
PrepareStencil::testMask(*state);
|
||||
state->setBlendFunction(true,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
|
|
|
@ -46,6 +46,9 @@
|
|||
#endif
|
||||
|
||||
#include "model/Geometry.h"
|
||||
|
||||
#include "StencilMaskPass.h"
|
||||
|
||||
#include "EntityTreeRenderer.h"
|
||||
#include "polyvox_vert.h"
|
||||
#include "polyvox_frag.h"
|
||||
|
@ -743,6 +746,7 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) {
|
|||
auto state = std::make_shared<gpu::State>();
|
||||
state->setCullMode(gpu::State::CULL_BACK);
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
PrepareStencil::testMaskDrawShape(*state);
|
||||
|
||||
_pipeline = gpu::Pipeline::create(program, state);
|
||||
|
||||
|
@ -750,6 +754,7 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) {
|
|||
wireframeState->setCullMode(gpu::State::CULL_BACK);
|
||||
wireframeState->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
wireframeState->setFillMode(gpu::State::FILL_LINE);
|
||||
PrepareStencil::testMaskDrawShape(*wireframeState);
|
||||
|
||||
_wireframePipeline = gpu::Pipeline::create(program, wireframeState);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <gpu/Batch.h>
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include <StencilMaskPass.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <PerfStat.h>
|
||||
|
||||
|
@ -93,6 +94,7 @@ void RenderableShapeEntityItem::render(RenderArgs* args) {
|
|||
_procedural->_fragmentSource = simple_frag;
|
||||
_procedural->_opaqueState->setCullMode(gpu::State::CULL_NONE);
|
||||
_procedural->_opaqueState->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
PrepareStencil::testMaskDrawShape(*_procedural->_opaqueState);
|
||||
_procedural->_opaqueState->setBlendFunction(false,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
|
|
|
@ -127,7 +127,7 @@ bool RenderableWebEntityItem::buildWebSurface(QSharedPointer<EntityTreeRenderer>
|
|||
|
||||
_webSurface->resume();
|
||||
_webSurface->getRootItem()->setProperty("url", _sourceUrl);
|
||||
_webSurface->getRootContext()->setContextProperty("desktop", QVariant());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("desktop", QVariant());
|
||||
// FIXME - Keyboard HMD only: Possibly add "HMDinfo" object to context for WebView.qml.
|
||||
|
||||
// forward web events to EntityScriptingInterface
|
||||
|
@ -271,7 +271,7 @@ void RenderableWebEntityItem::loadSourceURL() {
|
|||
});
|
||||
|
||||
_webSurface->getRootItem()->setProperty("url", _sourceUrl);
|
||||
_webSurface->getRootContext()->setContextProperty("desktop", QVariant());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("desktop", QVariant());
|
||||
|
||||
} else {
|
||||
_contentType = qmlContent;
|
||||
|
@ -284,7 +284,7 @@ void RenderableWebEntityItem::loadSourceURL() {
|
|||
_webSurface->getRootItem(), _webSurface.data());
|
||||
}
|
||||
}
|
||||
_webSurface->getRootContext()->setContextProperty("globalPosition", vec3toVariant(getPosition()));
|
||||
_webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(getPosition()));
|
||||
}
|
||||
|
||||
|
||||
|
@ -420,7 +420,7 @@ void RenderableWebEntityItem::update(const quint64& now) {
|
|||
|
||||
if (_webSurface) {
|
||||
// update globalPosition
|
||||
_webSurface->getRootContext()->setContextProperty("globalPosition", vec3toVariant(getPosition()));
|
||||
_webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(getPosition()));
|
||||
}
|
||||
|
||||
auto interval = now - _lastRenderTime;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
set(TARGET_NAME gl)
|
||||
setup_hifi_library(OpenGL Qml Quick)
|
||||
link_hifi_libraries(shared)
|
||||
link_hifi_libraries(shared networking)
|
||||
|
||||
target_opengl()
|
||||
|
||||
|
|
|
@ -33,6 +33,9 @@
|
|||
#include <NetworkAccessManager.h>
|
||||
#include <GLMHelpers.h>
|
||||
#include <shared/GlobalAppProperties.h>
|
||||
#include <FileTypeProfile.h>
|
||||
#include <HFWebEngineProfile.h>
|
||||
#include <HFTabletWebEngineProfile.h>
|
||||
|
||||
#include "OffscreenGLCanvas.h"
|
||||
#include "GLHelpers.h"
|
||||
|
@ -41,6 +44,7 @@
|
|||
|
||||
Q_LOGGING_CATEGORY(trace_render_qml, "trace.render.qml")
|
||||
Q_LOGGING_CATEGORY(trace_render_qml_gl, "trace.render.qml.gl")
|
||||
Q_LOGGING_CATEGORY(offscreenFocus, "hifi.offscreen.focus")
|
||||
|
||||
struct TextureSet {
|
||||
// The number of surfaces with this size
|
||||
|
@ -254,8 +258,72 @@ QNetworkAccessManager* QmlNetworkAccessManagerFactory::create(QObject* parent) {
|
|||
return new QmlNetworkAccessManager(parent);
|
||||
}
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(offscreenFocus)
|
||||
Q_LOGGING_CATEGORY(offscreenFocus, "hifi.offscreen.focus")
|
||||
static QQmlEngine* globalEngine { nullptr };
|
||||
static size_t globalEngineRefCount { 0 };
|
||||
|
||||
QString getEventBridgeJavascript() {
|
||||
// FIXME: Refactor with similar code in RenderableWebEntityItem
|
||||
QString javaScriptToInject;
|
||||
QFile webChannelFile(":qtwebchannel/qwebchannel.js");
|
||||
QFile createGlobalEventBridgeFile(PathUtils::resourcesPath() + "/html/createGlobalEventBridge.js");
|
||||
if (webChannelFile.open(QFile::ReadOnly | QFile::Text) &&
|
||||
createGlobalEventBridgeFile.open(QFile::ReadOnly | QFile::Text)) {
|
||||
QString webChannelStr = QTextStream(&webChannelFile).readAll();
|
||||
QString createGlobalEventBridgeStr = QTextStream(&createGlobalEventBridgeFile).readAll();
|
||||
javaScriptToInject = webChannelStr + createGlobalEventBridgeStr;
|
||||
} else {
|
||||
qCWarning(glLogging) << "Unable to find qwebchannel.js or createGlobalEventBridge.js";
|
||||
}
|
||||
return javaScriptToInject;
|
||||
}
|
||||
|
||||
|
||||
QQmlEngine* acquireEngine(QQuickWindow* window) {
|
||||
Q_ASSERT(QThread::currentThread() == qApp->thread());
|
||||
if (!globalEngine) {
|
||||
Q_ASSERT(0 == globalEngineRefCount);
|
||||
globalEngine = new QQmlEngine();
|
||||
globalEngine->setNetworkAccessManagerFactory(new QmlNetworkAccessManagerFactory);
|
||||
|
||||
auto importList = globalEngine->importPathList();
|
||||
importList.insert(importList.begin(), PathUtils::resourcesPath());
|
||||
globalEngine->setImportPathList(importList);
|
||||
for (const auto& path : importList) {
|
||||
qDebug() << path;
|
||||
}
|
||||
|
||||
if (!globalEngine->incubationController()) {
|
||||
globalEngine->setIncubationController(window->incubationController());
|
||||
}
|
||||
auto rootContext = globalEngine->rootContext();
|
||||
rootContext->setContextProperty("GL", ::getGLContextData());
|
||||
rootContext->setContextProperty("urlHandler", new UrlHandler());
|
||||
rootContext->setContextProperty("resourceDirectoryUrl", QUrl::fromLocalFile(PathUtils::resourcesPath()));
|
||||
rootContext->setContextProperty("pathToFonts", "../../");
|
||||
rootContext->setContextProperty("ApplicationInterface", qApp);
|
||||
auto javaScriptToInject = getEventBridgeJavascript();
|
||||
if (!javaScriptToInject.isEmpty()) {
|
||||
rootContext->setContextProperty("eventBridgeJavaScriptToInject", QVariant(javaScriptToInject));
|
||||
}
|
||||
rootContext->setContextProperty("FileTypeProfile", new FileTypeProfile(rootContext));
|
||||
rootContext->setContextProperty("HFWebEngineProfile", new HFWebEngineProfile(rootContext));
|
||||
rootContext->setContextProperty("HFTabletWebEngineProfile", new HFTabletWebEngineProfile(rootContext));
|
||||
|
||||
|
||||
}
|
||||
|
||||
++globalEngineRefCount;
|
||||
return globalEngine;
|
||||
}
|
||||
|
||||
void releaseEngine() {
|
||||
Q_ASSERT(QThread::currentThread() == qApp->thread());
|
||||
Q_ASSERT(0 != globalEngineRefCount);
|
||||
if (0 == --globalEngineRefCount) {
|
||||
globalEngine->deleteLater();
|
||||
globalEngine = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void OffscreenQmlSurface::cleanup() {
|
||||
_canvas->makeCurrent();
|
||||
|
@ -294,6 +362,7 @@ void OffscreenQmlSurface::render() {
|
|||
GLuint texture = offscreenTextures.getNextTexture(_size);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo);
|
||||
glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
_renderControl->render();
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
@ -362,8 +431,8 @@ OffscreenQmlSurface::~OffscreenQmlSurface() {
|
|||
_canvas->deleteLater();
|
||||
_rootItem->deleteLater();
|
||||
_qmlComponent->deleteLater();
|
||||
_qmlEngine->deleteLater();
|
||||
_quickWindow->deleteLater();
|
||||
releaseEngine();
|
||||
}
|
||||
|
||||
void OffscreenQmlSurface::onAboutToQuit() {
|
||||
|
@ -375,6 +444,8 @@ void OffscreenQmlSurface::create(QOpenGLContext* shareContext) {
|
|||
qCDebug(glLogging) << "Building QML surface";
|
||||
|
||||
_renderControl = new QMyQuickRenderControl();
|
||||
connect(_renderControl, &QQuickRenderControl::renderRequested, this, [this] { _render = true; });
|
||||
connect(_renderControl, &QQuickRenderControl::sceneChanged, this, [this] { _render = _polish = true; });
|
||||
|
||||
QQuickWindow::setDefaultAlphaBuffer(true);
|
||||
|
||||
|
@ -385,7 +456,7 @@ void OffscreenQmlSurface::create(QOpenGLContext* shareContext) {
|
|||
// so we wait until after its ctor to move object/context to this thread.
|
||||
_quickWindow = new QQuickWindow(_renderControl);
|
||||
_quickWindow->setColor(QColor(255, 255, 255, 0));
|
||||
_quickWindow->setFlags(_quickWindow->flags() | static_cast<Qt::WindowFlags>(Qt::WA_TranslucentBackground));
|
||||
_quickWindow->setClearBeforeRendering(false);
|
||||
|
||||
_renderControl->_renderWindow = _proxyWindow;
|
||||
|
||||
|
@ -398,32 +469,20 @@ void OffscreenQmlSurface::create(QOpenGLContext* shareContext) {
|
|||
connect(_quickWindow, &QQuickWindow::focusObjectChanged, this, &OffscreenQmlSurface::onFocusObjectChanged);
|
||||
|
||||
// Create a QML engine.
|
||||
_qmlEngine = new QQmlEngine;
|
||||
auto qmlEngine = acquireEngine(_quickWindow);
|
||||
_qmlContext = new QQmlContext(qmlEngine->rootContext());
|
||||
|
||||
_qmlEngine->setNetworkAccessManagerFactory(new QmlNetworkAccessManagerFactory);
|
||||
_qmlContext->setContextProperty("offscreenWindow", QVariant::fromValue(getWindow()));
|
||||
_qmlContext->setContextProperty("globalEventBridge", this);
|
||||
_qmlContext->setContextProperty("webEntity", this);
|
||||
|
||||
auto importList = _qmlEngine->importPathList();
|
||||
importList.insert(importList.begin(), PathUtils::resourcesPath());
|
||||
_qmlEngine->setImportPathList(importList);
|
||||
if (!_qmlEngine->incubationController()) {
|
||||
_qmlEngine->setIncubationController(_quickWindow->incubationController());
|
||||
}
|
||||
_qmlComponent = new QQmlComponent(qmlEngine);
|
||||
|
||||
// FIXME
|
||||
_glData = ::getGLContextData(); // Initialize JSON structure so that it can be filled in later and then used in QML.
|
||||
_qmlEngine->rootContext()->setContextProperty("GL", _glData);
|
||||
_qmlEngine->rootContext()->setContextProperty("offscreenWindow", QVariant::fromValue(getWindow()));
|
||||
_qmlComponent = new QQmlComponent(_qmlEngine);
|
||||
|
||||
|
||||
connect(_renderControl, &QQuickRenderControl::renderRequested, this, [this] { _render = true; });
|
||||
connect(_renderControl, &QQuickRenderControl::sceneChanged, this, [this] { _render = _polish = true; });
|
||||
|
||||
if (!_canvas->makeCurrent()) {
|
||||
qWarning("Failed to make context current for QML Renderer");
|
||||
return;
|
||||
}
|
||||
_glData = ::getGLContextData();
|
||||
_renderControl->initialize(_canvas->getContext());
|
||||
|
||||
// When Quick says there is a need to render, we will not render immediately. Instead,
|
||||
|
@ -433,11 +492,6 @@ void OffscreenQmlSurface::create(QOpenGLContext* shareContext) {
|
|||
_updateTimer.setTimerType(Qt::PreciseTimer);
|
||||
_updateTimer.setInterval(MIN_TIMER_MS); // 5ms, Qt::PreciseTimer required
|
||||
_updateTimer.start();
|
||||
|
||||
auto rootContext = getRootContext();
|
||||
rootContext->setContextProperty("urlHandler", new UrlHandler());
|
||||
rootContext->setContextProperty("resourceDirectoryUrl", QUrl::fromLocalFile(PathUtils::resourcesPath()));
|
||||
rootContext->setContextProperty("pathToFonts", "../../");
|
||||
}
|
||||
|
||||
static uvec2 clampSize(const uvec2& size, uint32_t maxDimension) {
|
||||
|
@ -460,7 +514,7 @@ void OffscreenQmlSurface::resize(const QSize& newSize_, bool forceResize) {
|
|||
return;
|
||||
}
|
||||
|
||||
_qmlEngine->rootContext()->setContextProperty("surfaceSize", newSize);
|
||||
_qmlContext->setContextProperty("surfaceSize", newSize);
|
||||
|
||||
if (_rootItem) {
|
||||
_rootItem->setSize(newSize);
|
||||
|
@ -520,14 +574,19 @@ QQuickItem* OffscreenQmlSurface::getRootItem() {
|
|||
}
|
||||
|
||||
void OffscreenQmlSurface::setBaseUrl(const QUrl& baseUrl) {
|
||||
_qmlEngine->setBaseUrl(baseUrl);
|
||||
_qmlContext->setBaseUrl(baseUrl);
|
||||
}
|
||||
|
||||
QObject* OffscreenQmlSurface::load(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f) {
|
||||
// Synchronous loading may take a while; restart the deadlock timer
|
||||
QMetaObject::invokeMethod(qApp, "updateHeartbeat", Qt::DirectConnection);
|
||||
|
||||
_qmlComponent->loadUrl(qmlSource, QQmlComponent::PreferSynchronous);
|
||||
if ((qmlSource.isRelative() && !qmlSource.isEmpty()) || qmlSource.scheme() == QLatin1String("file")) {
|
||||
_qmlComponent->loadUrl(_qmlContext->resolvedUrl(qmlSource), QQmlComponent::PreferSynchronous);
|
||||
} else {
|
||||
_qmlComponent->loadUrl(qmlSource, QQmlComponent::PreferSynchronous);
|
||||
}
|
||||
|
||||
|
||||
if (_qmlComponent->isLoading()) {
|
||||
connect(_qmlComponent, &QQmlComponent::statusChanged, this,
|
||||
|
@ -541,10 +600,22 @@ QObject* OffscreenQmlSurface::load(const QUrl& qmlSource, std::function<void(QQm
|
|||
}
|
||||
|
||||
void OffscreenQmlSurface::clearCache() {
|
||||
getRootContext()->engine()->clearComponentCache();
|
||||
_qmlContext->engine()->clearComponentCache();
|
||||
}
|
||||
|
||||
QObject* OffscreenQmlSurface::finishQmlLoad(std::function<void(QQmlContext*, QObject*)> f) {
|
||||
#if 0
|
||||
if (!_rootItem) {
|
||||
QQmlComponent component(_qmlContext->engine());
|
||||
component.setData(R"QML(
|
||||
import QtQuick 2.0
|
||||
import QtWebChannel 1.0
|
||||
Item { Component.onCompleted: globalEventBridge.WebChannel.id = "globalEventBridge"; }
|
||||
)QML", QUrl());
|
||||
QObject *helper = component.create(_qmlContext);
|
||||
qDebug() << "Created helper";
|
||||
}
|
||||
#endif
|
||||
disconnect(_qmlComponent, &QQmlComponent::statusChanged, this, 0);
|
||||
if (_qmlComponent->isError()) {
|
||||
QList<QQmlError> errorList = _qmlComponent->errors();
|
||||
|
@ -554,21 +625,8 @@ QObject* OffscreenQmlSurface::finishQmlLoad(std::function<void(QQmlContext*, QOb
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// FIXME: Refactor with similar code in RenderableWebEntityItem
|
||||
QString javaScriptToInject;
|
||||
QFile webChannelFile(":qtwebchannel/qwebchannel.js");
|
||||
QFile createGlobalEventBridgeFile(PathUtils::resourcesPath() + "/html/createGlobalEventBridge.js");
|
||||
if (webChannelFile.open(QFile::ReadOnly | QFile::Text) &&
|
||||
createGlobalEventBridgeFile.open(QFile::ReadOnly | QFile::Text)) {
|
||||
QString webChannelStr = QTextStream(&webChannelFile).readAll();
|
||||
QString createGlobalEventBridgeStr = QTextStream(&createGlobalEventBridgeFile).readAll();
|
||||
javaScriptToInject = webChannelStr + createGlobalEventBridgeStr;
|
||||
} else {
|
||||
qCWarning(glLogging) << "Unable to find qwebchannel.js or createGlobalEventBridge.js";
|
||||
}
|
||||
|
||||
QQmlContext* newContext = new QQmlContext(_qmlEngine, qApp);
|
||||
QObject* newObject = _qmlComponent->beginCreate(newContext);
|
||||
QObject* newObject = _qmlComponent->beginCreate(_qmlContext);
|
||||
if (_qmlComponent->isError()) {
|
||||
QList<QQmlError> errorList = _qmlComponent->errors();
|
||||
foreach(const QQmlError& error, errorList)
|
||||
|
@ -579,12 +637,10 @@ QObject* OffscreenQmlSurface::finishQmlLoad(std::function<void(QQmlContext*, QOb
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
_qmlEngine->setObjectOwnership(this, QQmlEngine::CppOwnership);
|
||||
_qmlContext->engine()->setObjectOwnership(this, QQmlEngine::CppOwnership);
|
||||
newObject->setProperty("eventBridge", QVariant::fromValue(this));
|
||||
|
||||
newContext->setContextProperty("eventBridgeJavaScriptToInject", QVariant(javaScriptToInject));
|
||||
|
||||
f(newContext, newObject);
|
||||
f(_qmlContext, newObject);
|
||||
_qmlComponent->completeCreate();
|
||||
|
||||
|
||||
|
@ -735,7 +791,7 @@ bool OffscreenQmlSurface::eventFilter(QObject* originalDestination, QEvent* even
|
|||
mouseEvent->screenPos(), mouseEvent->button(),
|
||||
mouseEvent->buttons(), mouseEvent->modifiers());
|
||||
if (event->type() == QEvent::MouseMove) {
|
||||
_qmlEngine->rootContext()->setContextProperty("lastMousePosition", transformedPos);
|
||||
_qmlContext->setContextProperty("lastMousePosition", transformedPos);
|
||||
}
|
||||
mappedEvent.ignore();
|
||||
if (QCoreApplication::sendEvent(_quickWindow, &mappedEvent)) {
|
||||
|
@ -762,9 +818,6 @@ void OffscreenQmlSurface::resume() {
|
|||
if (getRootItem()) {
|
||||
getRootItem()->setProperty("eventBridge", QVariant::fromValue(this));
|
||||
}
|
||||
if (getRootContext()) {
|
||||
getRootContext()->setContextProperty("webEntity", this);
|
||||
}
|
||||
}
|
||||
|
||||
bool OffscreenQmlSurface::isPaused() const {
|
||||
|
@ -790,8 +843,8 @@ QSize OffscreenQmlSurface::size() const {
|
|||
return _quickWindow->geometry().size();
|
||||
}
|
||||
|
||||
QQmlContext* OffscreenQmlSurface::getRootContext() {
|
||||
return _qmlEngine->rootContext();
|
||||
QQmlContext* OffscreenQmlSurface::getSurfaceContext() {
|
||||
return _qmlContext;
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(std::function<void()>);
|
||||
|
|
|
@ -73,7 +73,7 @@ public:
|
|||
QQuickItem* getRootItem();
|
||||
QQuickWindow* getWindow();
|
||||
QObject* getEventHandler();
|
||||
QQmlContext* getRootContext();
|
||||
QQmlContext* getSurfaceContext();
|
||||
|
||||
QPointF mapToVirtualScreen(const QPointF& originalPoint, QObject* originalWidget);
|
||||
bool eventFilter(QObject* originalDestination, QEvent* event) override;
|
||||
|
@ -133,11 +133,10 @@ private slots:
|
|||
private:
|
||||
QQuickWindow* _quickWindow { nullptr };
|
||||
QMyQuickRenderControl* _renderControl{ nullptr };
|
||||
QQmlEngine* _qmlEngine { nullptr };
|
||||
QQmlContext* _qmlContext { nullptr };
|
||||
QQmlComponent* _qmlComponent { nullptr };
|
||||
QQuickItem* _rootItem { nullptr };
|
||||
OffscreenGLCanvas* _canvas { nullptr };
|
||||
QJsonObject _glData;
|
||||
|
||||
QTimer _updateTimer;
|
||||
uint32_t _fbo { 0 };
|
||||
|
|
|
@ -49,7 +49,6 @@ QSharedPointer<OffscreenQmlSurface> OffscreenQmlSurfaceCache::buildSurface(const
|
|||
surface->create(currentContext);
|
||||
surface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/"));
|
||||
surface->load(rootSource);
|
||||
surface->getRootContext()->setContextProperty("ApplicationInterface", qApp);
|
||||
surface->resize(QSize(100, 100));
|
||||
currentContext->makeCurrent(currentSurface);
|
||||
return surface;
|
||||
|
|
28
libraries/gpu/src/gpu/DrawTransformVertexPosition.slv
Normal file
28
libraries/gpu/src/gpu/DrawTransformVertexPosition.slv
Normal file
|
@ -0,0 +1,28 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// Draw and transform the fed vertex position with the standard MVP stack
|
||||
// Output the clip position
|
||||
//
|
||||
// Created by Sam Gateau on 5/30/2017
|
||||
// Copyright 2017 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 gpu/Transform.slh@>
|
||||
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
layout(location = 0) in vec4 inPosition;
|
||||
|
||||
out vec3 varWorldPos;
|
||||
|
||||
void main(void) {
|
||||
// standard transform
|
||||
TransformCamera cam = getTransformCamera();
|
||||
TransformObject obj = getTransformObject();
|
||||
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
|
||||
}
|
|
@ -2,25 +2,18 @@
|
|||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// hit_effect.vert
|
||||
// vertex shader
|
||||
// Draw the fed vertex position, pass straight as clip pos
|
||||
// Output the clip position
|
||||
//
|
||||
// Created by Eric Levin on 7/20/15.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
// Created by Sam Gateau on 5/30/2017
|
||||
// Copyright 2017 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 gpu/Inputs.slh@>
|
||||
|
||||
<@include gpu/Transform.slh@>
|
||||
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
out vec2 varQuadPosition;
|
||||
layout(location = 0) in vec4 inPosition;
|
||||
|
||||
void main(void) {
|
||||
varQuadPosition = inPosition.xy;
|
||||
gl_Position = inPosition;
|
||||
}
|
||||
}
|
|
@ -2,15 +2,17 @@
|
|||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// drawOpaqueStencil.frag
|
||||
// fragment shader
|
||||
// Draw white
|
||||
//
|
||||
// Created by Sam Gateau on 9/29/15.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
// Created by Sam Gateau on 5/30/2017
|
||||
// Copyright 2017 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
|
||||
//
|
||||
|
||||
out vec4 outFragColor;
|
||||
|
||||
void main(void) {
|
||||
outFragColor = vec4(1.0);
|
||||
}
|
|
@ -16,6 +16,12 @@
|
|||
#include "DrawTransformUnitQuad_vert.h"
|
||||
#include "DrawTexcoordRectTransformUnitQuad_vert.h"
|
||||
#include "DrawViewportQuadTransformTexcoord_vert.h"
|
||||
#include "DrawVertexPosition_vert.h"
|
||||
#include "DrawTransformVertexPosition_vert.h"
|
||||
|
||||
const char DrawNada_frag[] = "void main(void) {}"; // DrawNada is really simple...
|
||||
|
||||
#include "DrawWhite_frag.h"
|
||||
#include "DrawTexture_frag.h"
|
||||
#include "DrawTextureOpaque_frag.h"
|
||||
#include "DrawColoredTexture_frag.h"
|
||||
|
@ -26,6 +32,10 @@ ShaderPointer StandardShaderLib::_drawUnitQuadTexcoordVS;
|
|||
ShaderPointer StandardShaderLib::_drawTransformUnitQuadVS;
|
||||
ShaderPointer StandardShaderLib::_drawTexcoordRectTransformUnitQuadVS;
|
||||
ShaderPointer StandardShaderLib::_drawViewportQuadTransformTexcoordVS;
|
||||
ShaderPointer StandardShaderLib::_drawVertexPositionVS;
|
||||
ShaderPointer StandardShaderLib::_drawTransformVertexPositionVS;
|
||||
ShaderPointer StandardShaderLib::_drawNadaPS;
|
||||
ShaderPointer StandardShaderLib::_drawWhitePS;
|
||||
ShaderPointer StandardShaderLib::_drawTexturePS;
|
||||
ShaderPointer StandardShaderLib::_drawTextureOpaquePS;
|
||||
ShaderPointer StandardShaderLib::_drawColoredTexturePS;
|
||||
|
@ -85,6 +95,34 @@ ShaderPointer StandardShaderLib::getDrawViewportQuadTransformTexcoordVS() {
|
|||
return _drawViewportQuadTransformTexcoordVS;
|
||||
}
|
||||
|
||||
ShaderPointer StandardShaderLib::getDrawVertexPositionVS() {
|
||||
if (!_drawVertexPositionVS) {
|
||||
_drawVertexPositionVS = gpu::Shader::createVertex(std::string(DrawVertexPosition_vert));
|
||||
}
|
||||
return _drawVertexPositionVS;
|
||||
}
|
||||
|
||||
ShaderPointer StandardShaderLib::getDrawTransformVertexPositionVS() {
|
||||
if (!_drawTransformVertexPositionVS) {
|
||||
_drawTransformVertexPositionVS = gpu::Shader::createVertex(std::string(DrawTransformVertexPosition_vert));
|
||||
}
|
||||
return _drawTransformVertexPositionVS;
|
||||
}
|
||||
|
||||
ShaderPointer StandardShaderLib::getDrawNadaPS() {
|
||||
if (!_drawNadaPS) {
|
||||
_drawNadaPS = gpu::Shader::createPixel(std::string(DrawNada_frag));
|
||||
}
|
||||
return _drawNadaPS;
|
||||
}
|
||||
|
||||
ShaderPointer StandardShaderLib::getDrawWhitePS() {
|
||||
if (!_drawWhitePS) {
|
||||
_drawWhitePS = gpu::Shader::createPixel(std::string(DrawWhite_frag));
|
||||
}
|
||||
return _drawWhitePS;
|
||||
}
|
||||
|
||||
ShaderPointer StandardShaderLib::getDrawTexturePS() {
|
||||
if (!_drawTexturePS) {
|
||||
_drawTexturePS = gpu::Shader::createPixel(std::string(DrawTexture_frag));
|
||||
|
@ -99,8 +137,6 @@ ShaderPointer StandardShaderLib::getDrawTextureOpaquePS() {
|
|||
return _drawTextureOpaquePS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ShaderPointer StandardShaderLib::getDrawColoredTexturePS() {
|
||||
if (!_drawColoredTexturePS) {
|
||||
_drawColoredTexturePS = gpu::Shader::createPixel(std::string(DrawColoredTexture_frag));
|
||||
|
|
|
@ -37,6 +37,15 @@ public:
|
|||
// Shader draws the unit quad in the full viewport clipPos = ([(-1,-1),(1,1)]) and transform the texcoord = [(0,0),(1,1)] by the model transform.
|
||||
static ShaderPointer getDrawViewportQuadTransformTexcoordVS();
|
||||
|
||||
// Shader draw the fed vertex position and transform it by the full model transform stack (Model, View, Proj).
|
||||
// simply output the world pos and the clip pos to the next stage
|
||||
static ShaderPointer getDrawVertexPositionVS();
|
||||
static ShaderPointer getDrawTransformVertexPositionVS();
|
||||
|
||||
// PShader does nothing, no really nothing, but still needed for defining a program triggering rasterization
|
||||
static ShaderPointer getDrawNadaPS();
|
||||
|
||||
static ShaderPointer getDrawWhitePS();
|
||||
static ShaderPointer getDrawTexturePS();
|
||||
static ShaderPointer getDrawTextureOpaquePS();
|
||||
static ShaderPointer getDrawColoredTexturePS();
|
||||
|
@ -51,6 +60,12 @@ protected:
|
|||
static ShaderPointer _drawTransformUnitQuadVS;
|
||||
static ShaderPointer _drawTexcoordRectTransformUnitQuadVS;
|
||||
static ShaderPointer _drawViewportQuadTransformTexcoordVS;
|
||||
|
||||
static ShaderPointer _drawVertexPositionVS;
|
||||
static ShaderPointer _drawTransformVertexPositionVS;
|
||||
|
||||
static ShaderPointer _drawNadaPS;
|
||||
static ShaderPointer _drawWhitePS;
|
||||
static ShaderPointer _drawTexturePS;
|
||||
static ShaderPointer _drawTextureOpaquePS;
|
||||
static ShaderPointer _drawColoredTexturePS;
|
||||
|
|
|
@ -241,6 +241,42 @@ void Mesh::forEach(std::function<void(glm::vec3)> vertexFunc,
|
|||
}
|
||||
}
|
||||
|
||||
MeshPointer Mesh::createIndexedTriangles_P3F(uint32_t numVertices, uint32_t numIndices, const glm::vec3* vertices, const uint32_t* indices) {
|
||||
MeshPointer mesh;
|
||||
if (numVertices == 0) { return mesh; }
|
||||
if (numIndices < 3) { return mesh; }
|
||||
|
||||
mesh = std::make_shared<Mesh>();
|
||||
|
||||
// Vertex buffer
|
||||
mesh->setVertexBuffer(gpu::BufferView(new gpu::Buffer(numVertices * sizeof(glm::vec3), (gpu::Byte*) vertices), gpu::Element::VEC3F_XYZ));
|
||||
|
||||
// trim down the indices to shorts if possible
|
||||
if (numIndices < std::numeric_limits<uint16_t>::max()) {
|
||||
Indices16 shortIndicesVector;
|
||||
int16_t* shortIndices = nullptr;
|
||||
if (indices) {
|
||||
shortIndicesVector.resize(numIndices);
|
||||
for (uint32_t i = 0; i < numIndices; i++) {
|
||||
shortIndicesVector[i] = indices[i];
|
||||
}
|
||||
shortIndices = shortIndicesVector.data();
|
||||
}
|
||||
|
||||
mesh->setIndexBuffer(gpu::BufferView(new gpu::Buffer(numIndices * sizeof(uint16_t), (gpu::Byte*) shortIndices), gpu::Element::INDEX_UINT16));
|
||||
} else {
|
||||
|
||||
mesh->setIndexBuffer(gpu::BufferView(new gpu::Buffer(numIndices * sizeof(uint32_t), (gpu::Byte*) indices), gpu::Element::INDEX_INT32));
|
||||
}
|
||||
|
||||
|
||||
std::vector<model::Mesh::Part> parts;
|
||||
parts.push_back(model::Mesh::Part(0, numIndices, 0, model::Mesh::TRIANGLES));
|
||||
mesh->setPartBuffer(gpu::BufferView(new gpu::Buffer(parts.size() * sizeof(model::Mesh::Part), (gpu::Byte*) parts.data()), gpu::Element::PART_DRAWCALL));
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
|
||||
Geometry::Geometry() {
|
||||
}
|
||||
|
@ -256,3 +292,5 @@ Geometry::~Geometry() {
|
|||
void Geometry::setMesh(const MeshPointer& mesh) {
|
||||
_mesh = mesh;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -65,6 +65,9 @@ public:
|
|||
const gpu::BufferStream& getVertexStream() const { return _vertexStream; }
|
||||
|
||||
// Index Buffer
|
||||
using Indices16 = std::vector<int16_t>;
|
||||
using Indices32 = std::vector<int32_t>;
|
||||
|
||||
void setIndexBuffer(const BufferView& buffer);
|
||||
const BufferView& getIndexBuffer() const { return _indexBuffer; }
|
||||
size_t getNumIndices() const { return _indexBuffer.getNumElements(); }
|
||||
|
@ -127,6 +130,9 @@ public:
|
|||
std::function<void(glm::vec3)> normalFunc,
|
||||
std::function<void(uint32_t)> indexFunc);
|
||||
|
||||
|
||||
static MeshPointer createIndexedTriangles_P3F(uint32_t numVertices, uint32_t numTriangles, const glm::vec3* vertices = nullptr, const uint32_t* indices = nullptr);
|
||||
|
||||
protected:
|
||||
|
||||
gpu::Stream::FormatPointer _vertexFormat;
|
||||
|
|
|
@ -97,7 +97,7 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky
|
|||
}
|
||||
|
||||
auto skyState = std::make_shared<gpu::State>();
|
||||
skyState->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||
skyState->setStencilTest(true, 0xFF, gpu::State::StencilTest(1, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||
|
||||
thePipeline = gpu::Pipeline::create(skyShader, skyState);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
set(TARGET_NAME networking)
|
||||
setup_hifi_library(Network)
|
||||
setup_hifi_library(Network WebEngine)
|
||||
link_hifi_libraries(shared)
|
||||
|
||||
target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_BINARY_DIR}/includes")
|
||||
|
|
|
@ -15,11 +15,13 @@
|
|||
|
||||
#include <QtCore/QThread>
|
||||
|
||||
#include <StatTracker.h>
|
||||
#include <Trace.h>
|
||||
|
||||
#include "AssetClient.h"
|
||||
#include "NetworkLogging.h"
|
||||
#include "NodeList.h"
|
||||
#include "ResourceCache.h"
|
||||
#include <Trace.h>
|
||||
|
||||
static int requestID = 0;
|
||||
|
||||
|
@ -62,9 +64,12 @@ void AssetRequest::start() {
|
|||
_data = loadFromCache(getUrl());
|
||||
if (!_data.isNull()) {
|
||||
_error = NoError;
|
||||
|
||||
|
||||
_loadedFromCache = true;
|
||||
|
||||
_state = Finished;
|
||||
emit finished(this);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,8 @@ public:
|
|||
QUrl getUrl() const { return ::getATPUrl(_hash); }
|
||||
QString getHash() const { return _hash; }
|
||||
|
||||
bool loadedFromCache() const { return _loadedFromCache; }
|
||||
|
||||
signals:
|
||||
void finished(AssetRequest* thisRequest);
|
||||
void progress(qint64 totalReceived, qint64 total);
|
||||
|
@ -66,6 +68,7 @@ private:
|
|||
int _numPendingRequests { 0 };
|
||||
MessageID _assetRequestID { INVALID_MESSAGE_ID };
|
||||
const ByteRange _byteRange;
|
||||
bool _loadedFromCache { false };
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -13,12 +13,14 @@
|
|||
|
||||
#include <QtCore/QLoggingCategory>
|
||||
|
||||
#include <Trace.h>
|
||||
#include <Profile.h>
|
||||
#include <StatTracker.h>
|
||||
|
||||
#include "AssetClient.h"
|
||||
#include "AssetUtils.h"
|
||||
#include "MappingRequest.h"
|
||||
#include "NetworkLogging.h"
|
||||
#include <Trace.h>
|
||||
#include <Profile.h>
|
||||
|
||||
static const int DOWNLOAD_PROGRESS_LOG_INTERVAL_SECONDS = 5;
|
||||
|
||||
|
@ -48,6 +50,8 @@ bool AssetResourceRequest::urlIsAssetHash(const QUrl& url) {
|
|||
}
|
||||
|
||||
void AssetResourceRequest::doSend() {
|
||||
DependencyManager::get<StatTracker>()->incrementStat(STAT_ATP_REQUEST_STARTED);
|
||||
|
||||
// We'll either have a hash or an ATP path to a file (that maps to a hash)
|
||||
if (urlIsAssetHash(_url)) {
|
||||
// We've detected that this is a hash - simply use AssetClient to request that asset
|
||||
|
@ -65,11 +69,16 @@ void AssetResourceRequest::doSend() {
|
|||
}
|
||||
|
||||
void AssetResourceRequest::requestMappingForPath(const AssetPath& path) {
|
||||
auto statTracker = DependencyManager::get<StatTracker>();
|
||||
statTracker->incrementStat(STAT_ATP_MAPPING_REQUEST_STARTED);
|
||||
|
||||
auto assetClient = DependencyManager::get<AssetClient>();
|
||||
_assetMappingRequest = assetClient->createGetMappingRequest(path);
|
||||
|
||||
// make sure we'll hear about the result of the get mapping request
|
||||
connect(_assetMappingRequest, &GetMappingRequest::finished, this, [this, path](GetMappingRequest* request){
|
||||
auto statTracker = DependencyManager::get<StatTracker>();
|
||||
|
||||
Q_ASSERT(_state == InProgress);
|
||||
Q_ASSERT(request == _assetMappingRequest);
|
||||
|
||||
|
@ -80,6 +89,8 @@ void AssetResourceRequest::requestMappingForPath(const AssetPath& path) {
|
|||
|
||||
requestHash(request->getHash());
|
||||
|
||||
statTracker->incrementStat(STAT_ATP_MAPPING_REQUEST_SUCCESS);
|
||||
|
||||
break;
|
||||
default: {
|
||||
switch (request->getError()) {
|
||||
|
@ -100,6 +111,9 @@ void AssetResourceRequest::requestMappingForPath(const AssetPath& path) {
|
|||
_state = Finished;
|
||||
emit finished();
|
||||
|
||||
statTracker->incrementStat(STAT_ATP_MAPPING_REQUEST_FAILED);
|
||||
statTracker->incrementStat(STAT_ATP_REQUEST_FAILED);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -140,10 +154,26 @@ void AssetResourceRequest::requestHash(const AssetHash& hash) {
|
|||
_result = Error;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
auto statTracker = DependencyManager::get<StatTracker>();
|
||||
|
||||
if (_assetRequest->loadedFromCache()) {
|
||||
_loadedFromCache = true;
|
||||
}
|
||||
|
||||
_state = Finished;
|
||||
emit finished();
|
||||
|
||||
if (_result == Success) {
|
||||
statTracker->incrementStat(STAT_ATP_REQUEST_SUCCESS);
|
||||
|
||||
if (loadedFromCache()) {
|
||||
statTracker->incrementStat(STAT_ATP_REQUEST_CACHE);
|
||||
}
|
||||
} else {
|
||||
statTracker->incrementStat(STAT_ATP_REQUEST_FAILED);
|
||||
}
|
||||
|
||||
_assetRequest->deleteLater();
|
||||
_assetRequest = nullptr;
|
||||
});
|
||||
|
|
|
@ -15,7 +15,12 @@
|
|||
|
||||
#include <QFile>
|
||||
|
||||
#include <StatTracker.h>
|
||||
|
||||
void FileResourceRequest::doSend() {
|
||||
auto statTracker = DependencyManager::get<StatTracker>();
|
||||
statTracker->incrementStat(STAT_FILE_REQUEST_STARTED);
|
||||
|
||||
QString filename = _url.toLocalFile();
|
||||
|
||||
// sometimes on windows, we see the toLocalFile() return null,
|
||||
|
@ -60,4 +65,10 @@ void FileResourceRequest::doSend() {
|
|||
|
||||
_state = Finished;
|
||||
emit finished();
|
||||
|
||||
if (_result == ResourceRequest::Success) {
|
||||
statTracker->incrementStat(STAT_FILE_REQUEST_SUCCESS);
|
||||
} else {
|
||||
statTracker->incrementStat(STAT_FILE_REQUEST_FAILED);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ HFTabletWebEngineProfile::HFTabletWebEngineProfile(QObject* parent) : QQuickWebE
|
|||
static const QString WEB_ENGINE_USER_AGENT = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36";
|
||||
|
||||
setHttpUserAgent(WEB_ENGINE_USER_AGENT);
|
||||
setStorageName(QML_WEB_ENGINE_NAME);
|
||||
|
||||
auto requestInterceptor = new HFTabletWebEngineRequestInterceptor(this);
|
||||
setRequestInterceptor(requestInterceptor);
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
#include "HFTabletWebEngineRequestInterceptor.h"
|
||||
#include <QtCore/QDebug>
|
||||
#include <AccountManager.h>
|
||||
#include "AccountManager.h"
|
||||
|
||||
bool isTabletAuthableHighFidelityURL(const QUrl& url) {
|
||||
static const QStringList HF_HOSTS = {
|
|
@ -20,6 +20,7 @@ HFWebEngineProfile::HFWebEngineProfile(QObject* parent) :
|
|||
{
|
||||
static const QString WEB_ENGINE_USER_AGENT = "Chrome/48.0 (HighFidelityInterface)";
|
||||
setHttpUserAgent(WEB_ENGINE_USER_AGENT);
|
||||
setStorageName(QML_WEB_ENGINE_STORAGE_NAME);
|
||||
|
||||
// we use the HFWebEngineRequestInterceptor to make sure that web requests are authenticated for the interface user
|
||||
auto requestInterceptor = new HFWebEngineRequestInterceptor(this);
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#include <AccountManager.h>
|
||||
#include "AccountManager.h"
|
||||
#include "RequestFilters.h"
|
||||
|
||||
void HFWebEngineRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) {
|
|
@ -17,6 +17,7 @@
|
|||
#include <QMetaEnum>
|
||||
|
||||
#include <SharedUtil.h>
|
||||
#include <StatTracker.h>
|
||||
|
||||
#include "NetworkAccessManager.h"
|
||||
#include "NetworkLogging.h"
|
||||
|
@ -49,6 +50,8 @@ void HTTPResourceRequest::cleanupTimer() {
|
|||
}
|
||||
|
||||
void HTTPResourceRequest::doSend() {
|
||||
DependencyManager::get<StatTracker>()->incrementStat(STAT_HTTP_REQUEST_STARTED);
|
||||
|
||||
QNetworkRequest networkRequest(_url);
|
||||
networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
|
||||
|
@ -178,6 +181,17 @@ void HTTPResourceRequest::onRequestFinished() {
|
|||
|
||||
_state = Finished;
|
||||
emit finished();
|
||||
|
||||
auto statTracker = DependencyManager::get<StatTracker>();
|
||||
if (_result == Success) {
|
||||
statTracker->incrementStat(STAT_HTTP_REQUEST_SUCCESS);
|
||||
|
||||
if (loadedFromCache()) {
|
||||
statTracker->incrementStat(STAT_HTTP_REQUEST_CACHE);
|
||||
}
|
||||
} else {
|
||||
statTracker->incrementStat(STAT_HTTP_REQUEST_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPResourceRequest::onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) {
|
||||
|
@ -202,4 +216,6 @@ void HTTPResourceRequest::onTimeout() {
|
|||
_result = Timeout;
|
||||
_state = Finished;
|
||||
emit finished();
|
||||
|
||||
DependencyManager::get<StatTracker>()->incrementStat(STAT_HTTP_REQUEST_FAILED);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <NumericalConstants.h>
|
||||
#include <SettingHandle.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <StatTracker.h>
|
||||
#include <UUID.h>
|
||||
|
||||
#include "AccountManager.h"
|
||||
|
@ -37,7 +38,6 @@
|
|||
#include "HifiSockAddr.h"
|
||||
#include "NetworkLogging.h"
|
||||
#include "udt/Packet.h"
|
||||
#include <Trace.h>
|
||||
|
||||
static Setting::Handle<quint16> LIMITED_NODELIST_LOCAL_PORT("LimitedNodeList.LocalPort", 0);
|
||||
|
||||
|
@ -1044,10 +1044,10 @@ void LimitedNodeList::setLocalSocket(const HifiSockAddr& sockAddr) {
|
|||
qCInfo(networking) << "Local socket is" << sockAddr;
|
||||
} else {
|
||||
qCInfo(networking) << "Local socket has changed from" << _localSockAddr << "to" << sockAddr;
|
||||
DependencyManager::get<StatTracker>()->incrementStat(LOCAL_SOCKET_CHANGE_STAT);
|
||||
}
|
||||
|
||||
_localSockAddr = sockAddr;
|
||||
|
||||
emit localSockAddrChanged(_localSockAddr);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,6 +66,8 @@ const QHostAddress DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME = QHostAddress::Lo
|
|||
|
||||
const QString USERNAME_UUID_REPLACEMENT_STATS_KEY = "$username";
|
||||
|
||||
const QString LOCAL_SOCKET_CHANGE_STAT = "LocalSocketChanges";
|
||||
|
||||
using namespace tbb;
|
||||
typedef std::pair<QUuid, SharedNodePointer> UUIDNodePair;
|
||||
typedef concurrent_unordered_map<QUuid, SharedNodePointer, UUIDHasher> NodeHash;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#include <AccountManager.h>
|
||||
#include "AccountManager.h"
|
||||
|
||||
namespace {
|
||||
|
|
@ -19,6 +19,21 @@
|
|||
|
||||
#include "ByteRange.h"
|
||||
|
||||
const QString STAT_ATP_REQUEST_STARTED = "StartedATPRequest";
|
||||
const QString STAT_HTTP_REQUEST_STARTED = "StartedHTTPRequest";
|
||||
const QString STAT_FILE_REQUEST_STARTED = "StartedFileRequest";
|
||||
const QString STAT_ATP_REQUEST_SUCCESS = "SuccessfulATPRequest";
|
||||
const QString STAT_HTTP_REQUEST_SUCCESS = "SuccessfulHTTPRequest";
|
||||
const QString STAT_FILE_REQUEST_SUCCESS = "SuccessfulFileRequest";
|
||||
const QString STAT_ATP_REQUEST_FAILED = "FailedATPRequest";
|
||||
const QString STAT_HTTP_REQUEST_FAILED = "FailedHTTPRequest";
|
||||
const QString STAT_FILE_REQUEST_FAILED = "FailedFileRequest";
|
||||
const QString STAT_ATP_REQUEST_CACHE = "CacheATPRequest";
|
||||
const QString STAT_HTTP_REQUEST_CACHE = "CacheHTTPRequest";
|
||||
const QString STAT_ATP_MAPPING_REQUEST_STARTED = "StartedATPMappingRequest";
|
||||
const QString STAT_ATP_MAPPING_REQUEST_FAILED = "FailedATPMappingRequest";
|
||||
const QString STAT_ATP_MAPPING_REQUEST_SUCCESS = "SuccessfulATPMappingRequest";
|
||||
|
||||
class ResourceRequest : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
|
|
@ -200,6 +200,7 @@ public:
|
|||
virtual float newFramePresentRate() const { return -1.0f; }
|
||||
// Rate at which rendered frames are being skipped
|
||||
virtual float droppedFrameRate() const { return -1.0f; }
|
||||
virtual bool getSupportsAutoSwitch() { return false; }
|
||||
|
||||
// Hardware specific stats
|
||||
virtual QJsonObject getHardwareStats() const { return QJsonObject(); }
|
||||
|
|
|
@ -53,6 +53,18 @@ public:
|
|||
virtual bool isActive() {
|
||||
return _active;
|
||||
}
|
||||
virtual bool startStandBySession() {
|
||||
_sessionStatus = true;
|
||||
return _sessionStatus;
|
||||
}
|
||||
|
||||
virtual void endSession() {
|
||||
_sessionStatus = false;
|
||||
}
|
||||
|
||||
virtual bool isSessionActive() {
|
||||
return _sessionStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the application during it's idle phase. If the plugin needs to do
|
||||
|
@ -73,6 +85,7 @@ signals:
|
|||
|
||||
protected:
|
||||
bool _active { false };
|
||||
bool _sessionStatus { false };
|
||||
PluginContainer* _container { nullptr };
|
||||
static const char* UNKNOWN_PLUGIN_ID;
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ ProceduralSkybox::ProceduralSkybox() : model::Skybox() {
|
|||
_procedural._fragmentSource = skybox_frag;
|
||||
// Adjust the pipeline state for background using the stencil test
|
||||
_procedural.setDoesFade(false);
|
||||
_procedural._opaqueState->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||
_procedural._opaqueState->setStencilTest(true, 0xFF, gpu::State::StencilTest(1, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||
}
|
||||
|
||||
bool ProceduralSkybox::empty() {
|
||||
|
|
|
@ -260,7 +260,7 @@ static void addLink(const AnimPose& rootPose, const AnimPose& pose, const AnimPo
|
|||
// there is room, so lets draw a nice bone
|
||||
|
||||
glm::vec3 uAxis, vAxis, wAxis;
|
||||
generateBasisVectors(boneAxis0, glm::vec3(1, 0, 0), uAxis, vAxis, wAxis);
|
||||
generateBasisVectors(boneAxis0, glm::vec3(1.0f, 0.0f, 0.0f), uAxis, vAxis, wAxis);
|
||||
|
||||
glm::vec3 boneBaseCorners[NUM_BASE_CORNERS];
|
||||
boneBaseCorners[0] = pose0 * ((uAxis * radius) + (vAxis * radius) + (wAxis * radius));
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <gpu/Context.h>
|
||||
|
||||
#include "AntialiasingEffect.h"
|
||||
#include "StencilMaskPass.h"
|
||||
#include "TextureCache.h"
|
||||
#include "FramebufferCache.h"
|
||||
#include "DependencyManager.h"
|
||||
|
@ -70,6 +71,8 @@ const gpu::PipelinePointer& Antialiasing::getAntialiasingPipeline() {
|
|||
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
|
||||
PrepareStencil::testMask(*state);
|
||||
|
||||
state->setDepthTest(false, false, gpu::LESS_EQUAL);
|
||||
|
||||
// Good to go add the brand new pipeline
|
||||
|
@ -93,6 +96,7 @@ const gpu::PipelinePointer& Antialiasing::getBlendPipeline() {
|
|||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
|
||||
state->setDepthTest(false, false, gpu::LESS_EQUAL);
|
||||
PrepareStencil::testMask(*state);
|
||||
|
||||
// Good to go add the brand new pipeline
|
||||
_blendPipeline = gpu::Pipeline::create(program, state);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <gpu/Batch.h>
|
||||
#include <gpu/Context.h>
|
||||
|
||||
#include "StencilMaskPass.h"
|
||||
#include "AbstractViewStateInterface.h"
|
||||
#include "GeometryCache.h"
|
||||
#include "TextureCache.h"
|
||||
|
@ -27,18 +28,15 @@
|
|||
#include "deferred_light_point_vert.h"
|
||||
#include "deferred_light_spot_vert.h"
|
||||
|
||||
#include "directional_light_frag.h"
|
||||
#include "directional_ambient_light_frag.h"
|
||||
#include "directional_skybox_light_frag.h"
|
||||
|
||||
#include "directional_light_shadow_frag.h"
|
||||
#include "directional_ambient_light_shadow_frag.h"
|
||||
#include "directional_skybox_light_shadow_frag.h"
|
||||
|
||||
#include "local_lights_shading_frag.h"
|
||||
#include "local_lights_drawOutline_frag.h"
|
||||
#include "point_light_frag.h"
|
||||
#include "spot_light_frag.h"
|
||||
|
||||
|
||||
using namespace render;
|
||||
|
||||
|
@ -82,48 +80,26 @@ enum DeferredShader_BufferSlot {
|
|||
};
|
||||
|
||||
static void loadLightProgram(const char* vertSource, const char* fragSource, bool lightVolume, gpu::PipelinePointer& program, LightLocationsPtr& locations);
|
||||
static void loadLightVolumeProgram(const char* vertSource, const char* fragSource, bool front, gpu::PipelinePointer& program, LightLocationsPtr& locations);
|
||||
|
||||
const char no_light_frag[] =
|
||||
R"SCRIBE(
|
||||
out vec4 _fragColor;
|
||||
|
||||
void main(void) {
|
||||
_fragColor = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
}
|
||||
)SCRIBE"
|
||||
;
|
||||
|
||||
void DeferredLightingEffect::init() {
|
||||
_directionalLightLocations = std::make_shared<LightLocations>();
|
||||
_directionalAmbientSphereLightLocations = std::make_shared<LightLocations>();
|
||||
_directionalSkyboxLightLocations = std::make_shared<LightLocations>();
|
||||
|
||||
_directionalLightShadowLocations = std::make_shared<LightLocations>();
|
||||
_directionalAmbientSphereLightShadowLocations = std::make_shared<LightLocations>();
|
||||
_directionalSkyboxLightShadowLocations = std::make_shared<LightLocations>();
|
||||
|
||||
_localLightLocations = std::make_shared<LightLocations>();
|
||||
_localLightOutlineLocations = std::make_shared<LightLocations>();
|
||||
_pointLightLocations = std::make_shared<LightLocations>();
|
||||
_spotLightLocations = std::make_shared<LightLocations>();
|
||||
|
||||
loadLightProgram(deferred_light_vert, directional_light_frag, false, _directionalLight, _directionalLightLocations);
|
||||
loadLightProgram(deferred_light_vert, directional_ambient_light_frag, false, _directionalAmbientSphereLight, _directionalAmbientSphereLightLocations);
|
||||
loadLightProgram(deferred_light_vert, directional_skybox_light_frag, false, _directionalSkyboxLight, _directionalSkyboxLightLocations);
|
||||
|
||||
loadLightProgram(deferred_light_vert, directional_light_shadow_frag, false, _directionalLightShadow, _directionalLightShadowLocations);
|
||||
loadLightProgram(deferred_light_vert, directional_ambient_light_shadow_frag, false, _directionalAmbientSphereLightShadow, _directionalAmbientSphereLightShadowLocations);
|
||||
loadLightProgram(deferred_light_vert, directional_skybox_light_shadow_frag, false, _directionalSkyboxLightShadow, _directionalSkyboxLightShadowLocations);
|
||||
|
||||
loadLightProgram(deferred_light_vert, local_lights_shading_frag, true, _localLight, _localLightLocations);
|
||||
loadLightProgram(deferred_light_vert, local_lights_drawOutline_frag, true, _localLightOutline, _localLightOutlineLocations);
|
||||
|
||||
loadLightVolumeProgram(deferred_light_point_vert, no_light_frag, false, _pointLightBack, _pointLightLocations);
|
||||
loadLightVolumeProgram(deferred_light_point_vert, no_light_frag, true, _pointLightFront, _pointLightLocations);
|
||||
loadLightVolumeProgram(deferred_light_spot_vert, no_light_frag, false, _spotLightBack, _spotLightLocations);
|
||||
loadLightVolumeProgram(deferred_light_spot_vert, no_light_frag, true, _spotLightFront, _spotLightLocations);
|
||||
|
||||
// Light Stage and clusters
|
||||
_lightStage = std::make_shared<LightStage>();
|
||||
|
||||
|
@ -160,11 +136,11 @@ void DeferredLightingEffect::init() {
|
|||
|
||||
|
||||
lp->setAmbientIntensity(0.5f);
|
||||
lp->setAmbientMap(_defaultSkyboxAmbientTexture);
|
||||
auto irradianceSH = _defaultSkyboxAmbientTexture->getIrradiance();
|
||||
if (irradianceSH) {
|
||||
lp->setAmbientSphere((*irradianceSH));
|
||||
}
|
||||
lp->setAmbientMap(_defaultSkyboxAmbientTexture);
|
||||
auto irradianceSH = _defaultSkyboxAmbientTexture->getIrradiance();
|
||||
if (irradianceSH) {
|
||||
lp->setAmbientSphere((*irradianceSH));
|
||||
}
|
||||
}
|
||||
|
||||
void DeferredLightingEffect::setupKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit) {
|
||||
|
@ -267,7 +243,7 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo
|
|||
state->setColorWriteMask(true, true, true, false);
|
||||
|
||||
if (lightVolume) {
|
||||
state->setStencilTest(true, 0x00, gpu::State::StencilTest(1, 0xFF, gpu::LESS_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||
PrepareStencil::testShape(*state);
|
||||
|
||||
state->setCullMode(gpu::State::CULL_BACK);
|
||||
// state->setCullMode(gpu::State::CULL_FRONT);
|
||||
|
@ -280,7 +256,7 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo
|
|||
|
||||
} else {
|
||||
// Stencil test all the light passes for objects pixels only, not the background
|
||||
state->setStencilTest(true, 0x00, gpu::State::StencilTest(0, 0x01, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||
PrepareStencil::testShape(*state);
|
||||
|
||||
state->setCullMode(gpu::State::CULL_BACK);
|
||||
// additive blending
|
||||
|
@ -290,39 +266,6 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo
|
|||
|
||||
}
|
||||
|
||||
|
||||
static void loadLightVolumeProgram(const char* vertSource, const char* fragSource, bool front, gpu::PipelinePointer& pipeline, LightLocationsPtr& locations) {
|
||||
gpu::ShaderPointer program = makeLightProgram(vertSource, fragSource, locations);
|
||||
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
|
||||
// Stencil test all the light passes for objects pixels only, not the background
|
||||
|
||||
if (front) {
|
||||
state->setCullMode(gpu::State::CULL_BACK);
|
||||
state->setDepthTest(true, false, gpu::LESS_EQUAL);
|
||||
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_DECR, gpu::State::STENCIL_OP_KEEP));
|
||||
|
||||
// state->setDepthClampEnable(true);
|
||||
// TODO: We should use DepthClamp and avoid changing geometry for inside /outside cases
|
||||
// additive blending
|
||||
// state->setBlendFunction(true, gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
|
||||
//state->setColorWriteMask(true, true, true, false);
|
||||
state->setColorWriteMask(false, false, false, false);
|
||||
} else {
|
||||
state->setCullMode(gpu::State::CULL_FRONT);
|
||||
state->setDepthTest(true, false, gpu::LESS_EQUAL);
|
||||
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_INCR, gpu::State::STENCIL_OP_KEEP));
|
||||
// additive blending
|
||||
// state->setBlendFunction(true, gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
// state->setColorWriteMask(true, true, true, false);
|
||||
state->setColorWriteMask(false, false, false, false);
|
||||
}
|
||||
pipeline = gpu::Pipeline::create(program, state);
|
||||
|
||||
}
|
||||
|
||||
void DeferredLightingEffect::setGlobalLight(const model::LightPointer& light) {
|
||||
/* auto globalLight = _allocatedLights.front();
|
||||
globalLight->setDirection(light->getDirection());
|
||||
|
@ -535,7 +478,7 @@ void PrepareDeferred::run(const RenderContextPointer& renderContext, const Input
|
|||
gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_COLOR1 | gpu::Framebuffer::BUFFER_COLOR2 | gpu::Framebuffer::BUFFER_COLOR3 |
|
||||
gpu::Framebuffer::BUFFER_DEPTH |
|
||||
gpu::Framebuffer::BUFFER_STENCIL,
|
||||
vec4(vec3(0), 0), 1.0, 0.0, true);
|
||||
vec4(vec3(0), 0), 1.0, 1, true);
|
||||
|
||||
// For the rest of the rendering, bind the lighting model
|
||||
batch.setUniformBuffer(LIGHTING_MODEL_BUFFER_SLOT, lightingModel->getParametersBuffer());
|
||||
|
@ -619,8 +562,8 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
|
|||
batch.setResourceTexture(SHADOW_MAP_UNIT, globalShadow->map);
|
||||
}
|
||||
|
||||
auto& program = deferredLightingEffect->_shadowMapEnabled ? deferredLightingEffect->_directionalLightShadow : deferredLightingEffect->_directionalLight;
|
||||
LightLocationsPtr locations = deferredLightingEffect->_shadowMapEnabled ? deferredLightingEffect->_directionalLightShadowLocations : deferredLightingEffect->_directionalLightLocations;
|
||||
auto& program = deferredLightingEffect->_directionalSkyboxLight;
|
||||
LightLocationsPtr locations = deferredLightingEffect->_directionalSkyboxLightLocations;
|
||||
const auto& keyLight = deferredLightingEffect->_allocatedLights[deferredLightingEffect->_globalLights.front()];
|
||||
|
||||
// Setup the global directional pass pipeline
|
||||
|
|
|
@ -82,32 +82,21 @@ private:
|
|||
|
||||
gpu::PipelinePointer _directionalSkyboxLight;
|
||||
gpu::PipelinePointer _directionalAmbientSphereLight;
|
||||
gpu::PipelinePointer _directionalLight;
|
||||
|
||||
gpu::PipelinePointer _directionalSkyboxLightShadow;
|
||||
gpu::PipelinePointer _directionalAmbientSphereLightShadow;
|
||||
gpu::PipelinePointer _directionalLightShadow;
|
||||
|
||||
gpu::PipelinePointer _localLight;
|
||||
gpu::PipelinePointer _localLightOutline;
|
||||
|
||||
gpu::PipelinePointer _pointLightBack;
|
||||
gpu::PipelinePointer _pointLightFront;
|
||||
gpu::PipelinePointer _spotLightBack;
|
||||
gpu::PipelinePointer _spotLightFront;
|
||||
|
||||
LightLocationsPtr _directionalSkyboxLightLocations;
|
||||
LightLocationsPtr _directionalAmbientSphereLightLocations;
|
||||
LightLocationsPtr _directionalLightLocations;
|
||||
|
||||
LightLocationsPtr _directionalSkyboxLightShadowLocations;
|
||||
LightLocationsPtr _directionalAmbientSphereLightShadowLocations;
|
||||
LightLocationsPtr _directionalLightShadowLocations;
|
||||
|
||||
LightLocationsPtr _localLightLocations;
|
||||
LightLocationsPtr _localLightOutlineLocations;
|
||||
LightLocationsPtr _pointLightLocations;
|
||||
LightLocationsPtr _spotLightLocations;
|
||||
|
||||
using Lights = std::vector<model::LightPointer>;
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "TextureCache.h"
|
||||
#include "RenderUtilsLogging.h"
|
||||
#include "StencilMaskPass.h"
|
||||
|
||||
#include "gpu/StandardShaderLib.h"
|
||||
|
||||
|
@ -1610,6 +1611,9 @@ void GeometryCache::renderGlowLine(gpu::Batch& batch, const glm::vec3& p1, const
|
|||
state->setBlendFunction(true,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
|
||||
PrepareStencil::testMask(*state);
|
||||
|
||||
gpu::Shader::BindingSet slotBindings;
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("lineData"), LINE_DATA_SLOT));
|
||||
gpu::Shader::makeProgram(*program, slotBindings);
|
||||
|
@ -1663,11 +1667,14 @@ void GeometryCache::useSimpleDrawPipeline(gpu::Batch& batch, bool noBlend) {
|
|||
|
||||
// enable decal blend
|
||||
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
|
||||
PrepareStencil::testMask(*state);
|
||||
|
||||
_standardDrawPipeline = gpu::Pipeline::create(program, state);
|
||||
|
||||
|
||||
auto stateNoBlend = std::make_shared<gpu::State>();
|
||||
PrepareStencil::testMaskDrawShape(*state);
|
||||
|
||||
auto noBlendPS = gpu::StandardShaderLib::getDrawTextureOpaquePS();
|
||||
auto programNoBlend = gpu::Shader::createProgram(vs, noBlendPS);
|
||||
gpu::Shader::makeProgram((*programNoBlend));
|
||||
|
@ -1690,12 +1697,14 @@ void GeometryCache::useGridPipeline(gpu::Batch& batch, GridBuffer gridBuffer, bo
|
|||
|
||||
auto stateLayered = std::make_shared<gpu::State>();
|
||||
stateLayered->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
|
||||
PrepareStencil::testMask(*stateLayered);
|
||||
_gridPipelineLayered = gpu::Pipeline::create(program, stateLayered);
|
||||
|
||||
auto state = std::make_shared<gpu::State>(stateLayered->getValues());
|
||||
const float DEPTH_BIAS = 0.001f;
|
||||
state->setDepthBias(DEPTH_BIAS);
|
||||
state->setDepthTest(true, false, gpu::LESS_EQUAL);
|
||||
PrepareStencil::testMaskDrawShape(*state);
|
||||
_gridPipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
|
||||
|
@ -1773,6 +1782,11 @@ static void buildWebShader(const std::string& vertShaderText, const std::string&
|
|||
state->setBlendFunction(blendEnable,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
if (blendEnable) {
|
||||
PrepareStencil::testMask(*state);
|
||||
} else {
|
||||
PrepareStencil::testMaskDrawShape(*state);
|
||||
}
|
||||
|
||||
pipelinePointerOut = gpu::Pipeline::create(shaderPointerOut, state);
|
||||
}
|
||||
|
@ -1858,6 +1872,12 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp
|
|||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
|
||||
if (config.isTransparent()) {
|
||||
PrepareStencil::testMask(*state);
|
||||
} else {
|
||||
PrepareStencil::testMaskDrawShape(*state);
|
||||
}
|
||||
|
||||
gpu::ShaderPointer program = (config.isUnlit()) ? _unlitShader : _simpleShader;
|
||||
gpu::PipelinePointer pipeline = gpu::Pipeline::create(program, state);
|
||||
_simplePrograms.insert(config, pipeline);
|
||||
|
|
|
@ -1,94 +0,0 @@
|
|||
//
|
||||
// HitEffect.cpp
|
||||
// interface/src/renderer
|
||||
//
|
||||
// Created by Andrzej Kapolka on 7/14/13.
|
||||
// Copyright 2013 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 this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL
|
||||
|
||||
|
||||
#include <glm/gtc/random.hpp>
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include <PathUtils.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "AbstractViewStateInterface.h"
|
||||
#include "HitEffect.h"
|
||||
|
||||
#include "TextureCache.h"
|
||||
#include "DependencyManager.h"
|
||||
#include "ViewFrustum.h"
|
||||
#include "GeometryCache.h"
|
||||
|
||||
#include <gpu/Context.h>
|
||||
|
||||
#include "hit_effect_vert.h"
|
||||
#include "hit_effect_frag.h"
|
||||
|
||||
|
||||
HitEffect::HitEffect() {
|
||||
_geometryId = DependencyManager::get<GeometryCache>()->allocateID();
|
||||
}
|
||||
|
||||
HitEffect::~HitEffect() {
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
if (_geometryId && geometryCache) {
|
||||
geometryCache->releaseID(_geometryId);
|
||||
}
|
||||
}
|
||||
|
||||
const gpu::PipelinePointer& HitEffect::getHitEffectPipeline() {
|
||||
if (!_hitEffectPipeline) {
|
||||
auto vs = gpu::Shader::createVertex(std::string(hit_effect_vert));
|
||||
auto ps = gpu::Shader::createPixel(std::string(hit_effect_frag));
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
||||
|
||||
|
||||
gpu::Shader::BindingSet slotBindings;
|
||||
gpu::Shader::makeProgram(*program, slotBindings);
|
||||
|
||||
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
|
||||
state->setDepthTest(false, false, gpu::LESS_EQUAL);
|
||||
|
||||
// Blend on transparent
|
||||
state->setBlendFunction(true,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
|
||||
|
||||
// Good to go add the brand new pipeline
|
||||
_hitEffectPipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
return _hitEffectPipeline;
|
||||
}
|
||||
|
||||
void HitEffect::run(const render::RenderContextPointer& renderContext) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
||||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->getViewFrustum().evalProjectionMatrix(projMat);
|
||||
args->getViewFrustum().evalViewTransform(viewMat);
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
batch.setModelTransform(Transform());
|
||||
|
||||
batch.setPipeline(getHitEffectPipeline());
|
||||
|
||||
static const glm::vec4 color(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
static const glm::vec2 bottomLeft(-1.0f, -1.0f);
|
||||
static const glm::vec2 topRight(1.0f, 1.0f);
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(batch, bottomLeft, topRight, color, _geometryId);
|
||||
});
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
//
|
||||
// hitEffect.h
|
||||
// hifi
|
||||
//
|
||||
// Created by eric levin on 7/17/15.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef hifi_hitEffect_h
|
||||
#define hifi_hitEffect_h
|
||||
|
||||
#include <render/DrawTask.h>
|
||||
|
||||
class HitEffectConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool enabled MEMBER enabled)
|
||||
public:
|
||||
HitEffectConfig() : render::Job::Config(false) {}
|
||||
};
|
||||
|
||||
class HitEffect {
|
||||
public:
|
||||
using Config = HitEffectConfig;
|
||||
using JobModel = render::Job::Model<HitEffect, Config>;
|
||||
|
||||
HitEffect();
|
||||
~HitEffect();
|
||||
void configure(const Config& config) {}
|
||||
void run(const render::RenderContextPointer& renderContext);
|
||||
|
||||
const gpu::PipelinePointer& getHitEffectPipeline();
|
||||
|
||||
private:
|
||||
int _geometryId { 0 };
|
||||
gpu::PipelinePointer _hitEffectPipeline;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
#include <gpu/StandardShaderLib.h>
|
||||
|
||||
#include "StencilMaskPass.h"
|
||||
|
||||
#include "lightClusters_drawGrid_vert.h"
|
||||
#include "lightClusters_drawGrid_frag.h"
|
||||
|
||||
|
|
|
@ -27,12 +27,12 @@
|
|||
#include <render/BlurTask.h>
|
||||
|
||||
#include "LightingModel.h"
|
||||
#include "StencilMaskPass.h"
|
||||
#include "DebugDeferredBuffer.h"
|
||||
#include "DeferredFramebuffer.h"
|
||||
#include "DeferredLightingEffect.h"
|
||||
#include "SurfaceGeometryPass.h"
|
||||
#include "FramebufferCache.h"
|
||||
#include "HitEffect.h"
|
||||
#include "TextureCache.h"
|
||||
#include "ZoneRenderer.h"
|
||||
|
||||
|
@ -43,8 +43,6 @@
|
|||
|
||||
#include <gpu/StandardShaderLib.h>
|
||||
|
||||
#include "drawOpaqueStencil_frag.h"
|
||||
|
||||
|
||||
using namespace render;
|
||||
extern void initOverlay3DPipelines(render::ShapePlumber& plumber);
|
||||
|
@ -85,13 +83,13 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
const auto deferredFramebuffer = prepareDeferredOutputs.getN<PrepareDeferred::Outputs>(0);
|
||||
const auto lightingFramebuffer = prepareDeferredOutputs.getN<PrepareDeferred::Outputs>(1);
|
||||
|
||||
// draw a stencil mask in hidden regions of the framebuffer.
|
||||
task.addJob<PrepareStencil>("PrepareStencil", primaryFramebuffer);
|
||||
|
||||
// Render opaque objects in DeferredBuffer
|
||||
const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel).hasVarying();
|
||||
task.addJob<DrawStateSortDeferred>("DrawOpaqueDeferred", opaqueInputs, shapePlumber);
|
||||
|
||||
// Once opaque is all rendered create stencil background
|
||||
task.addJob<DrawStencilDeferred>("DrawOpaqueStencil", deferredFramebuffer);
|
||||
|
||||
task.addJob<EndGPURangeTimer>("OpaqueRangeTimer", opaqueRangeTimer);
|
||||
|
||||
|
||||
|
@ -387,88 +385,6 @@ void DrawOverlay3D::run(const RenderContextPointer& renderContext, const Inputs&
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
gpu::PipelinePointer DrawStencilDeferred::getOpaquePipeline() {
|
||||
if (!_opaquePipeline) {
|
||||
const gpu::int8 STENCIL_OPAQUE = 1;
|
||||
auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS();
|
||||
auto ps = gpu::Shader::createPixel(std::string(drawOpaqueStencil_frag));
|
||||
auto program = gpu::Shader::createProgram(vs, ps);
|
||||
gpu::Shader::makeProgram((*program));
|
||||
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
state->setDepthTest(true, false, gpu::LESS_EQUAL);
|
||||
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(STENCIL_OPAQUE, 0xFF, gpu::ALWAYS, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_KEEP));
|
||||
state->setColorWriteMask(0);
|
||||
|
||||
_opaquePipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
return _opaquePipeline;
|
||||
}
|
||||
|
||||
void DrawStencilDeferred::run(const RenderContextPointer& renderContext, const DeferredFramebufferPointer& deferredFramebuffer) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
|
||||
// from the touched pixel generate the stencil buffer
|
||||
RenderArgs* args = renderContext->args;
|
||||
doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||
args->_batch = &batch;
|
||||
|
||||
auto deferredFboColorDepthStencil = deferredFramebuffer->getDeferredFramebufferDepthColor();
|
||||
|
||||
|
||||
batch.enableStereo(false);
|
||||
|
||||
batch.setFramebuffer(deferredFboColorDepthStencil);
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
batch.setStateScissorRect(args->_viewport);
|
||||
|
||||
batch.setPipeline(getOpaquePipeline());
|
||||
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
batch.setResourceTexture(0, nullptr);
|
||||
|
||||
});
|
||||
args->_batch = nullptr;
|
||||
}
|
||||
|
||||
void DrawBackgroundDeferred::run(const RenderContextPointer& renderContext, const Inputs& inputs) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
|
||||
const auto& inItems = inputs.get0();
|
||||
const auto& lightingModel = inputs.get1();
|
||||
if (!lightingModel->isBackgroundEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
RenderArgs* args = renderContext->args;
|
||||
doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||
args->_batch = &batch;
|
||||
// _gpuTimer.begin(batch);
|
||||
|
||||
batch.enableSkybox(true);
|
||||
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
batch.setStateScissorRect(args->_viewport);
|
||||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->getViewFrustum().evalProjectionMatrix(projMat);
|
||||
args->getViewFrustum().evalViewTransform(viewMat);
|
||||
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
|
||||
renderItems(renderContext, inItems);
|
||||
// _gpuTimer.end(batch);
|
||||
});
|
||||
args->_batch = nullptr;
|
||||
|
||||
// std::static_pointer_cast<Config>(renderContext->jobConfig)->gpuTime = _gpuTimer.getAverage();
|
||||
}
|
||||
|
||||
void Blit::run(const RenderContextPointer& renderContext, const gpu::FramebufferPointer& srcFramebuffer) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_context);
|
||||
|
@ -538,3 +454,4 @@ void Blit::run(const RenderContextPointer& renderContext, const gpu::Framebuffer
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -120,35 +120,6 @@ protected:
|
|||
bool _stateSort;
|
||||
};
|
||||
|
||||
class DeferredFramebuffer;
|
||||
class DrawStencilDeferred {
|
||||
public:
|
||||
using JobModel = render::Job::ModelI<DrawStencilDeferred, std::shared_ptr<DeferredFramebuffer>>;
|
||||
|
||||
void run(const render::RenderContextPointer& renderContext, const std::shared_ptr<DeferredFramebuffer>& deferredFramebuffer);
|
||||
|
||||
protected:
|
||||
gpu::PipelinePointer _opaquePipeline;
|
||||
|
||||
gpu::PipelinePointer getOpaquePipeline();
|
||||
};
|
||||
|
||||
using DrawBackgroundDeferredConfig = render::GPUJobConfig;
|
||||
|
||||
class DrawBackgroundDeferred {
|
||||
public:
|
||||
using Inputs = render::VaryingSet2 <render::ItemBounds, LightingModelPointer>;
|
||||
|
||||
using Config = DrawBackgroundDeferredConfig;
|
||||
using JobModel = render::Job::ModelI<DrawBackgroundDeferred, Inputs, Config>;
|
||||
|
||||
void configure(const Config& config) {}
|
||||
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs);
|
||||
|
||||
protected:
|
||||
gpu::RangeTimerPointer _gpuTimer;
|
||||
};
|
||||
|
||||
class DrawOverlay3DConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged)
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <gpu/Context.h>
|
||||
#include <gpu/StandardShaderLib.h>
|
||||
|
||||
#include "StencilMaskPass.h"
|
||||
#include "DeferredLightingEffect.h"
|
||||
#include "TextureCache.h"
|
||||
#include "render/DrawTask.h"
|
||||
|
@ -330,6 +331,7 @@ void addPlumberPipeline(ShapePlumber& plumber,
|
|||
bool isWireframed = (i & 4);
|
||||
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
PrepareStencil::testMaskDrawShape(*state);
|
||||
|
||||
// Depth test depends on transparency
|
||||
state->setDepthTest(true, !key.isTranslucent(), gpu::LESS_EQUAL);
|
||||
|
|
126
libraries/render-utils/src/StencilMaskPass.cpp
Normal file
126
libraries/render-utils/src/StencilMaskPass.cpp
Normal file
|
@ -0,0 +1,126 @@
|
|||
//
|
||||
// StencilMaskPass.cpp
|
||||
// render-utils/src/
|
||||
//
|
||||
// Created by Sam Gateau on 5/31/17.
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "StencilMaskPass.h"
|
||||
|
||||
#include <RenderArgs.h>
|
||||
#include <ViewFrustum.h>
|
||||
#include <gpu/Context.h>
|
||||
|
||||
|
||||
#include <gpu/StandardShaderLib.h>
|
||||
|
||||
#include "stencil_drawMask_frag.h"
|
||||
|
||||
using namespace render;
|
||||
|
||||
void PrepareStencil::configure(const Config& config) {
|
||||
_maskMode = config.maskMode;
|
||||
_forceDraw = config.forceDraw;
|
||||
}
|
||||
|
||||
model::MeshPointer PrepareStencil::getMesh() {
|
||||
if (!_mesh) {
|
||||
|
||||
std::vector<glm::vec3> vertices {
|
||||
{ -1.0f, -1.0f, 0.0f }, { -1.0f, 0.0f, 0.0f },
|
||||
{ -1.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f },
|
||||
{ 1.0f, 1.0f, 0.0f }, { 1.0f, 0.0f, 0.0f },
|
||||
{ 1.0f, -1.0f, 0.0f }, { 0.0f, -1.0f, 0.0f } };
|
||||
|
||||
std::vector<uint32_t> indices { 0, 7, 1, 1, 3, 2, 3, 5, 4, 5, 7, 6 };
|
||||
_mesh = model::Mesh::createIndexedTriangles_P3F((uint32_t) vertices.size(), (uint32_t) indices.size(), vertices.data(), indices.data());
|
||||
}
|
||||
return _mesh;
|
||||
}
|
||||
|
||||
gpu::PipelinePointer PrepareStencil::getMeshStencilPipeline() {
|
||||
if (!_meshStencilPipeline) {
|
||||
auto vs = gpu::StandardShaderLib::getDrawVertexPositionVS();
|
||||
auto ps = gpu::StandardShaderLib::getDrawNadaPS();
|
||||
auto program = gpu::Shader::createProgram(vs, ps);
|
||||
gpu::Shader::makeProgram((*program));
|
||||
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
drawMask(*state);
|
||||
state->setColorWriteMask(0);
|
||||
|
||||
_meshStencilPipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
return _meshStencilPipeline;
|
||||
}
|
||||
|
||||
gpu::PipelinePointer PrepareStencil::getPaintStencilPipeline() {
|
||||
if (!_paintStencilPipeline) {
|
||||
auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS();
|
||||
auto ps = gpu::Shader::createPixel(std::string(stencil_drawMask_frag));
|
||||
auto program = gpu::Shader::createProgram(vs, ps);
|
||||
gpu::Shader::makeProgram((*program));
|
||||
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
drawMask(*state);
|
||||
state->setColorWriteMask(0);
|
||||
|
||||
_paintStencilPipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
return _paintStencilPipeline;
|
||||
}
|
||||
|
||||
void PrepareStencil::run(const RenderContextPointer& renderContext, const gpu::FramebufferPointer& srcFramebuffer) {
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
||||
// Only draw the stencil mask if in HMD mode or not forced.
|
||||
if (!_forceDraw && (args->_displayMode != RenderArgs::STEREO_HMD)) {
|
||||
return;
|
||||
}
|
||||
|
||||
doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||
batch.enableStereo(false);
|
||||
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
|
||||
if (_maskMode < 0) {
|
||||
batch.setPipeline(getMeshStencilPipeline());
|
||||
|
||||
auto mesh = getMesh();
|
||||
batch.setIndexBuffer(mesh->getIndexBuffer());
|
||||
batch.setInputFormat((mesh->getVertexFormat()));
|
||||
batch.setInputStream(0, mesh->getVertexStream());
|
||||
|
||||
// Draw
|
||||
auto part = mesh->getPartBuffer().get<model::Mesh::Part>(0);
|
||||
batch.drawIndexed(gpu::TRIANGLES, part._numIndices, part._startIndex);
|
||||
} else {
|
||||
batch.setPipeline(getPaintStencilPipeline());
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void PrepareStencil::drawMask(gpu::State& state) {
|
||||
state.setStencilTest(true, 0xFF, gpu::State::StencilTest(PrepareStencil::STENCIL_MASK, 0xFF, gpu::ALWAYS, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_REPLACE));
|
||||
}
|
||||
|
||||
void PrepareStencil::testMask(gpu::State& state) {
|
||||
state.setStencilTest(true, 0x00, gpu::State::StencilTest(PrepareStencil::STENCIL_MASK, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||
}
|
||||
|
||||
void PrepareStencil::testBackground(gpu::State& state) {
|
||||
state.setStencilTest(true, 0x00, gpu::State::StencilTest(PrepareStencil::STENCIL_BACKGROUND, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||
}
|
||||
|
||||
void PrepareStencil::testMaskDrawShape(gpu::State& state) {
|
||||
state.setStencilTest(true, 0xFF, gpu::State::StencilTest(PrepareStencil::STENCIL_MASK, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_ZERO));
|
||||
}
|
||||
|
||||
void PrepareStencil::testShape(gpu::State& state) {
|
||||
state.setStencilTest(true, 0x00, gpu::State::StencilTest(PrepareStencil::STENCIL_SHAPE, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||
}
|
71
libraries/render-utils/src/StencilMaskPass.h
Normal file
71
libraries/render-utils/src/StencilMaskPass.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
//
|
||||
// StencilMaskPass.h
|
||||
// render-utils/src/
|
||||
//
|
||||
// Created by Sam Gateau on 5/31/17.
|
||||
// Copyright 20154 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
|
||||
//
|
||||
#pragma once
|
||||
#ifndef hifi_StencilMaskPass_h
|
||||
#define hifi_StencilMaskPass_h
|
||||
|
||||
#include <render/Engine.h>
|
||||
#include <gpu/Pipeline.h>
|
||||
#include <model/Geometry.h>
|
||||
|
||||
class PrepareStencilConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int maskMode MEMBER maskMode NOTIFY dirty)
|
||||
Q_PROPERTY(bool forceDraw MEMBER forceDraw NOTIFY dirty)
|
||||
|
||||
public:
|
||||
PrepareStencilConfig(bool enabled = true) : JobConfig(enabled) {}
|
||||
|
||||
int maskMode { 0 };
|
||||
bool forceDraw { false };
|
||||
|
||||
signals:
|
||||
void dirty();
|
||||
};
|
||||
|
||||
class PrepareStencil {
|
||||
public:
|
||||
using Config = PrepareStencilConfig;
|
||||
|
||||
using JobModel = render::Job::ModelI<PrepareStencil, gpu::FramebufferPointer, Config>;
|
||||
|
||||
void configure(const Config& config);
|
||||
|
||||
void run(const render::RenderContextPointer& renderContext, const gpu::FramebufferPointer& dstFramebuffer);
|
||||
|
||||
static const gpu::int8 STENCIL_MASK = 2;
|
||||
static const gpu::int8 STENCIL_BACKGROUND = 1;
|
||||
static const gpu::int8 STENCIL_SHAPE = 0;
|
||||
|
||||
|
||||
static void drawMask(gpu::State& state);
|
||||
static void testMask(gpu::State& state);
|
||||
static void testBackground(gpu::State& state);
|
||||
static void testMaskDrawShape(gpu::State& state);
|
||||
static void testShape(gpu::State& state);
|
||||
|
||||
|
||||
private:
|
||||
gpu::PipelinePointer _meshStencilPipeline;
|
||||
gpu::PipelinePointer getMeshStencilPipeline();
|
||||
|
||||
gpu::PipelinePointer _paintStencilPipeline;
|
||||
gpu::PipelinePointer getPaintStencilPipeline();
|
||||
|
||||
model::MeshPointer _mesh;
|
||||
model::MeshPointer getMesh();
|
||||
|
||||
int _maskMode { 0 };
|
||||
bool _forceDraw { false };
|
||||
};
|
||||
|
||||
|
||||
#endif // hifi_StencilMaskPass_h
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#include <gpu/Context.h>
|
||||
#include <gpu/StandardShaderLib.h>
|
||||
|
||||
#include "StencilMaskPass.h"
|
||||
|
||||
const int DepthLinearPass_FrameTransformSlot = 0;
|
||||
const int DepthLinearPass_DepthMapSlot = 0;
|
||||
|
@ -224,7 +224,7 @@ const gpu::PipelinePointer& LinearDepthPass::getLinearDepthPipeline() {
|
|||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
|
||||
// Stencil test the curvature pass for objects pixels only, not the background
|
||||
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||
PrepareStencil::testShape(*state);
|
||||
|
||||
state->setColorWriteMask(true, false, false, false);
|
||||
|
||||
|
@ -250,6 +250,7 @@ const gpu::PipelinePointer& LinearDepthPass::getDownsamplePipeline() {
|
|||
|
||||
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
PrepareStencil::testShape(*state);
|
||||
|
||||
state->setColorWriteMask(true, true, true, false);
|
||||
|
||||
|
@ -554,7 +555,7 @@ const gpu::PipelinePointer& SurfaceGeometryPass::getCurvaturePipeline() {
|
|||
|
||||
#ifdef USE_STENCIL_TEST
|
||||
// Stencil test the curvature pass for objects pixels only, not the background
|
||||
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||
PrepareStencil::testShape(*state);
|
||||
#endif
|
||||
// Good to go add the brand new pipeline
|
||||
_curvaturePipeline = gpu::Pipeline::create(program, state);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include <gpu/StandardShaderLib.h>
|
||||
|
||||
#include <RenderArgs.h>
|
||||
|
||||
#include "StencilMaskPass.h"
|
||||
#include "FramebufferCache.h"
|
||||
|
||||
#include "toneMapping_frag.h"
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <render/FilterTask.h>
|
||||
#include <render/DrawTask.h>
|
||||
|
||||
#include "StencilMaskPass.h"
|
||||
#include "DeferredLightingEffect.h"
|
||||
|
||||
#include "zone_drawKeyLight_frag.h"
|
||||
|
@ -74,6 +75,7 @@ const gpu::PipelinePointer& DebugZoneLighting::getKeyLightPipeline() {
|
|||
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
|
||||
PrepareStencil::testMask(*state);
|
||||
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
|
||||
_keyLightPipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
|
@ -95,6 +97,7 @@ const gpu::PipelinePointer& DebugZoneLighting::getAmbientPipeline() {
|
|||
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
|
||||
PrepareStencil::testMask(*state);
|
||||
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
|
||||
_ambientPipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
|
@ -115,6 +118,7 @@ const gpu::PipelinePointer& DebugZoneLighting::getBackgroundPipeline() {
|
|||
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
|
||||
PrepareStencil::testMask(*state);
|
||||
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
|
||||
_backgroundPipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// directional_light.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 9/3/14.
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
<@include DeferredBufferRead.slh@>
|
||||
<@include DeferredGlobalLight.slh@>
|
||||
|
||||
<$declareEvalLightmappedColor()$>
|
||||
<$declareEvalAmbientGlobalColor()$>
|
||||
|
||||
in vec2 _texCoord0;
|
||||
out vec4 _fragColor;
|
||||
|
||||
void main(void) {
|
||||
DeferredFrameTransform deferredTransform = getDeferredFrameTransform();
|
||||
DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0);
|
||||
|
||||
float shadowAttenuation = 1.0;
|
||||
|
||||
if (frag.mode == FRAG_MODE_UNLIT) {
|
||||
discard;
|
||||
} else if (frag.mode == FRAG_MODE_LIGHTMAPPED) {
|
||||
discard;
|
||||
} else {
|
||||
vec3 color = evalAmbientGlobalColor(
|
||||
getViewInverse(),
|
||||
shadowAttenuation,
|
||||
frag.obscurance,
|
||||
frag.position.xyz,
|
||||
frag.normal,
|
||||
frag.albedo,
|
||||
frag.fresnel,
|
||||
frag.metallic,
|
||||
frag.roughness);
|
||||
_fragColor = vec4(color, 1.0);
|
||||
}
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// directional_light_shadow.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Zach Pomerantz on 1/18/2016.
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
<@include Shadow.slh@>
|
||||
<@include DeferredBufferRead.slh@>
|
||||
<@include DeferredGlobalLight.slh@>
|
||||
|
||||
<$declareEvalLightmappedColor()$>
|
||||
<$declareEvalAmbientGlobalColor()$>
|
||||
|
||||
in vec2 _texCoord0;
|
||||
out vec4 _fragColor;
|
||||
|
||||
void main(void) {
|
||||
DeferredFrameTransform deferredTransform = getDeferredFrameTransform();
|
||||
DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0);
|
||||
|
||||
vec4 worldPos = getViewInverse() * vec4(frag.position.xyz, 1.0);
|
||||
float shadowAttenuation = evalShadowAttenuation(worldPos);
|
||||
|
||||
if (frag.mode == FRAG_MODE_UNLIT) {
|
||||
discard;
|
||||
} else if (frag.mode == FRAG_MODE_LIGHTMAPPED) {
|
||||
discard;
|
||||
} else {
|
||||
vec3 color = evalAmbientGlobalColor(
|
||||
getViewInverse(),
|
||||
shadowAttenuation,
|
||||
frag.obscurance,
|
||||
frag.position.xyz,
|
||||
frag.normal,
|
||||
frag.albedo,
|
||||
frag.fresnel,
|
||||
frag.metallic,
|
||||
frag.roughness);
|
||||
_fragColor = vec4(color, 1.0);
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
|
||||
// hit_effect.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Eric Levin on 7/20
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
|
||||
<@include DeferredBufferWrite.slh@>
|
||||
|
||||
in vec2 varQuadPosition;
|
||||
out vec4 outFragColor;
|
||||
|
||||
void main(void) {
|
||||
vec2 center = vec2(0.0, 0.0);
|
||||
float distFromCenter = distance( vec2(0.0, 0.0), varQuadPosition);
|
||||
float alpha = mix(0.0, 0.5, pow(distFromCenter,5.));
|
||||
outFragColor = vec4(1.0, 0.0, 0.0, alpha);
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// point_light.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Sam Gateau on 9/18/15.
|
||||
// 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
|
||||
//
|
||||
<!
|
||||
// Everything about deferred buffer
|
||||
<@include DeferredBufferRead.slh@>
|
||||
|
||||
<$declareDeferredCurvature()$>
|
||||
|
||||
// Everything about light
|
||||
<@include model/Light.slh@>
|
||||
<$declareLightBuffer()$>
|
||||
|
||||
<@include LightingModel.slh@>
|
||||
|
||||
<@include LightPoint.slh@>
|
||||
<$declareLightingPoint(supportScattering)$>
|
||||
|
||||
|
||||
uniform vec4 texcoordFrameTransform;
|
||||
|
||||
in vec4 _texCoord0;!>
|
||||
out vec4 _fragColor;
|
||||
|
||||
void main(void) {
|
||||
_fragColor = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
|
||||
<!
|
||||
DeferredFrameTransform deferredTransform = getDeferredFrameTransform();
|
||||
|
||||
// Grab the fragment data from the uv
|
||||
vec2 texCoord = _texCoord0.st / _texCoord0.q;
|
||||
texCoord *= texcoordFrameTransform.zw;
|
||||
texCoord += texcoordFrameTransform.xy;
|
||||
|
||||
DeferredFragment frag = unpackDeferredFragment(deferredTransform, texCoord);
|
||||
|
||||
if (frag.mode == FRAG_MODE_UNLIT) {
|
||||
discard;
|
||||
}
|
||||
|
||||
// Need the light now
|
||||
Light light = getLight();
|
||||
|
||||
// Frag pos in world
|
||||
mat4 invViewMat = getViewInverse();
|
||||
vec4 fragPos = invViewMat * frag.position;
|
||||
|
||||
// Clip againgst the light volume and Make the Light vector going from fragment to light center in world space
|
||||
vec4 fragLightVecLen2;
|
||||
if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragPos.xyz, fragLightVecLen2)) {
|
||||
discard;
|
||||
}
|
||||
|
||||
// Frag to eye vec
|
||||
vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0);
|
||||
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
|
||||
|
||||
|
||||
vec3 diffuse;
|
||||
vec3 specular;
|
||||
vec4 midNormalCurvature;
|
||||
vec4 lowNormalCurvature;
|
||||
if (frag.mode == FRAG_MODE_SCATTERING) {
|
||||
unpackMidLowNormalCurvature(texCoord, midNormalCurvature, lowNormalCurvature);
|
||||
}
|
||||
evalLightingPoint(diffuse, specular, light,
|
||||
fragLightVecLen2.xyz, fragEyeDir, frag.normal, frag.roughness,
|
||||
frag.metallic, frag.fresnel, frag.albedo, 1.0,
|
||||
frag.scattering, midNormalCurvature, lowNormalCurvature);
|
||||
|
||||
_fragColor.rgb += diffuse;
|
||||
_fragColor.rgb += specular;
|
||||
!>
|
||||
}
|
|
@ -1,115 +0,0 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// spot_light.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Sam Gateau on 9/18/15.
|
||||
// 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
|
||||
//
|
||||
|
||||
// Everything about deferred buffer
|
||||
<!<@include DeferredBufferRead.slh@>
|
||||
|
||||
<$declareDeferredCurvature()$>
|
||||
|
||||
// Everything about light
|
||||
<@include model/Light.slh@>
|
||||
<$declareLightBuffer(256)$>
|
||||
uniform lightIndexBuffer {
|
||||
int lightIndex[256];
|
||||
};
|
||||
<@include LightingModel.slh@>
|
||||
|
||||
<@include LightPoint.slh@>
|
||||
<$declareLightingPoint(supportScattering)$>
|
||||
<@include LightSpot.slh@>
|
||||
<$declareLightingSpot(supportScattering)$>
|
||||
|
||||
//uniform vec4 texcoordFrameTransform;
|
||||
!>
|
||||
|
||||
|
||||
//in vec4 _texCoord0;
|
||||
//flat in int instanceID;
|
||||
out vec4 _fragColor;
|
||||
|
||||
void main(void) {
|
||||
_fragColor = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
|
||||
// DeferredFrameTransform deferredTransform = getDeferredFrameTransform();
|
||||
|
||||
// Grab the fragment data from the uv
|
||||
//vec2 texCoord = _texCoord0.st;/* / _texCoord0.q;
|
||||
/*texCoord *= texcoordFrameTransform.zw;
|
||||
texCoord += texcoordFrameTransform.xy;*/
|
||||
/*
|
||||
vec4 fragPosition = unpackDeferredPositionFromZeye(texCoord);
|
||||
DeferredFragment frag = unpackDeferredFragmentNoPosition(texCoord);
|
||||
|
||||
if (frag.mode == FRAG_MODE_UNLIT) {
|
||||
discard;
|
||||
}
|
||||
|
||||
|
||||
// frag.depthVal = depthValue;
|
||||
frag.position = fragPosition;
|
||||
|
||||
vec4 midNormalCurvature;
|
||||
vec4 lowNormalCurvature;
|
||||
if (frag.mode == FRAG_MODE_SCATTERING) {
|
||||
unpackMidLowNormalCurvature(texCoord, midNormalCurvature, lowNormalCurvature);
|
||||
}
|
||||
|
||||
// Frag pos in world
|
||||
mat4 invViewMat = getViewInverse();
|
||||
vec4 fragPos = invViewMat * fragPosition;
|
||||
|
||||
// Frag to eye vec
|
||||
vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0);
|
||||
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
|
||||
|
||||
int numLights = lightIndex[0];
|
||||
for (int i = 0; i < numLights; i++) {
|
||||
// Need the light now
|
||||
Light light = getLight(lightIndex[i + 1]);
|
||||
bool isSpot = light_isSpot(light);
|
||||
// Clip againgst the light volume and Make the Light vector going from fragment to light center in world space
|
||||
vec4 fragLightVecLen2;
|
||||
vec4 fragLightDirLen;
|
||||
float cosSpotAngle;
|
||||
if (isSpot) {
|
||||
if (!clipFragToLightVolumeSpot(light, fragPos.xyz, fragLightVecLen2, fragLightDirLen, cosSpotAngle)) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (!clipFragToLightVolumePoint(light, fragPos.xyz, fragLightVecLen2)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
vec3 diffuse;
|
||||
vec3 specular;
|
||||
|
||||
if (isSpot) {
|
||||
evalLightingSpot(diffuse, specular, light,
|
||||
fragLightDirLen.xyzw, cosSpotAngle, fragEyeDir, frag.normal, frag.roughness,
|
||||
frag.metallic, frag.fresnel, frag.albedo, 1.0,
|
||||
frag.scattering, midNormalCurvature, lowNormalCurvature);
|
||||
} else {
|
||||
evalLightingPoint(diffuse, specular, light,
|
||||
fragLightVecLen2.xyz, fragEyeDir, frag.normal, frag.roughness,
|
||||
frag.metallic, frag.fresnel, frag.albedo, 1.0,
|
||||
frag.scattering, midNormalCurvature, lowNormalCurvature);
|
||||
}
|
||||
|
||||
_fragColor.rgb += diffuse;
|
||||
_fragColor.rgb += specular;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
23
libraries/render-utils/src/stencil_drawMask.slf
Normal file
23
libraries/render-utils/src/stencil_drawMask.slf
Normal file
|
@ -0,0 +1,23 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// stencil_drawMask.slf
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Sam Gateau on 5/31/17.
|
||||
// Copyright 2017 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
|
||||
//
|
||||
|
||||
in vec2 varTexCoord0;
|
||||
|
||||
float aspectRatio = 0.95;
|
||||
|
||||
void main(void) {
|
||||
vec2 pos = varTexCoord0 * 2.0 - vec2(1.0);
|
||||
pos.x = aspectRatio * (pos.x * (pos.x > 0.0 ? 2.0 : -2.0) - 1.0);
|
||||
if (1.0 - dot(pos.xy, pos.xy) > 0.0 ) discard;
|
||||
}
|
|
@ -49,7 +49,7 @@ const mat4 Matrices::Z_180 { createMatFromQuatAndPos(Quaternions::Z_180, Vectors
|
|||
glm::quat safeMix(const glm::quat& q1, const glm::quat& q2, float proportion) {
|
||||
float cosa = q1.x * q2.x + q1.y * q2.y + q1.z * q2.z + q1.w * q2.w;
|
||||
float ox = q2.x, oy = q2.y, oz = q2.z, ow = q2.w, s0, s1;
|
||||
|
||||
|
||||
// adjust signs if necessary
|
||||
if (cosa < 0.0f) {
|
||||
cosa = -cosa;
|
||||
|
@ -58,19 +58,19 @@ glm::quat safeMix(const glm::quat& q1, const glm::quat& q2, float proportion) {
|
|||
oz = -oz;
|
||||
ow = -ow;
|
||||
}
|
||||
|
||||
|
||||
// calculate coefficients; if the angle is too close to zero, we must fall back
|
||||
// to linear interpolation
|
||||
if ((1.0f - cosa) > EPSILON) {
|
||||
float angle = acosf(cosa), sina = sinf(angle);
|
||||
s0 = sinf((1.0f - proportion) * angle) / sina;
|
||||
s1 = sinf(proportion * angle) / sina;
|
||||
|
||||
|
||||
} else {
|
||||
s0 = 1.0f - proportion;
|
||||
s1 = proportion;
|
||||
}
|
||||
|
||||
|
||||
return glm::normalize(glm::quat(s0 * q1.w + s1 * ow, s0 * q1.x + s1 * ox, s0 * q1.y + s1 * oy, s0 * q1.z + s1 * oz));
|
||||
}
|
||||
|
||||
|
@ -105,10 +105,10 @@ int unpackFloatVec3FromSignedTwoByteFixed(const unsigned char* sourceBuffer, glm
|
|||
|
||||
int packFloatAngleToTwoByte(unsigned char* buffer, float degrees) {
|
||||
const float ANGLE_CONVERSION_RATIO = (std::numeric_limits<uint16_t>::max() / 360.0f);
|
||||
|
||||
|
||||
uint16_t angleHolder = floorf((degrees + 180.0f) * ANGLE_CONVERSION_RATIO);
|
||||
memcpy(buffer, &angleHolder, sizeof(uint16_t));
|
||||
|
||||
|
||||
return sizeof(uint16_t);
|
||||
}
|
||||
|
||||
|
@ -125,7 +125,7 @@ int packOrientationQuatToBytes(unsigned char* buffer, const glm::quat& quatInput
|
|||
quatParts[1] = floorf((quatNormalized.y + 1.0f) * QUAT_PART_CONVERSION_RATIO);
|
||||
quatParts[2] = floorf((quatNormalized.z + 1.0f) * QUAT_PART_CONVERSION_RATIO);
|
||||
quatParts[3] = floorf((quatNormalized.w + 1.0f) * QUAT_PART_CONVERSION_RATIO);
|
||||
|
||||
|
||||
memcpy(buffer, &quatParts, sizeof(quatParts));
|
||||
return sizeof(quatParts);
|
||||
}
|
||||
|
@ -133,12 +133,12 @@ int packOrientationQuatToBytes(unsigned char* buffer, const glm::quat& quatInput
|
|||
int unpackOrientationQuatFromBytes(const unsigned char* buffer, glm::quat& quatOutput) {
|
||||
uint16_t quatParts[4];
|
||||
memcpy(&quatParts, buffer, sizeof(quatParts));
|
||||
|
||||
|
||||
quatOutput.x = ((quatParts[0] / (float) std::numeric_limits<uint16_t>::max()) * 2.0f) - 1.0f;
|
||||
quatOutput.y = ((quatParts[1] / (float) std::numeric_limits<uint16_t>::max()) * 2.0f) - 1.0f;
|
||||
quatOutput.z = ((quatParts[2] / (float) std::numeric_limits<uint16_t>::max()) * 2.0f) - 1.0f;
|
||||
quatOutput.w = ((quatParts[3] / (float) std::numeric_limits<uint16_t>::max()) * 2.0f) - 1.0f;
|
||||
|
||||
|
||||
return sizeof(quatParts);
|
||||
}
|
||||
|
||||
|
@ -235,7 +235,7 @@ glm::vec3 safeEulerAngles(const glm::quat& q) {
|
|||
atan2f(q.y * q.z + q.x * q.w, 0.5f - (q.x * q.x + q.y * q.y)),
|
||||
asinf(sy),
|
||||
atan2f(q.x * q.y + q.z * q.w, 0.5f - (q.y * q.y + q.z * q.z)));
|
||||
|
||||
|
||||
} else {
|
||||
// not a unique solution; x + z = atan2(-m21, m11)
|
||||
eulers = glm::vec3(
|
||||
|
@ -250,7 +250,7 @@ glm::vec3 safeEulerAngles(const glm::quat& q) {
|
|||
PI_OVER_TWO,
|
||||
-atan2f(q.x * q.w - q.y * q.z, 0.5f - (q.x * q.x + q.z * q.z)));
|
||||
}
|
||||
|
||||
|
||||
// adjust so that z, rather than y, is in [-pi/2, pi/2]
|
||||
if (eulers.z < -PI_OVER_TWO) {
|
||||
if (eulers.x < 0.0f) {
|
||||
|
@ -265,7 +265,7 @@ glm::vec3 safeEulerAngles(const glm::quat& q) {
|
|||
eulers.y -= PI;
|
||||
}
|
||||
eulers.z += PI;
|
||||
|
||||
|
||||
} else if (eulers.z > PI_OVER_TWO) {
|
||||
if (eulers.x < 0.0f) {
|
||||
eulers.x += PI;
|
||||
|
@ -320,7 +320,7 @@ glm::quat extractRotation(const glm::mat4& matrix, bool assumeOrthogonal) {
|
|||
for (int i = 0; i < 10; i++) {
|
||||
// store the results of the previous iteration
|
||||
glm::mat3 previous = upper;
|
||||
|
||||
|
||||
// compute average of the matrix with its inverse transpose
|
||||
float sd00 = previous[1][1] * previous[2][2] - previous[2][1] * previous[1][2];
|
||||
float sd10 = previous[0][1] * previous[2][2] - previous[2][1] * previous[0][2];
|
||||
|
@ -334,15 +334,15 @@ glm::quat extractRotation(const glm::mat4& matrix, bool assumeOrthogonal) {
|
|||
upper[0][0] = +sd00 * hrdet + previous[0][0] * 0.5f;
|
||||
upper[1][0] = -sd10 * hrdet + previous[1][0] * 0.5f;
|
||||
upper[2][0] = +sd20 * hrdet + previous[2][0] * 0.5f;
|
||||
|
||||
|
||||
upper[0][1] = -(previous[1][0] * previous[2][2] - previous[2][0] * previous[1][2]) * hrdet + previous[0][1] * 0.5f;
|
||||
upper[1][1] = +(previous[0][0] * previous[2][2] - previous[2][0] * previous[0][2]) * hrdet + previous[1][1] * 0.5f;
|
||||
upper[2][1] = -(previous[0][0] * previous[1][2] - previous[1][0] * previous[0][2]) * hrdet + previous[2][1] * 0.5f;
|
||||
|
||||
|
||||
upper[0][2] = +(previous[1][0] * previous[2][1] - previous[2][0] * previous[1][1]) * hrdet + previous[0][2] * 0.5f;
|
||||
upper[1][2] = -(previous[0][0] * previous[2][1] - previous[2][0] * previous[0][1]) * hrdet + previous[1][2] * 0.5f;
|
||||
upper[2][2] = +(previous[0][0] * previous[1][1] - previous[1][0] * previous[0][1]) * hrdet + previous[2][2] * 0.5f;
|
||||
|
||||
|
||||
// compute the difference; if it's small enough, we're done
|
||||
glm::mat3 diff = upper - previous;
|
||||
if (diff[0][0] * diff[0][0] + diff[1][0] * diff[1][0] + diff[2][0] * diff[2][0] + diff[0][1] * diff[0][1] +
|
||||
|
@ -352,7 +352,7 @@ glm::quat extractRotation(const glm::mat4& matrix, bool assumeOrthogonal) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// now that we have a nice orthogonal matrix, we can extract the rotation quaternion
|
||||
// using the method described in http://en.wikipedia.org/wiki/Rotation_matrix#Conversions
|
||||
float x2 = fabs(1.0f + upper[0][0] - upper[1][1] - upper[2][2]);
|
||||
|
@ -473,7 +473,7 @@ glm::mat4 createMatFromScaleQuatAndPos(const glm::vec3& scale, const glm::quat&
|
|||
glm::vec4(zAxis, 0.0f), glm::vec4(trans, 1.0f));
|
||||
}
|
||||
|
||||
// cancel out roll
|
||||
// cancel out roll
|
||||
glm::quat cancelOutRoll(const glm::quat& q) {
|
||||
glm::vec3 forward = q * Vectors::FRONT;
|
||||
return glm::quat_cast(glm::inverse(glm::lookAt(Vectors::ZERO, forward, Vectors::UP)));
|
||||
|
@ -538,17 +538,16 @@ void generateBasisVectors(const glm::vec3& primaryAxis, const glm::vec3& seconda
|
|||
uAxisOut = glm::normalize(primaryAxis);
|
||||
glm::vec3 normSecondary = glm::normalize(secondaryAxis);
|
||||
|
||||
// if secondaryAxis is parallel with the primaryAxis, pick another axis.
|
||||
// if normSecondary is parallel with the primaryAxis, pick another secondary.
|
||||
const float EPSILON = 1.0e-4f;
|
||||
if (fabsf(fabsf(glm::dot(uAxisOut, secondaryAxis)) - 1.0f) > EPSILON) {
|
||||
// pick a better secondaryAxis.
|
||||
normSecondary = glm::vec3(1.0f, 0.0f, 0.0f);
|
||||
if (fabsf(fabsf(glm::dot(uAxisOut, secondaryAxis)) - 1.0f) > EPSILON) {
|
||||
normSecondary = glm::vec3(0.0f, 1.0f, 0.0f);
|
||||
if (fabsf(fabsf(glm::dot(uAxisOut, normSecondary)) - 1.0f) < EPSILON) {
|
||||
normSecondary = Vectors::UNIT_X;
|
||||
if (fabsf(fabsf(glm::dot(uAxisOut, normSecondary)) - 1.0f) < EPSILON) {
|
||||
normSecondary = Vectors::UNIT_Y;
|
||||
}
|
||||
}
|
||||
|
||||
wAxisOut = glm::normalize(glm::cross(uAxisOut, secondaryAxis));
|
||||
wAxisOut = glm::normalize(glm::cross(uAxisOut, normSecondary));
|
||||
vAxisOut = glm::cross(wAxisOut, uAxisOut);
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ public:
|
|||
class RenderArgs {
|
||||
public:
|
||||
enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE, MIRROR_RENDER_MODE };
|
||||
enum RenderSide { MONO, STEREO_LEFT, STEREO_RIGHT };
|
||||
enum DisplayMode { MONO, STEREO_MONITOR, STEREO_HMD };
|
||||
enum DebugFlags {
|
||||
RENDER_DEBUG_NONE = 0,
|
||||
RENDER_DEBUG_HULLS = 1
|
||||
|
@ -87,7 +87,7 @@ public:
|
|||
float sizeScale = 1.0f,
|
||||
int boundaryLevelAdjust = 0,
|
||||
RenderMode renderMode = DEFAULT_RENDER_MODE,
|
||||
RenderSide renderSide = MONO,
|
||||
DisplayMode displayMode = MONO,
|
||||
DebugFlags debugFlags = RENDER_DEBUG_NONE,
|
||||
gpu::Batch* batch = nullptr) :
|
||||
_context(context),
|
||||
|
@ -95,7 +95,7 @@ public:
|
|||
_sizeScale(sizeScale),
|
||||
_boundaryLevelAdjust(boundaryLevelAdjust),
|
||||
_renderMode(renderMode),
|
||||
_renderSide(renderSide),
|
||||
_displayMode(displayMode),
|
||||
_debugFlags(debugFlags),
|
||||
_batch(batch) {
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ public:
|
|||
float _sizeScale = 1.0f;
|
||||
int _boundaryLevelAdjust = 0;
|
||||
RenderMode _renderMode = DEFAULT_RENDER_MODE;
|
||||
RenderSide _renderSide = MONO;
|
||||
DisplayMode _displayMode = MONO;
|
||||
DebugFlags _debugFlags = RENDER_DEBUG_NONE;
|
||||
gpu::Batch* _batch = nullptr;
|
||||
|
||||
|
|
|
@ -91,14 +91,14 @@ QObject* OffscreenUi::getFlags() {
|
|||
|
||||
void OffscreenUi::create(QOpenGLContext* context) {
|
||||
OffscreenQmlSurface::create(context);
|
||||
auto rootContext = getRootContext();
|
||||
auto myContext = getSurfaceContext();
|
||||
|
||||
rootContext->setContextProperty("OffscreenUi", this);
|
||||
rootContext->setContextProperty("offscreenFlags", offscreenFlags = new OffscreenFlags());
|
||||
rootContext->setContextProperty("fileDialogHelper", new FileDialogHelper());
|
||||
myContext->setContextProperty("OffscreenUi", this);
|
||||
myContext->setContextProperty("offscreenFlags", offscreenFlags = new OffscreenFlags());
|
||||
myContext->setContextProperty("fileDialogHelper", new FileDialogHelper());
|
||||
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||
TabletProxy* tablet = tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system");
|
||||
rootContext->engine()->setObjectOwnership(tablet, QQmlEngine::CppOwnership);
|
||||
myContext->engine()->setObjectOwnership(tablet, QQmlEngine::CppOwnership);
|
||||
}
|
||||
|
||||
void OffscreenUi::show(const QUrl& url, const QString& name, std::function<void(QQmlContext*, QObject*)> f) {
|
||||
|
@ -547,14 +547,14 @@ void OffscreenUi::createDesktop(const QUrl& url) {
|
|||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
getRootContext()->setContextProperty("DebugQML", QVariant(true));
|
||||
getSurfaceContext()->setContextProperty("DebugQML", QVariant(true));
|
||||
#else
|
||||
getRootContext()->setContextProperty("DebugQML", QVariant(false));
|
||||
getSurfaceContext()->setContextProperty("DebugQML", QVariant(false));
|
||||
#endif
|
||||
|
||||
_desktop = dynamic_cast<QQuickItem*>(load(url));
|
||||
Q_ASSERT(_desktop);
|
||||
getRootContext()->setContextProperty("desktop", _desktop);
|
||||
getSurfaceContext()->setContextProperty("desktop", _desktop);
|
||||
|
||||
_toolWindow = _desktop->findChild<QQuickItem*>("ToolWindow");
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ private:
|
|||
|
||||
VrMenu::VrMenu(OffscreenUi* parent) : QObject(parent) {
|
||||
_rootMenu = parent->getRootItem()->findChild<QObject*>("rootMenu");
|
||||
parent->getRootContext()->setContextProperty("rootMenu", _rootMenu);
|
||||
parent->getSurfaceContext()->setContextProperty("rootMenu", _rootMenu);
|
||||
}
|
||||
|
||||
QObject* VrMenu::findMenuObject(const QString& menuOption) {
|
||||
|
|
|
@ -123,10 +123,19 @@ bool OculusBaseDisplayPlugin::internalActivate() {
|
|||
|
||||
void OculusBaseDisplayPlugin::internalDeactivate() {
|
||||
Parent::internalDeactivate();
|
||||
}
|
||||
|
||||
bool OculusBaseDisplayPlugin::activateStandBySession() {
|
||||
_session = acquireOculusSession();
|
||||
if (!_session) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void OculusBaseDisplayPlugin::deactivateSession() {
|
||||
releaseOculusSession();
|
||||
_session = nullptr;
|
||||
}
|
||||
|
||||
void OculusBaseDisplayPlugin::updatePresentPose() {
|
||||
//mat4 sensorResetMat;
|
||||
//_currentPresentFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds();
|
||||
|
|
|
@ -26,6 +26,7 @@ public:
|
|||
void resetSensors() override final;
|
||||
bool beginFrameRender(uint32_t frameIndex) override;
|
||||
float getTargetFrameRate() const override { return _hmdDesc.DisplayRefreshRate; }
|
||||
bool getSupportsAutoSwitch() override final { return true; }
|
||||
|
||||
|
||||
protected:
|
||||
|
@ -33,6 +34,8 @@ protected:
|
|||
void uncustomizeContext() override;
|
||||
bool internalActivate() override;
|
||||
void internalDeactivate() override;
|
||||
bool activateStandBySession() override;
|
||||
void deactivateSession() override;
|
||||
void updatePresentPose() override;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -366,45 +366,25 @@ function Teleporter() {
|
|||
}
|
||||
|
||||
// related to repositioning the avatar after you teleport
|
||||
var FOOT_JOINT_NAMES = ["RightToe_End", "RightToeBase", "RightFoot"];
|
||||
var DEFAULT_ROOT_TO_FOOT_OFFSET = 0.5;
|
||||
function getAvatarFootOffset() {
|
||||
var data = getJointData();
|
||||
var upperLeg, lowerLeg, foot, toe, toeTop;
|
||||
data.forEach(function(d) {
|
||||
|
||||
var jointName = d.joint;
|
||||
if (jointName === "RightUpLeg") {
|
||||
upperLeg = d.translation.y;
|
||||
} else if (jointName === "RightLeg") {
|
||||
lowerLeg = d.translation.y;
|
||||
} else if (jointName === "RightFoot") {
|
||||
foot = d.translation.y;
|
||||
} else if (jointName === "RightToeBase") {
|
||||
toe = d.translation.y;
|
||||
} else if (jointName === "RightToe_End") {
|
||||
toeTop = d.translation.y;
|
||||
// find a valid foot jointIndex
|
||||
var footJointIndex = -1;
|
||||
var i, l = FOOT_JOINT_NAMES.length;
|
||||
for (i = 0; i < l; i++) {
|
||||
footJointIndex = MyAvatar.getJointIndex(FOOT_JOINT_NAMES[i]);
|
||||
if (footJointIndex != -1) {
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
var offset = upperLeg + lowerLeg + foot + toe + toeTop;
|
||||
offset = offset / 100;
|
||||
return offset;
|
||||
}
|
||||
|
||||
function getJointData() {
|
||||
var allJointData = [];
|
||||
var jointNames = MyAvatar.jointNames;
|
||||
jointNames.forEach(function(joint, index) {
|
||||
var translation = MyAvatar.getJointTranslation(index);
|
||||
var rotation = MyAvatar.getJointRotation(index);
|
||||
allJointData.push({
|
||||
joint: joint,
|
||||
index: index,
|
||||
translation: translation,
|
||||
rotation: rotation
|
||||
});
|
||||
});
|
||||
|
||||
return allJointData;
|
||||
}
|
||||
if (footJointIndex != -1) {
|
||||
// default vertical offset from foot to avatar root.
|
||||
return -MyAvatar.getAbsoluteDefaultJointTranslationInObjectFrame(footJointIndex).y;
|
||||
} else {
|
||||
return DEFAULT_ROOT_TO_FOOT_OFFSET * MyAvatar.scale;
|
||||
}
|
||||
}
|
||||
|
||||
var leftPad = new ThumbPad('left');
|
||||
|
|
|
@ -642,6 +642,8 @@ var toolBar = (function () {
|
|||
enabled: active
|
||||
}));
|
||||
isActive = active;
|
||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
|
||||
if (!isActive) {
|
||||
entityListTool.setVisible(false);
|
||||
gridTool.setVisible(false);
|
||||
|
@ -650,8 +652,8 @@ var toolBar = (function () {
|
|||
selectionManager.clearSelections();
|
||||
cameraManager.disable();
|
||||
selectionDisplay.triggerMapping.disable();
|
||||
tablet.landscape = false;
|
||||
} else {
|
||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
tablet.loadQMLSource("Edit.qml");
|
||||
UserActivityLogger.enabledEdit();
|
||||
entityListTool.setVisible(true);
|
||||
|
@ -659,6 +661,8 @@ var toolBar = (function () {
|
|||
grid.setEnabled(true);
|
||||
propertiesTool.setVisible(true);
|
||||
selectionDisplay.triggerMapping.enable();
|
||||
print("starting tablet in landscape mode")
|
||||
tablet.landscape = true;
|
||||
// Not sure what the following was meant to accomplish, but it currently causes
|
||||
// everybody else to think that Interface has lost focus overall. fogbugzid:558
|
||||
// Window.setFocus();
|
||||
|
|
|
@ -22,7 +22,9 @@ var DEFAULT_WIDTH = 0.4375;
|
|||
var DEFAULT_VERTICAL_FIELD_OF_VIEW = 45; // degrees
|
||||
var SENSOR_TO_ROOM_MATRIX = -2;
|
||||
var CAMERA_MATRIX = -7;
|
||||
var ROT_Y_180 = {x: 0, y: 1, z: 0, w: 0};
|
||||
var ROT_Y_180 = {x: 0.0, y: 1.0, z: 0, w: 0};
|
||||
var ROT_LANDSCAPE = {x: 1.0, y: 1.0, z: 0, w: 0};
|
||||
var ROT_LANDSCAPE_WINDOW = {x: 0.0, y: 0.0, z: 0.0, w: 0};
|
||||
var ROT_IDENT = {x: 0, y: 0, z: 0, w: 1};
|
||||
var TABLET_TEXTURE_RESOLUTION = { x: 480, y: 706 };
|
||||
var INCHES_TO_METERS = 1 / 39.3701;
|
||||
|
@ -243,29 +245,29 @@ WebTablet = function (url, width, dpi, hand, clientOnly, location, visible) {
|
|||
};
|
||||
|
||||
WebTablet.prototype.getDimensions = function() {
|
||||
if (this.landscape) {
|
||||
return { x: this.width * 2, y: this.height, z: this.depth };
|
||||
} else {
|
||||
return { x: this.width, y: this.height, z: this.depth };
|
||||
}
|
||||
return { x: this.width, y: this.height, z: this.depth };
|
||||
};
|
||||
|
||||
WebTablet.prototype.getTabletTextureResolution = function() {
|
||||
if (this.landscape) {
|
||||
return { x: TABLET_TEXTURE_RESOLUTION.x * 2, y: TABLET_TEXTURE_RESOLUTION.y };
|
||||
return { x: TABLET_TEXTURE_RESOLUTION.y , y: TABLET_TEXTURE_RESOLUTION.x };
|
||||
} else {
|
||||
return TABLET_TEXTURE_RESOLUTION;
|
||||
}
|
||||
};
|
||||
|
||||
WebTablet.prototype.setLandscape = function(newLandscapeValue) {
|
||||
if (this.landscape == newLandscapeValue) {
|
||||
if (this.landscape === newLandscapeValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.landscape = newLandscapeValue;
|
||||
Overlays.editOverlay(this.tabletEntityID, { dimensions: this.getDimensions() });
|
||||
Overlays.editOverlay(this.tabletEntityID,
|
||||
{ rotation: this.landscape ? Quat.multiply(Camera.orientation, ROT_LANDSCAPE) :
|
||||
Quat.multiply(Camera.orientation, ROT_Y_180) });
|
||||
Overlays.editOverlay(this.webOverlayID, {
|
||||
resolution: this.getTabletTextureResolution()
|
||||
resolution: this.getTabletTextureResolution(),
|
||||
rotation: Quat.multiply(Camera.orientation, ROT_LANDSCAPE_WINDOW)
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -407,7 +409,7 @@ WebTablet.prototype.calculateWorldAttitudeRelativeToCamera = function (windowPos
|
|||
|
||||
return {
|
||||
position: worldMousePosition,
|
||||
rotation: Quat.multiply(Camera.orientation, ROT_Y_180)
|
||||
rotation: this.landscape ? Quat.multiply(Camera.orientation, ROT_LANDSCAPE) : Quat.multiply(Camera.orientation, ROT_Y_180)
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -191,16 +191,12 @@
|
|||
gTablet.updateAudioBar(currentMicLevel);
|
||||
}
|
||||
|
||||
if (validCheckTime - now > MSECS_PER_SEC/4) {
|
||||
//each 250ms should be just fine
|
||||
if (now - validCheckTime > MSECS_PER_SEC) {
|
||||
validCheckTime = now;
|
||||
updateTabletWidthFromSettings();
|
||||
if (UIWebTablet) {
|
||||
UIWebTablet.setLandscape(landscape);
|
||||
}
|
||||
}
|
||||
|
||||
if (validCheckTime - now > MSECS_PER_SEC) {
|
||||
validCheckTime = now;
|
||||
if (tabletRezzed && UIWebTablet && !tabletIsValid()) {
|
||||
// when we switch domains, the tablet entity gets destroyed and recreated. this causes
|
||||
// the overlay to be deleted, but not recreated. If the overlay is deleted for this or any
|
||||
|
|
|
@ -31,13 +31,9 @@
|
|||
#include <render-utils/deferred_light_point_vert.h>
|
||||
#include <render-utils/deferred_light_spot_vert.h>
|
||||
|
||||
#include <render-utils/directional_light_frag.h>
|
||||
#include <render-utils/directional_ambient_light_frag.h>
|
||||
#include <render-utils/directional_skybox_light_frag.h>
|
||||
|
||||
#include <render-utils/point_light_frag.h>
|
||||
#include <render-utils/spot_light_frag.h>
|
||||
|
||||
#include <render-utils/standardTransformPNTC_vert.h>
|
||||
#include <render-utils/standardDrawTexture_frag.h>
|
||||
|
||||
|
@ -66,9 +62,6 @@
|
|||
#include <entities-renderer/textured_particle_frag.h>
|
||||
#include <entities-renderer/textured_particle_vert.h>
|
||||
|
||||
#include <render-utils/hit_effect_vert.h>
|
||||
#include <render-utils/hit_effect_frag.h>
|
||||
|
||||
#include <render-utils/overlay3D_vert.h>
|
||||
#include <render-utils/overlay3D_frag.h>
|
||||
|
||||
|
@ -155,11 +148,8 @@ void QTestWindow::draw() {
|
|||
testShaderBuild(simple_vert, simple_frag);
|
||||
testShaderBuild(simple_vert, simple_textured_frag);
|
||||
testShaderBuild(simple_vert, simple_textured_unlit_frag);
|
||||
testShaderBuild(deferred_light_vert, directional_light_frag);
|
||||
testShaderBuild(deferred_light_vert, directional_ambient_light_frag);
|
||||
testShaderBuild(deferred_light_vert, directional_skybox_light_frag);
|
||||
testShaderBuild(deferred_light_point_vert, point_light_frag);
|
||||
testShaderBuild(deferred_light_spot_vert, spot_light_frag);
|
||||
testShaderBuild(standardTransformPNTC_vert, standardDrawTexture_frag);
|
||||
testShaderBuild(standardTransformPNTC_vert, DrawTextureOpaque_frag);
|
||||
|
||||
|
@ -190,7 +180,6 @@ void QTestWindow::draw() {
|
|||
testShaderBuild(ambient_occlusion_vert, ambient_occlusion_frag);
|
||||
testShaderBuild(ambient_occlusion_vert, occlusion_blend_frag);
|
||||
*/
|
||||
testShaderBuild(hit_effect_vert, hit_effect_frag);
|
||||
|
||||
testShaderBuild(overlay3D_vert, overlay3D_frag);
|
||||
|
||||
|
|
|
@ -140,3 +140,77 @@ void GLMHelpersTests::testSimd() {
|
|||
}
|
||||
qDebug() << "Done ";
|
||||
}
|
||||
|
||||
void GLMHelpersTests::testGenerateBasisVectors() {
|
||||
{ // very simple case: primary along X, secondary is linear combination of X and Y
|
||||
glm::vec3 u(1.0f, 0.0f, 0.0f);
|
||||
glm::vec3 v(1.0f, 1.0f, 0.0f);
|
||||
glm::vec3 w;
|
||||
|
||||
generateBasisVectors(u, v, u, v, w);
|
||||
|
||||
QCOMPARE_WITH_ABS_ERROR(u, Vectors::UNIT_X, EPSILON);
|
||||
QCOMPARE_WITH_ABS_ERROR(v, Vectors::UNIT_Y, EPSILON);
|
||||
QCOMPARE_WITH_ABS_ERROR(w, Vectors::UNIT_Z, EPSILON);
|
||||
}
|
||||
|
||||
{ // point primary along Y instead of X
|
||||
glm::vec3 u(0.0f, 1.0f, 0.0f);
|
||||
glm::vec3 v(1.0f, 1.0f, 0.0f);
|
||||
glm::vec3 w;
|
||||
|
||||
generateBasisVectors(u, v, u, v, w);
|
||||
|
||||
QCOMPARE_WITH_ABS_ERROR(u, Vectors::UNIT_Y, EPSILON);
|
||||
QCOMPARE_WITH_ABS_ERROR(v, Vectors::UNIT_X, EPSILON);
|
||||
QCOMPARE_WITH_ABS_ERROR(w, -Vectors::UNIT_Z, EPSILON);
|
||||
}
|
||||
|
||||
{ // pass bad data (both vectors along Y). The helper will guess X for secondary.
|
||||
glm::vec3 u(0.0f, 1.0f, 0.0f);
|
||||
glm::vec3 v(0.0f, 1.0f, 0.0f);
|
||||
glm::vec3 w;
|
||||
|
||||
generateBasisVectors(u, v, u, v, w);
|
||||
|
||||
QCOMPARE_WITH_ABS_ERROR(u, Vectors::UNIT_Y, EPSILON);
|
||||
QCOMPARE_WITH_ABS_ERROR(v, Vectors::UNIT_X, EPSILON);
|
||||
QCOMPARE_WITH_ABS_ERROR(w, -Vectors::UNIT_Z, EPSILON);
|
||||
}
|
||||
|
||||
{ // pass bad data (both vectors along X). The helper will guess X for secondary, fail, then guess Y.
|
||||
glm::vec3 u(1.0f, 0.0f, 0.0f);
|
||||
glm::vec3 v(1.0f, 0.0f, 0.0f);
|
||||
glm::vec3 w;
|
||||
|
||||
generateBasisVectors(u, v, u, v, w);
|
||||
|
||||
QCOMPARE_WITH_ABS_ERROR(u, Vectors::UNIT_X, EPSILON);
|
||||
QCOMPARE_WITH_ABS_ERROR(v, Vectors::UNIT_Y, EPSILON);
|
||||
QCOMPARE_WITH_ABS_ERROR(w, Vectors::UNIT_Z, EPSILON);
|
||||
}
|
||||
|
||||
{ // general case for arbitrary rotation
|
||||
float angle = 1.234f;
|
||||
glm::vec3 axis = glm::normalize(glm::vec3(1.0f, 2.0f, 3.0f));
|
||||
glm::quat rotation = glm::angleAxis(angle, axis);
|
||||
|
||||
// expected values
|
||||
glm::vec3 x = rotation * Vectors::UNIT_X;
|
||||
glm::vec3 y = rotation * Vectors::UNIT_Y;
|
||||
glm::vec3 z = rotation * Vectors::UNIT_Z;
|
||||
|
||||
// primary is along x
|
||||
// secondary is linear combination of x and y
|
||||
// tertiary is unknown
|
||||
glm::vec3 u = 1.23f * x;
|
||||
glm::vec3 v = 2.34f * x + 3.45f * y;
|
||||
glm::vec3 w;
|
||||
|
||||
generateBasisVectors(u, v, u, v, w);
|
||||
|
||||
QCOMPARE_WITH_ABS_ERROR(u, x, EPSILON);
|
||||
QCOMPARE_WITH_ABS_ERROR(v, y, EPSILON);
|
||||
QCOMPARE_WITH_ABS_ERROR(w, z, EPSILON);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ private slots:
|
|||
void testEulerDecomposition();
|
||||
void testSixByteOrientationCompression();
|
||||
void testSimd();
|
||||
void testGenerateBasisVectors();
|
||||
};
|
||||
|
||||
float getErrorDifference(const float& a, const float& b);
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#include "StorageTests.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
QTEST_MAIN(StorageTests)
|
||||
|
||||
using namespace storage;
|
||||
|
@ -32,8 +34,8 @@ void StorageTests::testConversion() {
|
|||
QFileInfo fileInfo(_testFile);
|
||||
QCOMPARE(fileInfo.exists(), false);
|
||||
}
|
||||
StoragePointer storagePointer = std::make_unique<MemoryStorage>(_testData.size(), _testData.data());
|
||||
QCOMPARE(storagePointer->size(), (quint64)_testData.size());
|
||||
StoragePointer storagePointer = std::unique_ptr<MemoryStorage>(new MemoryStorage(_testData.size(), _testData.data()));
|
||||
QCOMPARE(storagePointer->size(), _testData.size());
|
||||
QCOMPARE(memcmp(_testData.data(), storagePointer->data(), _testData.size()), 0);
|
||||
// Convert to a file
|
||||
storagePointer = storagePointer->toFileStorage(_testFile);
|
||||
|
@ -42,12 +44,12 @@ void StorageTests::testConversion() {
|
|||
QCOMPARE(fileInfo.exists(), true);
|
||||
QCOMPARE(fileInfo.size(), (qint64)_testData.size());
|
||||
}
|
||||
QCOMPARE(storagePointer->size(), (quint64)_testData.size());
|
||||
QCOMPARE(storagePointer->size(), _testData.size());
|
||||
QCOMPARE(memcmp(_testData.data(), storagePointer->data(), _testData.size()), 0);
|
||||
|
||||
// Convert to memory
|
||||
storagePointer = storagePointer->toMemoryStorage();
|
||||
QCOMPARE(storagePointer->size(), (quint64)_testData.size());
|
||||
QCOMPARE(storagePointer->size(), _testData.size());
|
||||
QCOMPARE(memcmp(_testData.data(), storagePointer->data(), _testData.size()), 0);
|
||||
{
|
||||
// ensure the file is unaffected
|
||||
|
@ -58,13 +60,13 @@ void StorageTests::testConversion() {
|
|||
|
||||
// truncate the data as a new memory object
|
||||
auto newSize = _testData.size() / 2;
|
||||
storagePointer = std::make_unique<MemoryStorage>(newSize, storagePointer->data());
|
||||
QCOMPARE(storagePointer->size(), (quint64)newSize);
|
||||
storagePointer = std::unique_ptr<Storage>(new MemoryStorage(newSize, storagePointer->data()));
|
||||
QCOMPARE(storagePointer->size(), newSize);
|
||||
QCOMPARE(memcmp(_testData.data(), storagePointer->data(), newSize), 0);
|
||||
|
||||
// Convert back to file
|
||||
storagePointer = storagePointer->toFileStorage(_testFile);
|
||||
QCOMPARE(storagePointer->size(), (quint64)newSize);
|
||||
QCOMPARE(storagePointer->size(), newSize);
|
||||
QCOMPARE(memcmp(_testData.data(), storagePointer->data(), newSize), 0);
|
||||
{
|
||||
// ensure the file is truncated
|
||||
|
|
Loading…
Reference in a new issue