Merge branch 'master' into DOC-102

This commit is contained in:
David Rowe 2019-07-20 09:13:52 +12:00
commit 0a32386f45
306 changed files with 3683 additions and 4996 deletions

View file

@ -268,6 +268,7 @@ macro(AUTOSCRIBE_SHADER_LIB)
set(PROGRAM_ENUMS "namespace program { enum {\n")
foreach(PROGRAM_FILE ${SHADER_PROGRAM_FILES})
get_filename_component(PROGRAM_NAME ${PROGRAM_FILE} NAME_WE)
get_filename_component(PROGRAM_FOLDER ${PROGRAM_FILE} DIRECTORY)
file(READ ${PROGRAM_FILE} PROGRAM_CONFIG)
set(AUTOSCRIBE_PROGRAM_VERTEX ${PROGRAM_NAME})
set(AUTOSCRIBE_PROGRAM_FRAGMENT ${PROGRAM_NAME})
@ -315,7 +316,11 @@ macro(AUTOSCRIBE_SHADER_LIB)
if (HAS_FRAGMENT EQUAL -1)
set(DEFINES "${VERTEX_DEFINES}")
set(SHADER_LIST "")
set(SHADER_FILE "${SRC_FOLDER}/${VERTEX_NAME}.slv")
set(SHADER_FILE "${PROGRAM_FOLDER}/${VERTEX_NAME}.slv")
if (NOT EXISTS "${SHADER_FILE}")
set(SHADER_FILE "${PROGRAM_FOLDER}/../${VERTEX_NAME}.slv")
endif()
find_file(SHADER_FILE "" PATHS "${PROGRAM_FOLDER}" PATH_SUFFIXES ".." NO_DEFAULT_PATH)
AUTOSCRIBE_SHADER(${ALL_SHADER_HEADERS})
string(CONCAT VERTEX_ENUMS "${VERTEX_ENUMS}" "${SHADER_LIST}")
else()
@ -331,7 +336,10 @@ macro(AUTOSCRIBE_SHADER_LIB)
if (HAS_VERTEX EQUAL -1)
set(DEFINES "${FRAGMENT_DEFINES}")
set(SHADER_LIST "")
set(SHADER_FILE "${SRC_FOLDER}/${FRAGMENT_NAME}.slf")
set(SHADER_FILE "${PROGRAM_FOLDER}/${FRAGMENT_NAME}.slf")
if (NOT EXISTS "${SHADER_FILE}")
set(SHADER_FILE "${PROGRAM_FOLDER}/../${FRAGMENT_NAME}.slf")
endif()
AUTOSCRIBE_SHADER(${ALL_SHADER_HEADERS})
string(CONCAT FRAGMENT_ENUMS "${FRAGMENT_ENUMS}" "${SHADER_LIST}")
else()

View file

@ -52,14 +52,8 @@ macro(setup_qt)
message(FATAL_ERROR "VCPKG_QT_CMAKE_PREFIX_PATH should have been set by hifi_vcpkg.py")
endif()
if (NOT DEV_BUILD)
if (UNIX AND DEFINED ENV{QT_CMAKE_PREFIX_PATH} AND NOT APPLE)
# HACK: obey QT_CMAKE_PREFIX_PATH to allow UNIX to use older QT libs
message("HACK: obey QT_CMAKE_PREFIX_PATH on UNIX")
set(QT_CMAKE_PREFIX_PATH $ENV{QT_CMAKE_PREFIX_PATH})
else()
message("override QT_CMAKE_PREFIX_PATH with VCPKG_QT_CMAKE_PREFIX_PATH")
set(QT_CMAKE_PREFIX_PATH ${VCPKG_QT_CMAKE_PREFIX_PATH})
endif()
message("override QT_CMAKE_PREFIX_PATH with VCPKG_QT_CMAKE_PREFIX_PATH")
set(QT_CMAKE_PREFIX_PATH ${VCPKG_QT_CMAKE_PREFIX_PATH})
else()
# DEV_BUILD
if (DEFINED ENV{QT_CMAKE_PREFIX_PATH})

View file

@ -259,7 +259,7 @@ endif()
url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-macos3.tar.gz'
elif platform.system() == 'Linux':
if platform.linux_distribution()[1][:3] == '16.':
url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-ubuntu-16.04.tar.gz'
url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-ubuntu-16.04-with-symbols.tar.gz'
elif platform.linux_distribution()[1][:3] == '18.':
url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-ubuntu-18.04.tar.gz'
else:

Binary file not shown.

View file

@ -30,7 +30,6 @@ Windows.Window {
signal selfDestruct();
property var flags: 0;
property var additionalFlags: 0;
property var overrideFlags: 0;
@ -158,8 +157,7 @@ Windows.Window {
if (Qt.platform.os !== "windows" && (root.additionalFlags & Desktop.ALWAYS_ON_TOP)) {
nativeWindowFlags |= Qt.WindowStaysOnTopHint;
}
root.flags = root.overrideFlags || nativeWindowFlags;
nativeWindow.flags = root.flags;
nativeWindow.flags = root.overrideFlags || nativeWindowFlags;
nativeWindow.x = interactiveWindowPosition.x;
nativeWindow.y = interactiveWindowPosition.y;
@ -317,7 +315,7 @@ Windows.Window {
// set invisible on close, to make it not re-appear unintended after switching PresentationMode
interactiveWindowVisible = false;
if ((root.flags & Desktop.CLOSE_BUTTON_HIDES) !== Desktop.CLOSE_BUTTON_HIDES) {
if ((root.additionalFlags & Desktop.CLOSE_BUTTON_HIDES) !== Desktop.CLOSE_BUTTON_HIDES) {
selfDestruct();
}
}

View file

@ -22,6 +22,7 @@ FocusScope {
property alias editable: comboBox.editable
property alias comboBox: comboBox
readonly property alias currentText: comboBox.currentText;
property alias displayText: comboBox.displayText;
property alias currentIndex: comboBox.currentIndex;
property int currentHighLightedIndex: comboBox.currentIndex;

View file

@ -0,0 +1,379 @@
//
// GraphicsSettings.qml
// qml\hifi\dialogs\graphics
//
// Created by Zach Fox on 2019-07-10
// Copyright 2019 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
//
import Hifi 1.0 as Hifi
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.12
import stylesUit 1.0 as HifiStylesUit
import controlsUit 1.0 as HifiControlsUit
import "qrc:////qml//controls" as HifiControls
import PerformanceEnums 1.0
Item {
HifiStylesUit.HifiConstants { id: hifi; }
id: root;
anchors.fill: parent
ColumnLayout {
id: graphicsSettingsColumnLayout
anchors.left: parent.left
anchors.leftMargin: 26
anchors.right: parent.right
anchors.rightMargin: 26
anchors.top: parent.top
anchors.topMargin: HMD.active ? 80 : 0
spacing: 8
ColumnLayout {
Layout.preferredWidth: parent.width
Layout.topMargin: 18
spacing: 0
HifiStylesUit.RalewayRegular {
text: "GRAPHICS SETTINGS"
Layout.maximumWidth: parent.width
height: 30
size: 16
color: "#FFFFFF"
}
ColumnLayout {
Layout.topMargin: 10
Layout.preferredWidth: parent.width
spacing: 0
HifiControlsUit.RadioButton {
id: performanceLow
colorScheme: hifi.colorSchemes.dark
height: 18
fontSize: 16
leftPadding: 0
text: "Low"
checked: Performance.getPerformancePreset() === PerformanceEnums.LOW
onClicked: {
Performance.setPerformancePreset(PerformanceEnums.LOW);
root.refreshAllDropdowns();
}
}
HifiControlsUit.RadioButton {
id: performanceMedium
colorScheme: hifi.colorSchemes.dark
height: 18
fontSize: 16
leftPadding: 0
text: "Medium"
checked: Performance.getPerformancePreset() === PerformanceEnums.MID
onClicked: {
Performance.setPerformancePreset(PerformanceEnums.MID);
root.refreshAllDropdowns();
}
}
HifiControlsUit.RadioButton {
id: performanceHigh
colorScheme: hifi.colorSchemes.dark
height: 18
fontSize: 16
leftPadding: 0
text: "High"
checked: Performance.getPerformancePreset() === PerformanceEnums.HIGH
onClicked: {
Performance.setPerformancePreset(PerformanceEnums.HIGH);
root.refreshAllDropdowns();
}
}
HifiControlsUit.RadioButton {
id: performanceCustom
colorScheme: hifi.colorSchemes.dark
height: 18
fontSize: 16
leftPadding: 0
text: "Custom"
checked: Performance.getPerformancePreset() === PerformanceEnums.UNKNOWN
onClicked: {
Performance.setPerformancePreset(PerformanceEnums.UNKNOWN);
}
}
}
ColumnLayout {
Layout.topMargin: 10
Layout.preferredWidth: parent.width
spacing: 0
Item {
Layout.preferredWidth: parent.width
Layout.preferredHeight: 35
HifiStylesUit.RalewayRegular {
id: worldDetailHeader
text: "World Detail"
anchors.left: parent.left
anchors.top: parent.top
width: 130
height: parent.height
size: 16
color: "#FFFFFF"
}
ListModel {
id: worldDetailModel
ListElement {
text: "Low World Detail"
worldDetailQualityValue: 0.25
}
ListElement {
text: "Medium World Detail"
worldDetailQualityValue: 0.5
}
ListElement {
text: "Full World Detail"
worldDetailQualityValue: 0.75
}
}
HifiControlsUit.ComboBox {
id: worldDetailDropdown
enabled: performanceCustom.checked
anchors.left: worldDetailHeader.right
anchors.leftMargin: 20
anchors.top: parent.top
width: 280
height: parent.height
colorScheme: hifi.colorSchemes.dark
model: worldDetailModel
currentIndex: -1
function refreshWorldDetailDropdown() {
var currentWorldDetailQuality = LODManager.worldDetailQuality;
if (currentWorldDetailQuality <= 0.25) {
worldDetailDropdown.currentIndex = 0;
} else if (currentWorldDetailQuality <= 0.5) {
worldDetailDropdown.currentIndex = 1;
} else {
worldDetailDropdown.currentIndex = 2;
}
}
Component.onCompleted: {
worldDetailDropdown.refreshWorldDetailDropdown();
}
onCurrentIndexChanged: {
LODManager.worldDetailQuality = model.get(currentIndex).worldDetailQualityValue;
worldDetailDropdown.displayText = model.get(currentIndex).text;
}
}
}
Item {
Layout.preferredWidth: parent.width
Layout.preferredHeight: 35
Layout.topMargin: 20
HifiStylesUit.RalewayRegular {
id: renderingEffectsHeader
text: "Rendering Effects"
anchors.left: parent.left
anchors.top: parent.top
width: 130
height: parent.height
size: 16
color: "#FFFFFF"
}
ListModel {
id: renderingEffectsModel
ListElement {
text: "No Rendering Effects"
preferredRenderMethod: 1 // "FORWARD"
shadowsEnabled: false
}
ListElement {
text: "Local Lights, Fog, Bloom"
preferredRenderMethod: 0 // "DEFERRED"
shadowsEnabled: false
}
ListElement {
text: "Local Lights, Fog, Bloom, Shadows"
preferredRenderMethod: 0 // "DEFERRED"
shadowsEnabled: true
}
}
HifiControlsUit.ComboBox {
id: renderingEffectsDropdown
enabled: performanceCustom.checked
anchors.left: renderingEffectsHeader.right
anchors.leftMargin: 20
anchors.top: parent.top
width: 280
height: parent.height
colorScheme: hifi.colorSchemes.dark
model: renderingEffectsModel
currentIndex: -1
function refreshRenderingEffectsDropdownDisplay() {
if (Render.shadowsEnabled) {
renderingEffectsDropdown.currentIndex = 2;
} else if (Render.renderMethod === 0) {
renderingEffectsDropdown.currentIndex = 1;
} else {
renderingEffectsDropdown.currentIndex = 0;
}
}
Component.onCompleted: {
renderingEffectsDropdown.refreshRenderingEffectsDropdownDisplay();
}
onCurrentIndexChanged: {
var renderMethodToSet = 1;
if (model.get(currentIndex).preferredRenderMethod === 0 &&
PlatformInfo.isRenderMethodDeferredCapable()) {
renderMethodToSet = 0;
}
Render.renderMethod = renderMethodToSet;
Render.shadowsEnabled = model.get(currentIndex).shadowsEnabled;
renderingEffectsDropdown.displayText = model.get(currentIndex).text;
}
}
}
Item {
Layout.preferredWidth: parent.width
Layout.preferredHeight: 35
Layout.topMargin: 20
HifiStylesUit.RalewayRegular {
id: refreshRateHeader
text: "Refresh Rate"
anchors.left: parent.left
anchors.top: parent.top
width: 130
height: parent.height
size: 16
color: "#FFFFFF"
}
ListModel {
id: refreshRateModel
ListElement {
text: "Economical"
refreshRatePreset: 0 // RefreshRateProfile::ECO
}
ListElement {
text: "Interactive"
refreshRatePreset: 1 // RefreshRateProfile::INTERACTIVE
}
ListElement {
text: "Real-Time"
refreshRatePreset: 2 // RefreshRateProfile::REALTIME
}
}
HifiControlsUit.ComboBox {
id: refreshRateDropdown
enabled: performanceCustom.checked
anchors.left: refreshRateHeader.right
anchors.leftMargin: 20
anchors.top: parent.top
width: 280
height: parent.height
colorScheme: hifi.colorSchemes.dark
model: refreshRateModel
currentIndex: -1
function refreshRefreshRateDropdownDisplay() {
if (Performance.getRefreshRateProfile() === 0) {
refreshRateDropdown.currentIndex = 0;
} else if (Performance.getRefreshRateProfile() === 1) {
refreshRateDropdown.currentIndex = 1;
} else {
refreshRateDropdown.currentIndex = 2;
}
}
Component.onCompleted: {
refreshRateDropdown.refreshRefreshRateDropdownDisplay();
}
onCurrentIndexChanged: {
Performance.setRefreshRateProfile(model.get(currentIndex).refreshRatePreset);
refreshRateDropdown.displayText = model.get(currentIndex).text;
}
}
}
Item {
Layout.preferredWidth: parent.width
Layout.preferredHeight: 35
Layout.topMargin: 16
HifiStylesUit.RalewayRegular {
id: resolutionHeader
text: "Resolution Scale (" + Number.parseFloat(Render.viewportResolutionScale).toPrecision(3) + ")"
anchors.left: parent.left
anchors.top: parent.top
width: 130
height: parent.height
size: 16
color: "#FFFFFF"
}
HifiControlsUit.Slider {
id: resolutionScaleSlider
enabled: performanceCustom.checked
anchors.left: resolutionHeader.right
anchors.leftMargin: 57
anchors.top: parent.top
width: 150
height: parent.height
colorScheme: hifi.colorSchemes.dark
minimumValue: 0.25
maximumValue: 1.0
stepSize: 0.02
value: Render.viewportResolutionScale
live: true
function updateResolutionScale(sliderValue) {
if (Render.viewportResolutionScale !== sliderValue) {
Render.viewportResolutionScale = sliderValue;
}
}
onValueChanged: {
updateResolutionScale(value);
}
onPressedChanged: {
if (!pressed) {
updateResolutionScale(value);
}
}
}
}
}
}
}
function refreshAllDropdowns() {
worldDetailDropdown.refreshWorldDetailDropdown();
renderingEffectsDropdown.refreshRenderingEffectsDropdownDisplay();
refreshRateDropdown.refreshRefreshRateDropdownDisplay();
}
}

View file

@ -91,7 +91,7 @@ Item {
SimplifiedControls.TextField {
id: myDisplayNameText
text: MyAvatar.sessionDisplayName === "" ? MyAvatar.displayName : MyAvatar.sessionDisplayName
text: MyAvatar.displayName
maximumLength: 256
clip: true
selectByMouse: true

View file

@ -257,6 +257,10 @@ extern "C" {
}
#endif
#ifdef Q_OS_MAC
#include "MacHelper.h"
#endif
#if defined(Q_OS_ANDROID)
#include <android/log.h>
#include "AndroidHelper.h"
@ -960,6 +964,9 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
DependencyManager::set<KeyboardScriptingInterface>();
DependencyManager::set<GrabManager>();
DependencyManager::set<AvatarPackager>();
#ifdef Q_OS_MAC
DependencyManager::set<MacHelper>();
#endif
QString setBookmarkValue = getCmdOption(argc, constArgv, "--setBookmark");
if (!setBookmarkValue.isEmpty()) {
@ -1187,6 +1194,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
}
auto accountManager = DependencyManager::get<AccountManager>();
// set the account manager's root URL and trigger a login request if we don't have the access token
accountManager->setIsAgent(true);
accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL());
if (!accountManager->hasKeyPair()) {
accountManager->generateNewUserKeypair();
}
#ifndef Q_OS_ANDROID
_logger->setSessionID(accountManager->getSessionID());
#endif
@ -1334,10 +1348,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
#endif
connect(accountManager.data(), &AccountManager::usernameChanged, this, &Application::updateWindowTitle);
// set the account manager's root URL and trigger a login request if we don't have the access token
accountManager->setIsAgent(true);
accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL());
// use our MyAvatar position and quat for address manager path
addressManager->setPositionGetter([] {
auto avatarManager = DependencyManager::get<AvatarManager>();
@ -2807,7 +2817,7 @@ void Application::cleanupBeforeQuit() {
DependencyManager::destroy<TabletScriptingInterface>();
DependencyManager::destroy<ToolbarScriptingInterface>();
DependencyManager::destroy<OffscreenUi>();
DependencyManager::destroy<OffscreenQmlSurfaceCache>();
_snapshotSoundInjector = nullptr;
@ -2853,6 +2863,9 @@ Application::~Application() {
_gameWorkload.shutdown();
DependencyManager::destroy<Preferences>();
#ifdef Q_OS_MAC
DependencyManager::destroy<MacHelper>();
#endif
_entityClipboard->eraseAllOctreeElements();
_entityClipboard.reset();
@ -4429,27 +4442,6 @@ void Application::keyPressEvent(QKeyEvent* event) {
}
break;
case Qt::Key_P: {
if (!isShifted && !isMeta && !isOption && !event->isAutoRepeat()) {
AudioInjectorOptions options;
options.localOnly = true;
options.positionSet = false; // system sound
options.stereo = true;
Setting::Handle<bool> notificationSounds{ MenuOption::NotificationSounds, true };
Setting::Handle<bool> notificationSoundSnapshot{ MenuOption::NotificationSoundsSnapshot, true };
if (notificationSounds.get() && notificationSoundSnapshot.get()) {
if (_snapshotSoundInjector) {
DependencyManager::get<AudioInjectorManager>()->setOptionsAndRestart(_snapshotSoundInjector, options);
} else {
_snapshotSoundInjector = DependencyManager::get<AudioInjectorManager>()->playSound(_snapshotSound, options);
}
}
takeSnapshot(true);
}
break;
}
case Qt::Key_Apostrophe: {
if (isMeta) {
auto cursor = Cursor::Manager::instance().getCursor();
@ -5994,6 +5986,7 @@ void Application::resetPhysicsReadyInformation() {
_gpuTextureMemSizeStabilityCount = 0;
_gpuTextureMemSizeAtLastCheck = 0;
_physicsEnabled = false;
_octreeProcessor.stopSafeLanding();
}
void Application::reloadResourceCaches() {
@ -6253,6 +6246,7 @@ void Application::tryToEnablePhysics() {
// We keep physics disabled until we've received a full scene and everything near the avatar in that
// scene is ready to compute its collision shape.
if (getMyAvatar()->isReadyForPhysics()) {
_octreeProcessor.resetSafeLanding();
_physicsEnabled = true;
setIsInterstitialMode(false);
getMyAvatar()->updateMotionBehaviorFromMenu();
@ -6776,6 +6770,12 @@ void Application::update(float deltaTime) {
if (!getActiveDisplayPlugin()->isActive()) {
getMain3DScene()->processTransactionQueue();
}
// decide if the sensorToWorldMatrix is changing in a way that warrents squeezing the edges of the view down
if (getActiveDisplayPlugin()->isHmd()) {
PerformanceTimer perfTimer("squeezeVision");
_visionSqueeze.updateVisionSqueeze(myAvatar->getSensorToWorldMatrix(), deltaTime);
}
}
void Application::updateRenderArgs(float deltaTime) {
@ -6982,13 +6982,16 @@ int Application::sendNackPackets() {
}
void Application::queryOctree(NodeType_t serverType, PacketType packetType) {
if (!_settingsLoaded) {
return; // bail early if settings are not loaded
}
const bool isModifiedQuery = !_physicsEnabled;
if (isModifiedQuery) {
if (!_octreeProcessor.safeLandingIsActive()) {
// don't send the octreeQuery until SafeLanding knows it has started
return;
}
// Create modified view that is a simple sphere.
bool interstitialModeEnabled = DependencyManager::get<NodeList>()->getDomainHandler().getInterstitialModeEnabled();
@ -7211,7 +7214,6 @@ void Application::clearDomainOctreeDetails(bool clearAll) {
void Application::domainURLChanged(QUrl domainURL) {
// disable physics until we have enough information about our new location to not cause craziness.
resetPhysicsReadyInformation();
setIsServerlessMode(domainURL.scheme() != URL_SCHEME_HIFI);
if (isServerlessMode()) {
loadServerlessDomain(domainURL);
@ -7221,7 +7223,6 @@ void Application::domainURLChanged(QUrl domainURL) {
void Application::goToErrorDomainURL(QUrl errorDomainURL) {
// disable physics until we have enough information about our new location to not cause craziness.
resetPhysicsReadyInformation();
setIsServerlessMode(errorDomainURL.scheme() != URL_SCHEME_HIFI);
if (isServerlessMode()) {
loadErrorDomain(errorDomainURL);
@ -7238,12 +7239,12 @@ void Application::resettingDomain() {
void Application::nodeAdded(SharedNodePointer node) {
if (node->getType() == NodeType::EntityServer) {
if (_failedToConnectToEntityServer && !_entityServerConnectionTimer.isActive()) {
_failedToConnectToEntityServer = false;
_octreeProcessor.stopSafeLanding();
_octreeProcessor.startSafeLanding();
_failedToConnectToEntityServer = false;
} else if (_entityServerConnectionTimer.isActive()) {
_entityServerConnectionTimer.stop();
}
_octreeProcessor.startSafeLanding();
_entityServerConnectionTimer.setInterval(ENTITY_SERVER_CONNECTION_TIMEOUT);
_entityServerConnectionTimer.start();
}
@ -7318,7 +7319,7 @@ void Application::nodeKilled(SharedNodePointer node) {
_octreeProcessor.nodeKilled(node);
_entityEditSender.nodeKilled(node);
if (node->getType() == NodeType::AudioMixer) {
QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(), "audioMixerKilled");
} else if (node->getType() == NodeType::EntityServer) {

View file

@ -78,6 +78,7 @@
#include <ModelScriptingInterface.h>
#include "Sound.h"
#include "VisionSqueeze.h"
class GLCanvas;
class FaceTracker;
@ -364,6 +365,9 @@ public:
void forceLoginWithTokens(const QString& tokens);
void setConfigFileURL(const QString& fileUrl);
// used by preferences and HMDScriptingInterface...
VisionSqueeze& getVisionSqueeze() { return _visionSqueeze; }
signals:
void svoImportRequested(const QString& url);
@ -731,6 +735,7 @@ private:
bool _loginDialogPoppedUp{ false };
bool _desktopRootItemCreated{ false };
bool _developerMenuVisible{ false };
QString _previousAvatarSkeletonModel;
float _previousAvatarTargetScale;
@ -837,5 +842,7 @@ private:
bool _resumeAfterLoginDialogActionTaken_SafeToRun { false };
bool _startUpFinished { false };
bool _overrideEntry { false };
VisionSqueeze _visionSqueeze;
};
#endif // hifi_Application_h

58
interface/src/MacHelper.cpp Executable file
View file

@ -0,0 +1,58 @@
//
// MacHelper.h
// interface/src
//
// Created by Howard Stearns
// Copyright 2019 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 "InterfaceLogging.h"
#include "MacHelper.h"
#include <NodeList.h>
#ifdef Q_OS_MAC
#include <IOKit/IOMessage.h>
#include <IOKit/pwr_mgt/IOPMLib.h>
// The type definitions in these variables come from IOKit, which includes a definition of Duration that conflicts with ours.
// So... we include these definitions here rather than in the .h, as the .h is included in Application.cpp which
// uses Duration.
static io_connect_t root_port;
static IONotificationPortRef notifyPortRef;
static io_object_t notifierObject;
static void* refCon;
static void sleepHandler(void* refCon, io_service_t service, natural_t messageType, void* messageArgument) {
if (messageType == kIOMessageSystemHasPoweredOn) {
qCInfo(interfaceapp) << "Waking up from sleep or hybernation.";
QMetaObject::invokeMethod(DependencyManager::get<NodeList>().data(), "noteAwakening", Qt::QueuedConnection);
}
}
#endif
MacHelper::MacHelper() {
#ifdef Q_OS_MAC
root_port = IORegisterForSystemPower(refCon, &notifyPortRef, sleepHandler, &notifierObject);
if (root_port == 0) {
qCWarning(interfaceapp) << "IORegisterForSystemPower failed";
return;
}
CFRunLoopAddSource(CFRunLoopGetCurrent(),
IONotificationPortGetRunLoopSource(notifyPortRef),
kCFRunLoopCommonModes);
#endif
}
MacHelper::~MacHelper() {
#ifdef Q_OS_MAC
CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
IONotificationPortGetRunLoopSource(notifyPortRef),
kCFRunLoopCommonModes);
IODeregisterForSystemPower(&notifierObject);
IOServiceClose(root_port);
IONotificationPortDestroy(notifyPortRef);
#endif
}

21
interface/src/MacHelper.h Executable file
View file

@ -0,0 +1,21 @@
//
// MacHelper.h
// interface/src
//
// Created by Howard Stearns
// Copyright 2019 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
#include "DependencyManager.h"
class MacHelper : public Dependency {
public:
MacHelper();
~MacHelper();
};

View file

@ -266,8 +266,13 @@ Menu::Menu() {
// Settings > Graphics...
action = addActionToQMenuAndActionHash(settingsMenu, "Graphics...");
connect(action, &QAction::triggered, [] {
qApp->showDialog(QString("hifi/dialogs/GraphicsPreferencesDialog.qml"),
QString("hifi/tablet/TabletGraphicsPreferences.qml"), "GraphicsPreferencesDialog");
auto tablet = DependencyManager::get<TabletScriptingInterface>()->getTablet("com.highfidelity.interface.tablet.system");
auto hmd = DependencyManager::get<HMDScriptingInterface>();
tablet->pushOntoStack("hifi/dialogs/graphics/GraphicsSettings.qml");
if (!hmd->getShouldShowTablet()) {
hmd->toggleShouldShowTablet();
}
});
// Settings > Security...

View file

@ -92,7 +92,7 @@ void PerformanceManager::applyPerformancePreset(PerformanceManager::PerformanceP
RenderScriptingInterface::getInstance()->setShadowsEnabled(true);
qApp->getRefreshRateManager().setRefreshRateProfile(RefreshRateManager::RefreshRateProfile::REALTIME);
DependencyManager::get<LODManager>()->setWorldDetailQuality(0.5f);
DependencyManager::get<LODManager>()->setWorldDetailQuality(0.75f);
break;
case PerformancePreset::MID:
@ -114,7 +114,7 @@ void PerformanceManager::applyPerformancePreset(PerformanceManager::PerformanceP
RenderScriptingInterface::getInstance()->setViewportResolutionScale(recommandedPpiScale);
DependencyManager::get<LODManager>()->setWorldDetailQuality(0.75f);
DependencyManager::get<LODManager>()->setWorldDetailQuality(0.25f);
break;
case PerformancePreset::UNKNOWN:

View file

@ -0,0 +1,213 @@
//
// VisionSqueeze.cpp
// interface/src
//
// Created by Seth Alves on 2019-3-13.
// Copyright 2019 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 "VisionSqueeze.h"
#include <glm/gtx/matrix_decompose.hpp>
#include <glm/gtc/epsilon.hpp>
#include <display-plugins/hmd/HmdDisplayPlugin.h>
#include "Application.h"
VisionSqueeze::VisionSqueeze() :
_visionSqueezeEnabled(_visionSqueezeEnabledSetting.get()),
_visionSqueezeRatioX(_visionSqueezeRatioXSetting.get()),
_visionSqueezeRatioY(_visionSqueezeRatioYSetting.get()),
_visionSqueezeUnSqueezeDelay(_visionSqueezeUnSqueezeDelaySetting.get()),
_visionSqueezeUnSqueezeSpeed(_visionSqueezeUnSqueezeSpeedSetting.get()),
_visionSqueezeTransition(_visionSqueezeTransitionSetting.get()),
_visionSqueezePerEye(_visionSqueezePerEyeSetting.get()),
_visionSqueezeGroundPlaneY(_visionSqueezeGroundPlaneYSetting.get()),
_visionSqueezeSpotlightSize(_visionSqueezeSpotlightSizeSetting.get()),
_visionSqueezeTurningXFactor(_visionSqueezeTurningXFactorSetting.get()),
_visionSqueezeTurningYFactor(_visionSqueezeTurningYFactorSetting.get()) {
}
void VisionSqueeze::setVisionSqueezeEnabled(bool value) {
if (value != _visionSqueezeEnabled) {
_visionSqueezeEnabled = value;
_visionSqueezeEnabledSetting.set(_visionSqueezeEnabled);
}
}
void VisionSqueeze::setVisionSqueezeRatioX(float value) {
if (value != _visionSqueezeRatioX) {
_visionSqueezeRatioX = value;
_visionSqueezeRatioXSetting.set(_visionSqueezeRatioX);
}
}
void VisionSqueeze::setVisionSqueezeRatioY(float value) {
if (value != _visionSqueezeRatioY) {
_visionSqueezeRatioY = value;
_visionSqueezeRatioYSetting.set(_visionSqueezeRatioY);
}
}
void VisionSqueeze::setVisionSqueezeUnSqueezeDelay(float value) {
if (value != _visionSqueezeUnSqueezeDelay) {
_visionSqueezeUnSqueezeDelay = value;
_visionSqueezeUnSqueezeDelaySetting.set(_visionSqueezeUnSqueezeDelay);
}
}
void VisionSqueeze::setVisionSqueezeUnSqueezeSpeed(float value) {
if (value != _visionSqueezeUnSqueezeSpeed) {
_visionSqueezeUnSqueezeSpeed = value;
_visionSqueezeUnSqueezeSpeedSetting.set(_visionSqueezeUnSqueezeSpeed);
}
}
void VisionSqueeze::setVisionSqueezeTransition(float value) {
if (value != _visionSqueezeTransition) {
_visionSqueezeTransition = value;
_visionSqueezeTransitionSetting.set(_visionSqueezeTransition);
}
}
void VisionSqueeze::setVisionSqueezePerEye(int value) {
if (value != _visionSqueezePerEye) {
_visionSqueezePerEye = value;
_visionSqueezePerEyeSetting.set(_visionSqueezePerEye);
}
}
void VisionSqueeze::setVisionSqueezeGroundPlaneY(float value) {
if (value != _visionSqueezeGroundPlaneY) {
_visionSqueezeGroundPlaneY = value;
_visionSqueezeGroundPlaneYSetting.set(_visionSqueezeGroundPlaneY);
}
}
void VisionSqueeze::setVisionSqueezeSpotlightSize(float value) {
if (value != _visionSqueezeSpotlightSize) {
_visionSqueezeSpotlightSize = value;
_visionSqueezeSpotlightSizeSetting.set(_visionSqueezeSpotlightSize);
}
}
void VisionSqueeze::setVisionSqueezeTurningXFactor(float value) {
if (value != _visionSqueezeTurningXFactor) {
_visionSqueezeTurningXFactor = value;
_visionSqueezeTurningXFactorSetting.set(_visionSqueezeTurningXFactor);
}
}
void VisionSqueeze::setVisionSqueezeTurningYFactor(float value) {
if (value != _visionSqueezeTurningYFactor) {
_visionSqueezeTurningYFactor = value;
_visionSqueezeTurningYFactorSetting.set(_visionSqueezeTurningYFactor);
}
}
void VisionSqueeze::updateVisionSqueeze(const glm::mat4& sensorToWorldMatrix, float deltaTime) {
const float SENSOR_TO_WORLD_TRANS_EPSILON = 0.0001f;
const float SENSOR_TO_WORLD_TRANS_Y_EPSILON = 0.01f;
const float SENSOR_TO_WORLD_TRANS_ITS_A_TELEPORT_SQUARED = 2.0f;
const float SENSOR_TO_WORLD_ROT_EPSILON = 0.000005f;
const float SENSOR_TO_WORLD_ROT_ITS_A_SNAP_TURN = 0.99f;
const float VISION_SQUEEZE_TP_LOCKOUT = 0.1f; // seconds
glm::vec3 scale;
glm::quat rotation;
glm::vec3 translation;
glm::vec3 skew;
glm::vec4 perspective;
glm::decompose(sensorToWorldMatrix, scale, rotation, translation, skew, perspective);
if (!_visionSqueezeEnabled) {
_squeezeVision = false;
_squeezeVisionTurning = false;
} else if (_visionSqueezeLockout > 0.0f) {
_visionSqueezeLockout -= deltaTime;
} else {
_squeezeVision = false;
_squeezeVisionTurning = false;
glm::vec3 absTransDelta = glm::abs(translation - _prevTranslation);
float rotDot = fabsf(glm::dot(rotation, _prevRotation));
// if the avatar has just teleported or snap-turned, briefly disable triggering of vision-squeeze
if (glm::length2(translation - _prevTranslation) > SENSOR_TO_WORLD_TRANS_ITS_A_TELEPORT_SQUARED ||
rotDot < SENSOR_TO_WORLD_ROT_ITS_A_SNAP_TURN) {
_visionSqueezeLockout = VISION_SQUEEZE_TP_LOCKOUT;
_squeezeVision = true;
_squeezeVisionTurning = true;
} else if (rotDot < 1.0f - SENSOR_TO_WORLD_ROT_EPSILON) {
_squeezeVision = true;
_squeezeVisionTurning = true;
} else if (absTransDelta.x > SENSOR_TO_WORLD_TRANS_EPSILON ||
absTransDelta.y > SENSOR_TO_WORLD_TRANS_Y_EPSILON ||
absTransDelta.z > SENSOR_TO_WORLD_TRANS_EPSILON) {
_squeezeVision = true;
_squeezeVisionTurning = false;
}
}
_prevTranslation = translation;
_prevRotation = rotation;
static quint64 lastSqueezeTime = 0;
quint64 now = usecTimestampNow();
static float visionSqueezeX = 0.0f; // 0.0 -- unobstructed, 1.0 -- fully blocked
static float visionSqueezeY = 0.0f; // 0.0 -- unobstructed, 1.0 -- fully blocked
if (_squeezeVision) {
float ratioX = getVisionSqueezeRatioX();
float ratioY = getVisionSqueezeRatioY();
if (ratioX >= 0.0f) {
if (_squeezeVisionTurning) {
ratioX += (1.0f - ratioX) * getVisionSqueezeTurningXFactor();
}
float newVisionSqueezeX = ratioX;
if (newVisionSqueezeX >= visionSqueezeX) {
lastSqueezeTime = now;
visionSqueezeX = newVisionSqueezeX;
}
} else {
visionSqueezeX = -1.0f;
}
if (ratioY >= 0.0f) {
float newVisionSqueezeY = ratioY;
if (newVisionSqueezeY >= visionSqueezeY) {
lastSqueezeTime = now;
visionSqueezeY = newVisionSqueezeY;
}
} else {
visionSqueezeY = -1.0f;
}
}
float unsqueezeAmount = deltaTime * getVisionSqueezeUnSqueezeSpeed();
if (now - lastSqueezeTime > getVisionSqueezeUnSqueezeDelay() * USECS_PER_SECOND) {
visionSqueezeX -= unsqueezeAmount;
if (visionSqueezeX < 0.0f) {
visionSqueezeX = -1.0f;
}
visionSqueezeY -= unsqueezeAmount;
if (visionSqueezeY < 0.0f) {
visionSqueezeY = -1.0f;
}
}
std::shared_ptr<HmdDisplayPlugin> hmdDisplayPlugin =
std::dynamic_pointer_cast<HmdDisplayPlugin>(qApp->getActiveDisplayPlugin());
if (hmdDisplayPlugin) {
hmdDisplayPlugin->updateVisionSqueezeParameters(visionSqueezeX, visionSqueezeY,
getVisionSqueezeTransition(),
getVisionSqueezePerEye(),
getVisionSqueezeGroundPlaneY(),
getVisionSqueezeSpotlightSize());
}
}

View file

@ -0,0 +1,108 @@
//
// VisionSqueeze.h
// interface/src
//
// Created by Seth Alves on 2019-3-13.
// Copyright 2019 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_VisionSqueeze_h
#define hifi_VisionSqueeze_h
#include <memory>
#include <glm/glm.hpp>
#include <SettingHandle.h>
static const float DEFAULT_VISION_SQUEEZE_TURNING_X_FACTOR = 0.51f;
static const float DEFAULT_VISION_SQUEEZE_TURNING_Y_FACTOR = 0.36f;
static const float DEFAULT_VISION_SQUEEZE_UNSQUEEZE_DELAY = 0.2f; // seconds
static const float DEFAULT_VISION_SQUEEZE_UNSQUEEZE_SPEED = 3.0f;
static const float DEFAULT_VISION_SQUEEZE_TRANSITION = 0.25f;
static const int DEFAULT_VISION_SQUEEZE_PER_EYE = 1;
static const float DEFAULT_VISION_SQUEEZE_GROUND_PLANE_Y = 0.0f;
static const float DEFAULT_VISION_SQUEEZE_SPOTLIGHT_SIZE = 6.0f;
class VisionSqueeze {
public:
VisionSqueeze();
bool getVisionSqueezeEnabled() const { return _visionSqueezeEnabled; }
void setVisionSqueezeEnabled(bool value);
float getVisionSqueezeRatioX() const { return _visionSqueezeRatioX; }
float getVisionSqueezeRatioY() const { return _visionSqueezeRatioY; }
void setVisionSqueezeRatioX(float value);
void setVisionSqueezeRatioY(float value);
float getVisionSqueezeUnSqueezeDelay() const { return _visionSqueezeUnSqueezeDelay; }
void setVisionSqueezeUnSqueezeDelay(float value);
float getVisionSqueezeUnSqueezeSpeed() const { return _visionSqueezeUnSqueezeSpeed; }
void setVisionSqueezeUnSqueezeSpeed(float value);
float getVisionSqueezeTransition() const { return _visionSqueezeTransition; }
void setVisionSqueezeTransition(float value);
int getVisionSqueezePerEye() const { return _visionSqueezePerEye; }
void setVisionSqueezePerEye(int value);
float getVisionSqueezeGroundPlaneY() const { return _visionSqueezeGroundPlaneY; }
void setVisionSqueezeGroundPlaneY(float value);
float getVisionSqueezeSpotlightSize() const { return _visionSqueezeSpotlightSize; }
void setVisionSqueezeSpotlightSize(float value);
float getVisionSqueezeTurningXFactor() const { return _visionSqueezeTurningXFactor; }
void setVisionSqueezeTurningXFactor(float value);
float getVisionSqueezeTurningYFactor() const { return _visionSqueezeTurningYFactor; }
void setVisionSqueezeTurningYFactor(float value);
void updateVisionSqueeze(const glm::mat4& sensorToWorldMatrix, float deltaTime);
// state variable accessors used by Application.cpp...
bool getSqueezeVision() const { return _squeezeVision; }
void setSqueezeVision(bool value) { _squeezeVision = value; }
bool getSqueezeVisionTurning() const { return _squeezeVisionTurning; }
void setSqueezeVisionTurning(bool value) { _squeezeVisionTurning = value; }
private:
Setting::Handle<bool> _visionSqueezeEnabledSetting {"visionSqueezeEnabled", false};
Setting::Handle<float> _visionSqueezeRatioXSetting {"visionSqueezeRatioX", 0.0f};
Setting::Handle<float> _visionSqueezeRatioYSetting {"visionSqueezeRatioY", 0.0f};
Setting::Handle<float> _visionSqueezeUnSqueezeDelaySetting {"visionSqueezeUnSqueezeDelay",
DEFAULT_VISION_SQUEEZE_UNSQUEEZE_DELAY};
Setting::Handle<float> _visionSqueezeUnSqueezeSpeedSetting {"visionSqueezeUnSqueezeSpeed",
DEFAULT_VISION_SQUEEZE_UNSQUEEZE_SPEED};
Setting::Handle<float> _visionSqueezeTransitionSetting {"visionSqueezeTransition", DEFAULT_VISION_SQUEEZE_TRANSITION};
Setting::Handle<float> _visionSqueezePerEyeSetting {"visionSqueezePerEye", DEFAULT_VISION_SQUEEZE_PER_EYE};
Setting::Handle<float> _visionSqueezeGroundPlaneYSetting {"visionSqueezeGroundPlaneY",
DEFAULT_VISION_SQUEEZE_GROUND_PLANE_Y};
Setting::Handle<float> _visionSqueezeSpotlightSizeSetting {"visionSqueezeSpotlightSize",
DEFAULT_VISION_SQUEEZE_SPOTLIGHT_SIZE};
Setting::Handle<float> _visionSqueezeTurningXFactorSetting {"visionSqueezeTurningXFactor",
DEFAULT_VISION_SQUEEZE_TURNING_X_FACTOR};
Setting::Handle<float> _visionSqueezeTurningYFactorSetting {"visionSqueezeTurningYFactor",
DEFAULT_VISION_SQUEEZE_TURNING_Y_FACTOR};
// these are readable and writable from the scripting interface (on a different thread), so make them atomic
std::atomic<bool> _visionSqueezeEnabled { false };
std::atomic<float> _visionSqueezeRatioX { 0.0f };
std::atomic<float> _visionSqueezeRatioY { 0.0f };
std::atomic<float> _visionSqueezeUnSqueezeDelay { DEFAULT_VISION_SQUEEZE_UNSQUEEZE_DELAY }; // seconds
std::atomic<float> _visionSqueezeUnSqueezeSpeed { DEFAULT_VISION_SQUEEZE_UNSQUEEZE_SPEED };
std::atomic<float> _visionSqueezeTransition { DEFAULT_VISION_SQUEEZE_TRANSITION };
std::atomic<int> _visionSqueezePerEye { DEFAULT_VISION_SQUEEZE_PER_EYE };
std::atomic<float> _visionSqueezeGroundPlaneY { DEFAULT_VISION_SQUEEZE_GROUND_PLANE_Y };
std::atomic<float> _visionSqueezeSpotlightSize { DEFAULT_VISION_SQUEEZE_SPOTLIGHT_SIZE };
std::atomic<float> _visionSqueezeTurningXFactor { DEFAULT_VISION_SQUEEZE_TURNING_X_FACTOR };
std::atomic<float> _visionSqueezeTurningYFactor { DEFAULT_VISION_SQUEEZE_TURNING_Y_FACTOR };
bool _squeezeVision { false };
bool _squeezeVisionTurning { false };
float _visionSqueezeLockout { 0.0 };
glm::vec3 _prevTranslation;
glm::quat _prevRotation;
};
#endif // hifi_VisionSqueeze_h

View file

@ -574,6 +574,7 @@ void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar
avatar->die();
queuePhysicsChange(avatar);
avatar->removeOrb();
// remove this avatar's entities from the tree now, if we wait (as we did previously) for this Avatar's destructor
// it might not fire until after we create a new instance for the same remote avatar, which creates a race

View file

@ -6144,4 +6144,3 @@ void MyAvatar::sendPacket(const QUuid& entityID) const {
});
}
}

View file

@ -75,6 +75,7 @@ void OtherAvatar::createOrb() {
properties.setType(EntityTypes::Sphere);
properties.setAlpha(1.0f);
properties.setColor(getLoadingOrbColor(_loadingStatus));
properties.setName("Loading Avatar " + getID().toString());
properties.setPrimitiveMode(PrimitiveMode::LINES);
properties.getPulse().setMin(0.5f);
properties.getPulse().setMax(1.0f);
@ -201,6 +202,7 @@ void OtherAvatar::computeShapeLOD() {
break;
case workload::Region::UNKNOWN:
case workload::Region::INVALID:
case workload::Region::R4:
case workload::Region::R3:
default:
newLOD = BodyLOD::Sphere;

View file

@ -259,7 +259,7 @@ void GraphicsEngine::render_performFrame() {
batch.enableSkybox(true);
batch.enableStereo(isStereo);
batch.setViewportTransform({ 0, 0, finalFramebuffer->getSize() });
_splashScreen->render(batch, viewFrustum);
_splashScreen->render(batch, viewFrustum, renderArgs._renderMethod == RenderArgs::RenderMethod::FORWARD);
});
} else {
{

View file

@ -114,7 +114,11 @@ void OctreePacketProcessor::processPacket(QSharedPointer<ReceivedMessage> messag
if (renderer) {
renderer->processDatagram(*message, sendingNode);
if (_safeLanding && _safeLanding->isTracking()) {
_safeLanding->addToSequence(renderer->getLastOctreeMessageSequence());
OCTREE_PACKET_SEQUENCE thisSequence = renderer->getLastOctreeMessageSequence();
_safeLanding->addToSequence(thisSequence);
if (_safeLandingSequenceStart == SafeLanding::INVALID_SEQUENCE) {
_safeLandingSequenceStart = thisSequence;
}
}
}
}
@ -124,8 +128,8 @@ void OctreePacketProcessor::processPacket(QSharedPointer<ReceivedMessage> messag
// Read sequence #
OCTREE_PACKET_SEQUENCE completionNumber;
message->readPrimitive(&completionNumber);
if (_safeLanding) {
_safeLanding->finishSequence(0, completionNumber);
if (_safeLanding && _safeLanding->isTracking()) {
_safeLanding->finishSequence(_safeLandingSequenceStart, completionNumber);
}
} break;
@ -153,6 +157,13 @@ void OctreePacketProcessor::stopSafeLanding() {
}
}
void OctreePacketProcessor::resetSafeLanding() {
if (_safeLanding) {
_safeLanding->reset();
}
_safeLandingSequenceStart = SafeLanding::INVALID_SEQUENCE;
}
bool OctreePacketProcessor::safeLandingIsActive() const {
return _safeLanding && _safeLanding->isTracking();
}

View file

@ -28,6 +28,7 @@ public:
void startSafeLanding();
void updateSafeLanding();
void stopSafeLanding();
void resetSafeLanding();
bool safeLandingIsActive() const;
bool safeLandingIsComplete() const;
@ -43,6 +44,7 @@ private slots:
void handleOctreePacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
private:
OCTREE_PACKET_SEQUENCE _safeLandingSequenceStart { SafeLanding::INVALID_SEQUENCE };
std::unique_ptr<SafeLanding> _safeLanding;
};
#endif // hifi_OctreePacketProcessor_h

View file

@ -17,7 +17,6 @@
#include "InterfaceLogging.h"
#include "Application.h"
const int SafeLanding::SEQUENCE_MODULO = std::numeric_limits<OCTREE_PACKET_SEQUENCE>::max() + 1;
CalculateEntityLoadingPriority SafeLanding::entityLoadingOperatorElevateCollidables = [](const EntityItem& entityItem) {
const int COLLIDABLE_ENTITY_PRIORITY = 10.0f;
@ -25,8 +24,8 @@ CalculateEntityLoadingPriority SafeLanding::entityLoadingOperatorElevateCollidab
};
namespace {
template<typename T> bool lessThanWraparound(int a, int b) {
constexpr int MAX_T_VALUE = std::numeric_limits<T>::max();
template<typename T> bool lessThanWraparound(int32_t a, int32_t b) {
constexpr int32_t MAX_T_VALUE = std::numeric_limits<T>::max();
if (b <= a) {
b += MAX_T_VALUE;
}
@ -34,7 +33,7 @@ namespace {
}
}
bool SafeLanding::SequenceLessThan::operator()(const int& a, const int& b) const {
bool SafeLanding::SequenceLessThan::operator()(const OCTREE_PACKET_SEQUENCE& a, const OCTREE_PACKET_SEQUENCE& b) const {
return lessThanWraparound<OCTREE_PACKET_SEQUENCE>(a, b);
}
@ -46,8 +45,8 @@ void SafeLanding::startTracking(QSharedPointer<EntityTreeRenderer> entityTreeRen
_entityTreeRenderer = entityTreeRenderer;
_trackedEntities.clear();
_maxTrackedEntityCount = 0;
_initialStart = INVALID_SEQUENCE;
_initialEnd = INVALID_SEQUENCE;
_sequenceStart = SafeLanding::INVALID_SEQUENCE;
_sequenceEnd = SafeLanding::INVALID_SEQUENCE;
_sequenceNumbers.clear();
_trackingEntities = true;
_startTime = usecTimestampNow();
@ -72,7 +71,7 @@ void SafeLanding::addTrackedEntity(const EntityItemID& entityID) {
if (entity && !entity->isLocalEntity() && entity->getCreated() < _startTime) {
_trackedEntities.emplace(entityID, entity);
int trackedEntityCount = (int)_trackedEntities.size();
int32_t trackedEntityCount = (int32_t)_trackedEntities.size();
if (trackedEntityCount > _maxTrackedEntityCount) {
_maxTrackedEntityCount = trackedEntityCount;
_trackedEntityStabilityCount = 0;
@ -87,15 +86,15 @@ void SafeLanding::deleteTrackedEntity(const EntityItemID& entityID) {
_trackedEntities.erase(entityID);
}
void SafeLanding::finishSequence(int first, int last) {
void SafeLanding::finishSequence(OCTREE_PACKET_SEQUENCE first, OCTREE_PACKET_SEQUENCE last) {
Locker lock(_lock);
if (_trackingEntities) {
_initialStart = first;
_initialEnd = last;
_sequenceStart = first;
_sequenceEnd = last;
}
}
void SafeLanding::addToSequence(int sequenceNumber) {
void SafeLanding::addToSequence(OCTREE_PACKET_SEQUENCE sequenceNumber) {
Locker lock(_lock);
_sequenceNumbers.insert(sequenceNumber);
}
@ -135,14 +134,13 @@ void SafeLanding::updateTracking() {
if (_trackedEntities.empty()) {
// no more tracked entities --> check sequenceNumbers
if (_initialStart != INVALID_SEQUENCE) {
if (_sequenceStart != SafeLanding::INVALID_SEQUENCE) {
bool shouldStop = false;
{
Locker lock(_lock);
int sequenceSize = _initialStart <= _initialEnd ? _initialEnd - _initialStart:
_initialEnd + SEQUENCE_MODULO - _initialStart;
auto startIter = _sequenceNumbers.find(_initialStart);
auto endIter = _sequenceNumbers.find(_initialEnd - 1);
auto sequenceSize = _sequenceEnd - _sequenceStart; // this works even in rollover case
auto startIter = _sequenceNumbers.find(_sequenceStart);
auto endIter = _sequenceNumbers.find(_sequenceEnd - 1);
bool missingSequenceNumbers = qApp->isMissingSequenceNumbers();
shouldStop = (sequenceSize == 0 ||
@ -159,31 +157,41 @@ void SafeLanding::updateTracking() {
void SafeLanding::stopTracking() {
Locker lock(_lock);
_trackingEntities = false;
if (_entityTreeRenderer) {
auto entityTree = _entityTreeRenderer->getTree();
disconnect(std::const_pointer_cast<EntityTree>(entityTree).get(),
&EntityTree::addingEntity, this, &SafeLanding::addTrackedEntity);
disconnect(std::const_pointer_cast<EntityTree>(entityTree).get(),
&EntityTree::deletingEntity, this, &SafeLanding::deleteTrackedEntity);
_entityTreeRenderer.reset();
if (_trackingEntities) {
_trackingEntities = false;
if (_entityTreeRenderer) {
auto entityTree = _entityTreeRenderer->getTree();
disconnect(std::const_pointer_cast<EntityTree>(entityTree).get(),
&EntityTree::addingEntity, this, &SafeLanding::addTrackedEntity);
disconnect(std::const_pointer_cast<EntityTree>(entityTree).get(),
&EntityTree::deletingEntity, this, &SafeLanding::deleteTrackedEntity);
_entityTreeRenderer.reset();
}
EntityTreeRenderer::setEntityLoadingPriorityFunction(_prevEntityLoadingPriorityOperator);
}
EntityTreeRenderer::setEntityLoadingPriorityFunction(_prevEntityLoadingPriorityOperator);
}
void SafeLanding::reset() {
_trackingEntities = false;
_trackedEntities.clear();
_maxTrackedEntityCount = 0;
_sequenceStart = SafeLanding::INVALID_SEQUENCE;
_sequenceEnd = SafeLanding::INVALID_SEQUENCE;
}
bool SafeLanding::trackingIsComplete() const {
return !_trackingEntities && (_initialStart != INVALID_SEQUENCE);
return !_trackingEntities && (_sequenceStart != SafeLanding::INVALID_SEQUENCE);
}
float SafeLanding::loadingProgressPercentage() {
Locker lock(_lock);
static const int MINIMUM_TRACKED_ENTITY_STABILITY_COUNT = 15;
float entityReadyPercentage = 0.0f;
if (_maxTrackedEntityCount > 0) {
entityReadyPercentage = ((_maxTrackedEntityCount - _trackedEntities.size()) / (float)_maxTrackedEntityCount);
}
constexpr int32_t MINIMUM_TRACKED_ENTITY_STABILITY_COUNT = 15;
if (_trackedEntityStabilityCount < MINIMUM_TRACKED_ENTITY_STABILITY_COUNT) {
entityReadyPercentage *= 0.20f;
}
@ -203,8 +211,22 @@ bool SafeLanding::isEntityPhysicsReady(const EntityItemPointer& entity) {
if (hasAABox && downloadedCollisionTypes.count(modelEntity->getShapeType()) != 0) {
auto space = _entityTreeRenderer->getWorkloadSpace();
uint8_t region = space ? space->getRegion(entity->getSpaceIndex()) : (uint8_t)workload::Region::INVALID;
bool shouldBePhysical = region < workload::Region::R3 && entity->shouldBePhysical();
return (!shouldBePhysical || entity->isInPhysicsSimulation() || modelEntity->computeShapeFailedToLoad());
// Note: the meanings of the workload regions are:
// R1 = in physics simulation and willing to own simulation
// R2 = in physics simulation but does NOT want to own simulation
// R3 = not in physics simulation but kinematically animated when velocities are non-zero
// R4 = sorted by workload and found to be outside R3
// UNKNOWN = known to workload but not yet sorted
// INVALID = not known to workload
// So any entity sorted into R3 or R4 is definitelyNotPhysical
bool definitelyNotPhysical = region == workload::Region::R3 ||
region == workload::Region::R4 ||
!entity->shouldBePhysical() ||
modelEntity->unableToLoadCollisionShape();
bool definitelyPhysical = entity->isInPhysicsSimulation();
return definitelyNotPhysical || definitelyPhysical;
}
}
}
@ -212,20 +234,24 @@ bool SafeLanding::isEntityPhysicsReady(const EntityItemPointer& entity) {
}
void SafeLanding::debugDumpSequenceIDs() const {
int p = -1;
qCDebug(interfaceapp) << "Sequence set size:" << _sequenceNumbers.size();
for (auto s: _sequenceNumbers) {
if (p == -1) {
p = s;
qCDebug(interfaceapp) << "First:" << s;
} else {
auto itr = _sequenceNumbers.begin();
OCTREE_PACKET_SEQUENCE p = SafeLanding::INVALID_SEQUENCE;
if (itr != _sequenceNumbers.end()) {
p = (*itr);
qCDebug(interfaceapp) << "First:" << (int32_t)p;
++itr;
while (itr != _sequenceNumbers.end()) {
OCTREE_PACKET_SEQUENCE s = *itr;
if (s != p + 1) {
qCDebug(interfaceapp) << "Gap from" << p << "to" << s << "(exclusive)";
qCDebug(interfaceapp) << "Gap from" << (int32_t)p << "to" << (int32_t)s << "(exclusive)";
p = s;
}
++itr;
}
if (p != SafeLanding::INVALID_SEQUENCE) {
qCDebug(interfaceapp) << "Last:" << p;
}
}
if (p != -1) {
qCDebug(interfaceapp) << "Last:" << p;
}
}

View file

@ -17,6 +17,8 @@
#include <QtCore/QObject>
#include <QtCore/QSharedPointer>
#include <set>
#include "EntityItem.h"
#include "EntityDynamicInterface.h"
@ -27,14 +29,18 @@ class EntityItemID;
class SafeLanding : public QObject {
public:
static constexpr OCTREE_PACKET_SEQUENCE MAX_SEQUENCE = std::numeric_limits<OCTREE_PACKET_SEQUENCE>::max();
static constexpr OCTREE_PACKET_SEQUENCE INVALID_SEQUENCE = MAX_SEQUENCE; // not technically invalid, but close enough
void startTracking(QSharedPointer<EntityTreeRenderer> entityTreeRenderer);
void updateTracking();
void stopTracking();
void reset();
bool isTracking() const { return _trackingEntities; }
bool trackingIsComplete() const;
void finishSequence(int first, int last); // 'last' exclusive.
void addToSequence(int sequenceNumber);
void finishSequence(OCTREE_PACKET_SEQUENCE first, OCTREE_PACKET_SEQUENCE last); // 'last' exclusive.
void addToSequence(OCTREE_PACKET_SEQUENCE sequenceNumber);
float loadingProgressPercentage();
private slots:
@ -52,24 +58,22 @@ private:
using EntityMap = std::map<EntityItemID, EntityItemPointer>;
EntityMap _trackedEntities;
static constexpr int INVALID_SEQUENCE = -1;
int _initialStart { INVALID_SEQUENCE };
int _initialEnd { INVALID_SEQUENCE };
int _maxTrackedEntityCount { 0 };
int _trackedEntityStabilityCount { 0 };
OCTREE_PACKET_SEQUENCE _sequenceStart { INVALID_SEQUENCE };
OCTREE_PACKET_SEQUENCE _sequenceEnd { INVALID_SEQUENCE };
int32_t _maxTrackedEntityCount { 0 };
int32_t _trackedEntityStabilityCount { 0 };
quint64 _startTime { 0 };
struct SequenceLessThan {
bool operator()(const int& a, const int& b) const;
bool operator()(const OCTREE_PACKET_SEQUENCE& a, const OCTREE_PACKET_SEQUENCE& b) const;
};
std::set<int, SequenceLessThan> _sequenceNumbers;
using SequenceSet = std::set<OCTREE_PACKET_SEQUENCE, SequenceLessThan>;
SequenceSet _sequenceNumbers;
static CalculateEntityLoadingPriority entityLoadingOperatorElevateCollidables;
CalculateEntityLoadingPriority _prevEntityLoadingPriorityOperator { nullptr };
static const int SEQUENCE_MODULO;
};
#endif // hifi_SafeLanding_h

View file

@ -405,7 +405,8 @@ gpu::PipelinePointer ParabolaPointer::RenderState::ParabolaRenderItem::getParabo
using namespace shader::render_utils::program;
static const std::vector<std::tuple<bool, bool, uint32_t>> keys = {
std::make_tuple(false, false, parabola), std::make_tuple(false, true, forward_parabola), std::make_tuple(true, false, parabola_translucent)/*, std::make_tuple(true, true, forward_parabola_translucent)*/
std::make_tuple(false, false, parabola), std::make_tuple(false, true, parabola_forward),
std::make_tuple(true, false, parabola_translucent), std::make_tuple(true, true, parabola_forward) // The forward opaque/translucent pipelines are the same for now
};
for (auto& key : keys) {
@ -423,9 +424,6 @@ gpu::PipelinePointer ParabolaPointer::RenderState::ParabolaRenderItem::getParabo
_parabolaPipelines[{std::get<0>(key), std::get<1>(key)}] = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<2>(key)), state);
}
// The forward opaque/translucent pipelines are the same for now
_parabolaPipelines[{ true, true }] = _parabolaPipelines[{ false, true}];
}
return _parabolaPipelines[{ _parabolaData.color.a < 1.0f, forward }];
}

View file

@ -111,10 +111,11 @@ void DesktopScriptingInterface::show(const QString& path, const QString& title)
InteractiveWindowPointer DesktopScriptingInterface::createWindow(const QString& sourceUrl, const QVariantMap& properties) {
if (QThread::currentThread() != thread()) {
InteractiveWindowPointer interactiveWindow = nullptr;
BLOCKING_INVOKE_METHOD(this, "createWindow",
BLOCKING_INVOKE_METHOD(this, "createWindowOnThread",
Q_RETURN_ARG(InteractiveWindowPointer, interactiveWindow),
Q_ARG(QString, sourceUrl),
Q_ARG(QVariantMap, properties));
Q_ARG(QVariantMap, properties),
Q_ARG(QThread*, QThread::currentThread()));
return interactiveWindow;
}
@ -129,3 +130,16 @@ InteractiveWindowPointer DesktopScriptingInterface::createWindow(const QString&
return new InteractiveWindow(sourceUrl, properties);
}
InteractiveWindowPointer DesktopScriptingInterface::createWindowOnThread(const QString& sourceUrl, const QVariantMap& properties, QThread* targetThread) {
// The offscreen surface already validates against non-local QML sources, but we also need to ensure that
// if we create top level QML, like dock widgets or other types of QQuickView containing desktop windows
// that the source URL is permitted
const auto& urlValidator = OffscreenQmlSurface::getUrlValidator();
if (!urlValidator(sourceUrl)) {
return nullptr;
}
InteractiveWindowPointer window = new InteractiveWindow(sourceUrl, properties);
window->moveToThread(targetThread);
return window;
}

View file

@ -101,6 +101,8 @@ private:
static int flagAlwaysOnTop() { return AlwaysOnTop; }
static int flagCloseButtonHides() { return CloseButtonHides; }
Q_INVOKABLE InteractiveWindowPointer createWindowOnThread(const QString& sourceUrl, const QVariantMap& properties, QThread* targetThread);
static QVariantMap getDockArea();
Q_INVOKABLE static QVariantMap getPresentationMode();

View file

@ -236,3 +236,83 @@ QVariant HMDScriptingInterface::getPlayAreaRect() {
QVector<glm::vec3> HMDScriptingInterface::getSensorPositions() {
return qApp->getActiveDisplayPlugin()->getSensorPositions();
}
float HMDScriptingInterface::getVisionSqueezeRatioX() const {
return qApp->getVisionSqueeze().getVisionSqueezeRatioX();
}
float HMDScriptingInterface::getVisionSqueezeRatioY() const {
return qApp->getVisionSqueeze().getVisionSqueezeRatioY();
}
void HMDScriptingInterface::setVisionSqueezeRatioX(float value) {
qApp->getVisionSqueeze().setVisionSqueezeRatioX(value);
}
void HMDScriptingInterface::setVisionSqueezeRatioY(float value) {
qApp->getVisionSqueeze().setVisionSqueezeRatioY(value);
}
float HMDScriptingInterface::getVisionSqueezeUnSqueezeDelay() const {
return qApp->getVisionSqueeze().getVisionSqueezeUnSqueezeDelay();
}
void HMDScriptingInterface::setVisionSqueezeUnSqueezeDelay(float value) {
qApp->getVisionSqueeze().setVisionSqueezeUnSqueezeDelay(value);
}
float HMDScriptingInterface::getVisionSqueezeUnSqueezeSpeed() const {
return qApp->getVisionSqueeze().getVisionSqueezeUnSqueezeSpeed();
}
void HMDScriptingInterface::setVisionSqueezeUnSqueezeSpeed(float value) {
qApp->getVisionSqueeze().setVisionSqueezeUnSqueezeSpeed(value);
}
float HMDScriptingInterface::getVisionSqueezeTransition() const {
return qApp->getVisionSqueeze().getVisionSqueezeTransition();
}
void HMDScriptingInterface::setVisionSqueezeTransition(float value) {
qApp->getVisionSqueeze().setVisionSqueezeTransition(value);
}
int HMDScriptingInterface::getVisionSqueezePerEye() const {
return qApp->getVisionSqueeze().getVisionSqueezePerEye();
}
void HMDScriptingInterface::setVisionSqueezePerEye(int value) {
qApp->getVisionSqueeze().setVisionSqueezePerEye(value);
}
float HMDScriptingInterface::getVisionSqueezeGroundPlaneY() const {
return qApp->getVisionSqueeze().getVisionSqueezeGroundPlaneY();
}
void HMDScriptingInterface::setVisionSqueezeGroundPlaneY(float value) {
qApp->getVisionSqueeze().setVisionSqueezeGroundPlaneY(value);
}
float HMDScriptingInterface::getVisionSqueezeSpotlightSize() const {
return qApp->getVisionSqueeze().getVisionSqueezeSpotlightSize();
}
void HMDScriptingInterface::setVisionSqueezeSpotlightSize(float value) {
qApp->getVisionSqueeze().setVisionSqueezeSpotlightSize(value);
}
float HMDScriptingInterface::getVisionSqueezeTurningXFactor() const {
return qApp->getVisionSqueeze().getVisionSqueezeTurningXFactor();
}
void HMDScriptingInterface::setVisionSqueezeTurningXFactor(float value) {
qApp->getVisionSqueeze().setVisionSqueezeTurningXFactor(value);
}
float HMDScriptingInterface::getVisionSqueezeTurningYFactor() const {
return qApp->getVisionSqueeze().getVisionSqueezeTurningYFactor();
}
void HMDScriptingInterface::setVisionSqueezeTurningYFactor(float value) {
qApp->getVisionSqueeze().setVisionSqueezeTurningYFactor(value);
}

View file

@ -84,6 +84,17 @@ class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Depen
Q_PROPERTY(QVariant playArea READ getPlayAreaRect);
Q_PROPERTY(QVector<glm::vec3> sensorPositions READ getSensorPositions);
Q_PROPERTY(float visionSqueezeRatioX READ getVisionSqueezeRatioX WRITE setVisionSqueezeRatioX);
Q_PROPERTY(float visionSqueezeRatioY READ getVisionSqueezeRatioY WRITE setVisionSqueezeRatioY);
Q_PROPERTY(float visionSqueezeUnSqueezeDelay READ getVisionSqueezeUnSqueezeDelay WRITE setVisionSqueezeUnSqueezeDelay);
Q_PROPERTY(float visionSqueezeUnSqueezeSpeed READ getVisionSqueezeUnSqueezeSpeed WRITE setVisionSqueezeUnSqueezeSpeed);
Q_PROPERTY(float visionSqueezeTransition READ getVisionSqueezeTransition WRITE setVisionSqueezeTransition);
Q_PROPERTY(int visionSqueezePerEye READ getVisionSqueezePerEye WRITE setVisionSqueezePerEye);
Q_PROPERTY(float visionSqueezeGroundPlaneY READ getVisionSqueezeGroundPlaneY WRITE setVisionSqueezeGroundPlaneY);
Q_PROPERTY(float visionSqueezeSpotlightSize READ getVisionSqueezeSpotlightSize WRITE setVisionSqueezeSpotlightSize);
Q_PROPERTY(float visionSqueezeTurningXFactor READ getVisionSqueezeTurningXFactor WRITE setVisionSqueezeTurningXFactor);
Q_PROPERTY(float visionSqueezeTurningYFactor READ getVisionSqueezeTurningYFactor WRITE setVisionSqueezeTurningYFactor);
public:
/**jsdoc
@ -339,6 +350,27 @@ public:
*/
Q_INVOKABLE void openTablet(bool contextualMode = false);
float getVisionSqueezeRatioX() const;
float getVisionSqueezeRatioY() const;
void setVisionSqueezeRatioX(float value);
void setVisionSqueezeRatioY(float value);
float getVisionSqueezeUnSqueezeDelay() const;
void setVisionSqueezeUnSqueezeDelay(float value);
float getVisionSqueezeUnSqueezeSpeed() const;
void setVisionSqueezeUnSqueezeSpeed(float value);
float getVisionSqueezeTransition() const;
void setVisionSqueezeTransition(float value);
int getVisionSqueezePerEye() const;
void setVisionSqueezePerEye(int value);
float getVisionSqueezeGroundPlaneY() const;
void setVisionSqueezeGroundPlaneY(float value);
float getVisionSqueezeSpotlightSize() const;
void setVisionSqueezeSpotlightSize(float value);
float getVisionSqueezeTurningXFactor() const;
void setVisionSqueezeTurningXFactor(float value);
float getVisionSqueezeTurningYFactor() const;
void setVisionSqueezeTurningYFactor(float value);
signals:
/**jsdoc
* Triggered when a request to show or hide models of the HMD hand controllers is made using

View file

@ -221,4 +221,6 @@ QStringList PlatformInfoScriptingInterface::getPlatformTierNames() {
return platformTierNames;
}
bool PlatformInfoScriptingInterface::isRenderMethodDeferredCapable() {
return platform::Profiler::isRenderMethodDeferredCapable();
}

View file

@ -245,7 +245,12 @@ public slots:
*/
QStringList getPlatformTierNames();
/**jsdoc
* Gets whether the current hardware can render using the Deferred method.
* @function PlatformInfo.isRenderMethodDeferredCapable
* @returns {bool} <code>true</code> if the current hardware can render using the Deferred method; <code>false</code> otherwise.
*/
bool isRenderMethodDeferredCapable();
};
#endif // hifi_PlatformInfoScriptingInterface_h

View file

@ -94,7 +94,7 @@ void AvatarInputs::setShowBubbleTools(bool showBubbleTools) {
return;
_showBubbleTools = showBubbleTools;
showBubbleToolsSetting.set(_showAudioTools);
showBubbleToolsSetting.set(_showBubbleTools);
emit showBubbleToolsChanged(_showBubbleTools);
}

View file

@ -51,6 +51,28 @@ static const QStringList KNOWN_SCHEMES = QStringList() << "http" << "https" << "
static const int DEFAULT_HEIGHT = 60;
QmlWindowProxy::QmlWindowProxy(QObject* qmlObject, QObject* parent) : QmlWrapper(qmlObject, parent) {
_qmlWindow = qmlObject;
}
void QmlWindowProxy::parentNativeWindowToMainWindow() {
#ifdef Q_OS_WIN
if (!_qmlWindow) {
return;
}
const auto nativeWindowProperty = _qmlWindow->property("nativeWindow");
if (nativeWindowProperty.isNull() || !nativeWindowProperty.isValid()) {
return;
}
const auto nativeWindow = qvariant_cast<QQuickWindow*>(nativeWindowProperty);
SetWindowLongPtr((HWND)nativeWindow->winId(), GWLP_HWNDPARENT, (LONG)MainWindow::findMainWindow()->winId());
#endif
}
static void qmlWindowProxyDeleter(QmlWindowProxy* qmlWindowProxy) {
qmlWindowProxy->deleteLater();
}
static void dockWidgetDeleter(DockWidget* dockWidget) {
dockWidget->deleteLater();
}
@ -85,13 +107,13 @@ void InteractiveWindow::forwardKeyReleaseEvent(int key, int modifiers) {
* @property {string} [title="InteractiveWindow] - The title of the window.
* @property {Vec2} [position] - The initial position of the window, in pixels.
* @property {Vec2} [size] - The initial size of the window, in pixels
* @property {boolean} [visible=true] - <code>true</code> to make the window visible when created, <code>false</code> to make
* @property {boolean} [visible=true] - <code>true</code> to make the window visible when created, <code>false</code> to make
* it invisible.
* @property {InteractiveWindow.PresentationMode} [presentationMode=Desktop.PresentationMode.VIRTUAL] -
* <code>Desktop.PresentationMode.VIRTUAL</code> to display the window inside Interface, <code>.NATIVE</code> to display it
* @property {InteractiveWindow.PresentationMode} [presentationMode=Desktop.PresentationMode.VIRTUAL] -
* <code>Desktop.PresentationMode.VIRTUAL</code> to display the window inside Interface, <code>.NATIVE</code> to display it
* as its own separate window.
* @property {InteractiveWindow.PresentationWindowInfo} [presentationWindowInfo] - Controls how a <code>NATIVE</code> window is
* displayed. If used, the window is docked to the specified edge of the Interface window, otherwise the window is
* @property {InteractiveWindow.PresentationWindowInfo} [presentationWindowInfo] - Controls how a <code>NATIVE</code> window is
* displayed. If used, the window is docked to the specified edge of the Interface window, otherwise the window is
* displayed as its own separate window.
* @property {InteractiveWindow.AdditionalFlags} [additionalFlags=0] - Window behavior flags in addition to "native window flags" (minimize/maximize/close),
* set at window creation. Possible flag values are provided as {@link Desktop|Desktop.ALWAYS_ON_TOP} and {@link Desktop|Desktop.CLOSE_BUTTON_HIDES}.
@ -124,7 +146,7 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap
auto mainWindow = qApp->getWindow();
_dockWidget = std::shared_ptr<DockWidget>(new DockWidget(title, mainWindow), dockWidgetDeleter);
auto quickView = _dockWidget->getQuickView();
Application::setupQmlSurface(quickView->rootContext() , true);
//add any whitelisted callbacks
@ -176,13 +198,12 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap
});
_dockWidget->setSource(QUrl(sourceUrl));
mainWindow->addDockWidget(dockArea, _dockWidget.get());
} else {
auto offscreenUi = DependencyManager::get<OffscreenUi>();
// Build the event bridge and wrapper on the main thread
offscreenUi->loadInNewContext(CONTENT_WINDOW_QML, [&](QQmlContext* context, QObject* object) {
_qmlWindow = object;
_qmlWindowProxy = std::shared_ptr<QmlWindowProxy>(new QmlWindowProxy(object, nullptr), qmlWindowProxyDeleter);
context->setContextProperty(EVENT_BRIDGE_PROPERTY, this);
if (properties.contains(ADDITIONAL_FLAGS_PROPERTY)) {
object->setProperty(ADDITIONAL_FLAGS_PROPERTY, properties[ADDITIONAL_FLAGS_PROPERTY].toUInt());
@ -249,60 +270,48 @@ void InteractiveWindow::sendToQml(const QVariant& message) {
QMetaObject::invokeMethod(rootItem, "fromScript", Qt::QueuedConnection, Q_ARG(QVariant, message));
}
} else {
QMetaObject::invokeMethod(_qmlWindow, "fromScript", Qt::QueuedConnection, Q_ARG(QVariant, message));
QMetaObject::invokeMethod(_qmlWindowProxy->getQmlWindow(), "fromScript", Qt::QueuedConnection, Q_ARG(QVariant, message));
}
}
void InteractiveWindow::emitScriptEvent(const QVariant& scriptMessage) {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "emitScriptEvent", Qt::QueuedConnection, Q_ARG(QVariant, scriptMessage));
} else {
emit scriptEventReceived(scriptMessage);
}
emit scriptEventReceived(scriptMessage);
}
void InteractiveWindow::emitWebEvent(const QVariant& webMessage) {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "emitWebEvent", Qt::QueuedConnection, Q_ARG(QVariant, webMessage));
} else {
emit webEventReceived(webMessage);
}
emit webEventReceived(webMessage);
}
void InteractiveWindow::close() {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "close");
return;
if (_qmlWindowProxy) {
QObject* qmlWindow = _qmlWindowProxy->getQmlWindow();
if (qmlWindow) {
qmlWindow->deleteLater();
}
_qmlWindowProxy->deleteLater();
}
if (_qmlWindow) {
_qmlWindow->deleteLater();
if (_dockWidget) {
auto window = qApp->getWindow();
if (QThread::currentThread() != window->thread()) {
BLOCKING_INVOKE_METHOD(window, "removeDockWidget", Q_ARG(QDockWidget*, _dockWidget.get()));
} else {
window->removeDockWidget(_dockWidget.get());
}
}
qApp->getWindow()->removeDockWidget(_dockWidget.get());
_dockWidget = nullptr;
_qmlWindow = nullptr;
_qmlWindowProxy = nullptr;
}
void InteractiveWindow::show() {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "show");
return;
}
if (_qmlWindow) {
QMetaObject::invokeMethod(_qmlWindow, "show", Qt::DirectConnection);
if (_qmlWindowProxy) {
QMetaObject::invokeMethod(_qmlWindowProxy->getQmlWindow(), "show");
}
}
void InteractiveWindow::raise() {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "raise");
return;
}
if (_qmlWindow) {
QMetaObject::invokeMethod(_qmlWindow, "raiseWindow", Qt::DirectConnection);
if (_qmlWindowProxy) {
QMetaObject::invokeMethod(_qmlWindowProxy->getQmlWindow(), "raiseWindow");
}
}
@ -317,144 +326,84 @@ void InteractiveWindow::qmlToScript(const QVariant& message) {
}
void InteractiveWindow::setVisible(bool visible) {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "setVisible", Q_ARG(bool, visible));
return;
}
if (!_qmlWindow.isNull()) {
_qmlWindow->setProperty(INTERACTIVE_WINDOW_VISIBLE_PROPERTY, visible);
if (_qmlWindowProxy) {
QMetaObject::invokeMethod(_qmlWindowProxy.get(), "writeProperty", Q_ARG(QString, INTERACTIVE_WINDOW_VISIBLE_PROPERTY),
Q_ARG(QVariant, visible));
}
}
bool InteractiveWindow::isVisible() const {
if (QThread::currentThread() != thread()) {
bool result = false;
BLOCKING_INVOKE_METHOD(const_cast<InteractiveWindow*>(this), "isVisible", Q_RETURN_ARG(bool, result));
return result;
}
if (_qmlWindow.isNull()) {
if (!_qmlWindowProxy) {
return false;
}
return _qmlWindow->property(INTERACTIVE_WINDOW_VISIBLE_PROPERTY).toBool();
return _qmlWindowProxy->readProperty(INTERACTIVE_WINDOW_VISIBLE_PROPERTY).toBool();
}
glm::vec2 InteractiveWindow::getPosition() const {
if (QThread::currentThread() != thread()) {
glm::vec2 result;
BLOCKING_INVOKE_METHOD(const_cast<InteractiveWindow*>(this), "getPosition", Q_RETURN_ARG(glm::vec2, result));
return result;
}
if (_qmlWindow.isNull()) {
if (!_qmlWindowProxy) {
return {};
}
return toGlm(_qmlWindow->property(INTERACTIVE_WINDOW_POSITION_PROPERTY).toPointF());
return toGlm(_qmlWindowProxy->readProperty(INTERACTIVE_WINDOW_POSITION_PROPERTY).toPointF());
}
void InteractiveWindow::setPosition(const glm::vec2& position) {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "setPosition", Q_ARG(const glm::vec2&, position));
return;
}
if (!_qmlWindow.isNull()) {
_qmlWindow->setProperty(INTERACTIVE_WINDOW_POSITION_PROPERTY, QPointF(position.x, position.y));
QMetaObject::invokeMethod(_qmlWindow, "updateInteractiveWindowPositionForMode", Qt::DirectConnection);
if (_qmlWindowProxy) {
QMetaObject::invokeMethod(_qmlWindowProxy.get(), "writeProperty", Q_ARG(QString, INTERACTIVE_WINDOW_POSITION_PROPERTY),
Q_ARG(QVariant, QPointF(position.x, position.y)));
QMetaObject::invokeMethod(_qmlWindowProxy->getQmlWindow(), "updateInteractiveWindowPositionForMode");
}
}
glm::vec2 InteractiveWindow::getSize() const {
if (QThread::currentThread() != thread()) {
glm::vec2 result;
BLOCKING_INVOKE_METHOD(const_cast<InteractiveWindow*>(this), "getSize", Q_RETURN_ARG(glm::vec2, result));
return result;
}
if (_qmlWindow.isNull()) {
if (!_qmlWindowProxy) {
return {};
}
return toGlm(_qmlWindow->property(INTERACTIVE_WINDOW_SIZE_PROPERTY).toSize());
return toGlm(_qmlWindowProxy->readProperty(INTERACTIVE_WINDOW_SIZE_PROPERTY).toSize());
}
void InteractiveWindow::setSize(const glm::vec2& size) {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "setSize", Q_ARG(const glm::vec2&, size));
return;
}
if (!_qmlWindow.isNull()) {
_qmlWindow->setProperty(INTERACTIVE_WINDOW_SIZE_PROPERTY, QSize(size.x, size.y));
QMetaObject::invokeMethod(_qmlWindow, "updateInteractiveWindowSizeForMode", Qt::DirectConnection);
if (_qmlWindowProxy) {
QMetaObject::invokeMethod(_qmlWindowProxy.get(), "writeProperty", Q_ARG(QString, INTERACTIVE_WINDOW_SIZE_PROPERTY),
Q_ARG(QVariant, QSize(size.x, size.y)));
QMetaObject::invokeMethod(_qmlWindowProxy->getQmlWindow(), "updateInteractiveWindowSizeForMode");
}
}
QString InteractiveWindow::getTitle() const {
if (QThread::currentThread() != thread()) {
QString result;
BLOCKING_INVOKE_METHOD(const_cast<InteractiveWindow*>(this), "getTitle", Q_RETURN_ARG(QString, result));
return result;
}
if (_qmlWindow.isNull()) {
if (!_qmlWindowProxy) {
return QString();
}
return _qmlWindow->property(TITLE_PROPERTY).toString();
return _qmlWindowProxy->readProperty(TITLE_PROPERTY).toString();
}
void InteractiveWindow::setTitle(const QString& title) {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "setTitle", Q_ARG(const QString&, title));
return;
}
if (!_qmlWindow.isNull()) {
_qmlWindow->setProperty(TITLE_PROPERTY, title);
if (_qmlWindowProxy) {
QMetaObject::invokeMethod(_qmlWindowProxy.get(), "writeProperty", Q_ARG(QString, TITLE_PROPERTY),
Q_ARG(QVariant, title));
}
}
int InteractiveWindow::getPresentationMode() const {
if (QThread::currentThread() != thread()) {
int result;
BLOCKING_INVOKE_METHOD(const_cast<InteractiveWindow*>(this), "getPresentationMode",
Q_RETURN_ARG(int, result));
return result;
}
if (_qmlWindow.isNull()) {
if (!_qmlWindowProxy) {
return Virtual;
}
return _qmlWindow->property(PRESENTATION_MODE_PROPERTY).toInt();
return _qmlWindowProxy->readProperty(PRESENTATION_MODE_PROPERTY).toInt();
}
void InteractiveWindow::parentNativeWindowToMainWindow() {
#ifdef Q_OS_WIN
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "parentNativeWindowToMainWindow");
return;
if (_qmlWindowProxy) {
QMetaObject::invokeMethod(_qmlWindowProxy.get(), "parentNativeWindowToMainWindow");
}
if (_qmlWindow.isNull()) {
return;
}
const auto nativeWindowProperty = _qmlWindow->property("nativeWindow");
if (nativeWindowProperty.isNull() || !nativeWindowProperty.isValid()) {
return;
}
const auto nativeWindow = qvariant_cast<QQuickWindow*>(nativeWindowProperty);
SetWindowLongPtr((HWND)nativeWindow->winId(), GWLP_HWNDPARENT, (LONG)MainWindow::findMainWindow()->winId());
#endif
}
void InteractiveWindow::setPresentationMode(int presentationMode) {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "setPresentationMode", Q_ARG(int, presentationMode));
return;
}
if (!_qmlWindow.isNull()) {
_qmlWindow->setProperty(PRESENTATION_MODE_PROPERTY, presentationMode);
if (_qmlWindowProxy) {
QMetaObject::invokeMethod(_qmlWindowProxy.get(), "writeProperty", Q_ARG(QString, PRESENTATION_MODE_PROPERTY),
Q_ARG(QVariant, presentationMode));
}
}

View file

@ -18,10 +18,26 @@
#include <QtCore/QPointer>
#include <QtScript/QScriptValue>
#include <QQmlEngine>
#include <ui/QmlWrapper.h>
#include <glm/glm.hpp>
#include <GLMHelpers.h>
class QmlWindowProxy : public QmlWrapper {
Q_OBJECT
public:
QmlWindowProxy(QObject* qmlObject, QObject* parent = nullptr);
Q_INVOKABLE void parentNativeWindowToMainWindow();
QObject* getQmlWindow() const { return _qmlWindow; }
private:
QObject* _qmlWindow;
};
namespace InteractiveWindowEnums {
Q_NAMESPACE
@ -291,7 +307,7 @@ protected slots:
void forwardKeyReleaseEvent(int key, int modifiers);
private:
QPointer<QObject> _qmlWindow;
std::shared_ptr<QmlWindowProxy> _qmlWindowProxy;
std::shared_ptr<DockWidget> _dockWidget { nullptr };
};

View file

@ -16,6 +16,7 @@
#include <Preferences.h>
#include <plugins/PluginUtils.h>
#include <display-plugins/CompositorHelper.h>
#include <display-plugins/hmd/HmdDisplayPlugin.h>
#include "scripting/RenderScriptingInterface.h"
#include "Application.h"
#include "DialogsManager.h"
@ -377,6 +378,33 @@ void setupPreferences() {
preference->setDecimals(2);
preferences->addPreference(preference);
}
{
auto getter = []()->bool {
return qApp->getVisionSqueeze().getVisionSqueezeEnabled();
};
auto setter = [](bool value) {
qApp->getVisionSqueeze().setVisionSqueezeEnabled(value);
};
auto preference = new CheckPreference(VR_MOVEMENT, "Enable HMD Comfort Mode", getter, setter);
preferences->addPreference(preference);
}
{
const float sliderPositions = 5.0f;
auto getter = [sliderPositions]()->float {
return roundf(sliderPositions * qApp->getVisionSqueeze().getVisionSqueezeRatioX());
};
auto setter = [sliderPositions](float value) {
float ratio = value / sliderPositions;
qApp->getVisionSqueeze().setVisionSqueezeRatioX(ratio);
qApp->getVisionSqueeze().setVisionSqueezeRatioY(ratio);
};
auto preference = new SpinnerSliderPreference(VR_MOVEMENT, "Comfort Mode", getter, setter);
preference->setMin(0.0f);
preference->setMax(sliderPositions);
preference->setStep(1.0f);
preference->setDecimals(0);
preferences->addPreference(preference);
}
{
auto getter = [myAvatar]()->bool { return myAvatar->getShowPlayArea(); };
auto setter = [myAvatar](bool value) { myAvatar->setShowPlayArea(value); };

View file

@ -442,7 +442,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE;
NSString* contentPath = [[self getDownloadPathForContentAndScripts] stringByAppendingString:@"content"];
NSString* displayName = [ self displayName];
NSString* scriptsPath = [[self getAppPath] stringByAppendingString:@"interface.app/Contents/Resources/scripts/simplifiedUI/"];
NSString* scriptsPath = [[self getAppPath] stringByAppendingString:@"interface.app/Contents/Resources/scripts/simplifiedUIBootstrapper.js"];
NSString* domainUrl = [[Settings sharedSettings] getDomainUrl];
NSString* userToken = [[Launcher sharedLauncher] getTokenString];
NSString* homeBookmark = [[NSString stringWithFormat:@"hqhome="] stringByAppendingString:domainUrl];
@ -453,7 +453,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE;
@"--tokens", userToken,
@"--cache", contentPath,
@"--displayName", displayName,
@"--scripts", scriptsPath,
@"--defaultScriptsOverride", scriptsPath,
@"--setBookmark", homeBookmark,
@"--no-updater",
@"--no-launcher", nil];
@ -461,7 +461,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE;
arguments = [NSArray arrayWithObjects:
@"--url" , domainUrl,
@"--cache", contentPath,
@"--scripts", scriptsPath,
@"--defaultScriptsOverride", scriptsPath,
@"--setBookmark", homeBookmark,
@"--no-updater",
@"--no-launcher", nil];

View file

@ -672,7 +672,7 @@ void CLauncherDlg::OnTimer(UINT_PTR nIDEvent) {
theApp._manager.addToLog(_T("Start splash screen"));
setDrawDialog(DrawStep::DrawLogo);
}
} else if (_splashStep > 100) {
} else if (_splashStep > 100 && !theApp._manager.needsToWait()) {
_showSplash = false;
if (theApp._manager.shouldShutDown()) {
if (_applicationWND != NULL) {

View file

@ -24,35 +24,7 @@ LauncherManager::~LauncherManager() {
void LauncherManager::init() {
initLog();
addToLog(_T("Getting most recent build"));
CString response;
LauncherUtils::ResponseError error = getMostRecentBuild(_latestApplicationURL, _latestVersion, response);
if (error == LauncherUtils::ResponseError::NoError) {
addToLog(_T("Latest version: ") + _latestVersion);
CString currentVersion;
if (isApplicationInstalled(currentVersion, _domainURL, _contentURL, _loggedIn) && _loggedIn) {
addToLog(_T("Installed version: ") + currentVersion);
if (_latestVersion.Compare(currentVersion) == 0) {
addToLog(_T("Already running most recent build. Launching interface.exe"));
_shouldLaunch = TRUE;
_shouldShutdown = TRUE;
} else {
addToLog(_T("New build found. Updating"));
_shouldUpdate = TRUE;
}
} else if (_loggedIn) {
addToLog(_T("Interface not found but logged in. Reinstalling"));
_shouldUpdate = TRUE;
} else {
_shouldInstall = TRUE;
}
} else {
_hasFailed = true;
CString msg;
msg.Format(_T("Getting most recent build has failed with error: %d"), error);
addToLog(msg);
msg.Format(_T("Response: %s"), response);
addToLog(msg);
}
getMostRecentBuild(_latestApplicationURL, _latestVersion);
}
BOOL LauncherManager::initLog() {
@ -387,39 +359,71 @@ LauncherUtils::ResponseError LauncherManager::readOrganizationJSON(const CString
return LauncherUtils::ResponseError::ParsingJSON;
}
LauncherUtils::ResponseError LauncherManager::getMostRecentBuild(CString& urlOut, CString& versionOut,
CString& response) {
void LauncherManager::getMostRecentBuild(CString& urlOut, CString& versionOut) {
CString contentTypeJson = L"content-type:application/json";
LauncherUtils::ResponseError error = LauncherUtils::makeHTTPCall(L"HQ Launcher",
L"thunder.highfidelity.com",
L"/builds/api/tags/latest?format=json",
contentTypeJson, CStringA(),
response, false);
if (error != LauncherUtils::ResponseError::NoError) {
return error;
}
Json::Value json;
if (LauncherUtils::parseJSON(response, json)) {
int count = json["count"].isInt() ? json["count"].asInt() : 0;
if (count > 0 && json["results"].isArray()) {
for (int i = 0; i < count; i++) {
if (json["results"][i].isObject()) {
Json::Value result = json["results"][i];
if (result["latest_version"].isInt()) {
std::string version = std::to_string(result["latest_version"].asInt());
versionOut = CString(version.c_str());
}
if (result["installers"].isObject() &&
result["installers"]["windows"].isObject() &&
result["installers"]["windows"]["zip_url"].isString()) {
urlOut = result["installers"]["windows"]["zip_url"].asCString();
return LauncherUtils::ResponseError::NoError;
std::function<void(CString, int)> httpCallback = [&](CString response, int err) {
LauncherUtils::ResponseError error = LauncherUtils::ResponseError(err);
if (error == LauncherUtils::ResponseError::NoError) {
Json::Value json;
error = LauncherUtils::ResponseError::ParsingJSON;
if (LauncherUtils::parseJSON(response, json)) {
int count = json["count"].isInt() ? json["count"].asInt() : 0;
if (count > 0 && json["results"].isArray()) {
for (int i = 0; i < count; i++) {
if (json["results"][i].isObject()) {
Json::Value result = json["results"][i];
if (result["latest_version"].isInt()) {
std::string version = std::to_string(result["latest_version"].asInt());
versionOut = CString(version.c_str());
}
if (result["installers"].isObject() &&
result["installers"]["windows"].isObject() &&
result["installers"]["windows"]["zip_url"].isString()) {
urlOut = result["installers"]["windows"]["zip_url"].asCString();
error = LauncherUtils::ResponseError::NoError;
}
}
}
}
}
onMostRecentBuildReceived(response, error);
}
};
LauncherUtils::httpCallOnThread(L"HQ Launcher",
L"thunder.highfidelity.com",
L"/builds/api/tags/latest?format=json",
contentTypeJson, CStringA(), false, httpCallback);
}
void LauncherManager::onMostRecentBuildReceived(const CString& response, LauncherUtils::ResponseError error) {
if (error == LauncherUtils::ResponseError::NoError) {
addToLog(_T("Latest version: ") + _latestVersion);
CString currentVersion;
if (isApplicationInstalled(currentVersion, _domainURL, _contentURL, _loggedIn) && _loggedIn) {
addToLog(_T("Installed version: ") + currentVersion);
if (_latestVersion.Compare(currentVersion) == 0) {
addToLog(_T("Already running most recent build. Launching interface.exe"));
_shouldLaunch = TRUE;
_shouldShutdown = TRUE;
} else {
addToLog(_T("New build found. Updating"));
_shouldUpdate = TRUE;
}
} else if (_loggedIn) {
addToLog(_T("Interface not found but logged in. Reinstalling"));
_shouldUpdate = TRUE;
} else {
_shouldInstall = TRUE;
}
_shouldWait = FALSE;
} else {
_hasFailed = true;
CString msg;
msg.Format(_T("Getting most recent build has failed with error: %d"), error);
addToLog(msg);
msg.Format(_T("Response: %s"), response);
addToLog(msg);
}
return LauncherUtils::ResponseError::ParsingJSON;
}
LauncherUtils::ResponseError LauncherManager::getAccessTokenForCredentials(const CString& username,
@ -603,12 +607,10 @@ BOOL LauncherManager::downloadFile(ProcessType type, const CString& url, CString
std::function<void(int, bool)> onDownloadFinished = [&](int type, bool error) {
if (!error) {
onFileDownloaded((ProcessType)type);
}
else {
} else {
if (type == ProcessType::DownloadApplication) {
addToLog(_T("Error downloading content."));
}
else {
} else {
addToLog(_T("Error downloading application."));
}
_hasFailed = true;

View file

@ -67,7 +67,7 @@ public:
BOOL isApplicationInstalled(CString& version, CString& domain,
CString& content, bool& loggedIn);
LauncherUtils::ResponseError getAccessTokenForCredentials(const CString& username, const CString& password);
LauncherUtils::ResponseError getMostRecentBuild(CString& urlOut, CString& versionOut, CString& response);
void getMostRecentBuild(CString& urlOut, CString& versionOut);
LauncherUtils::ResponseError readOrganizationJSON(const CString& hash);
LauncherUtils::ResponseError readConfigJSON(CString& version, CString& domain,
CString& content, bool& loggedIn);
@ -90,12 +90,13 @@ public:
BOOL needsUpdate() { return _shouldUpdate; }
BOOL needsUninstall() { return _shouldUninstall; }
BOOL needsInstall() { return _shouldInstall; }
BOOL needsToWait() { return _shouldWait; }
void setDisplayName(const CString& displayName) { _displayName = displayName; }
bool isLoggedIn() { return _loggedIn; }
bool hasFailed() { return _hasFailed; }
void setFailed(bool hasFailed) { _hasFailed = hasFailed; }
const CString& getLatestInterfaceURL() const { return _latestApplicationURL; }
void uninstall() { _shouldUninstall = true; };
void uninstall() { _shouldUninstall = true; _shouldWait = false; };
BOOL downloadFile(ProcessType type, const CString& url, CString& localPath);
BOOL downloadContent();
@ -110,6 +111,7 @@ public:
private:
ProcessType _currentProcess { ProcessType::DownloadApplication };
void onMostRecentBuildReceived(const CString& response, LauncherUtils::ResponseError error);
CString _latestApplicationURL;
CString _latestVersion;
CString _contentURL;
@ -126,6 +128,7 @@ private:
BOOL _shouldInstall { FALSE };
BOOL _shouldShutdown { FALSE };
BOOL _shouldLaunch { FALSE };
BOOL _shouldWait { TRUE };
float _progress { 0.0f };
CStdioFile _logFile;
};

View file

@ -470,9 +470,9 @@ BOOL LauncherUtils::hMac256(const CString& cmessage, const char* keystr, CString
DWORD WINAPI LauncherUtils::unzipThread(LPVOID lpParameter) {
UnzipThreadData& data = *((UnzipThreadData*)lpParameter);
uint64_t size = LauncherUtils::extractZip(data._zipFile, data._path, std::vector<std::string>(), data.progressCallback);
uint64_t size = LauncherUtils::extractZip(data._zipFile, data._path, std::vector<std::string>(), data._progressCallback);
int mb_size = (int)(size * 0.001f);
data.callback(data._type, mb_size);
data._callback(data._type, mb_size);
delete &data;
return 0;
}
@ -480,17 +480,26 @@ DWORD WINAPI LauncherUtils::unzipThread(LPVOID lpParameter) {
DWORD WINAPI LauncherUtils::downloadThread(LPVOID lpParameter) {
DownloadThreadData& data = *((DownloadThreadData*)lpParameter);
ProgressCallback progressCallback;
progressCallback.setProgressCallback(data.progressCallback);
progressCallback.setProgressCallback(data._progressCallback);
auto hr = URLDownloadToFile(0, data._url, data._file, 0,
static_cast<LPBINDSTATUSCALLBACK>(&progressCallback));
data.callback(data._type, hr != S_OK);
data._callback(data._type, hr != S_OK);
return 0;
}
DWORD WINAPI LauncherUtils::deleteDirectoryThread(LPVOID lpParameter) {
DeleteThreadData& data = *((DeleteThreadData*)lpParameter);
BOOL success = LauncherUtils::deleteFileOrDirectory(data._dirPath);
data.callback(!success);
data._callback(!success);
return 0;
}
DWORD WINAPI LauncherUtils::httpThread(LPVOID lpParameter) {
HttpThreadData& data = *((HttpThreadData*)lpParameter);
CString response;
auto error = LauncherUtils::makeHTTPCall(data._callerName, data._mainUrl, data._dirUrl,
data._contentType, data._postData, response, data._isPost);
data._callback(response, error);
return 0;
}
@ -543,6 +552,26 @@ BOOL LauncherUtils::deleteDirectoryOnThread(const CString& dirPath, std::functio
return FALSE;
}
BOOL LauncherUtils::httpCallOnThread(const CString& callerName, const CString& mainUrl, const CString& dirUrl,
const CString& contentType, CStringA& postData, bool isPost,
std::function<void(CString, int)> callback) {
DWORD myThreadID;
HttpThreadData* httpThreadData = new HttpThreadData();
httpThreadData->_callerName = callerName;
httpThreadData->_mainUrl = mainUrl;
httpThreadData->_dirUrl = dirUrl;
httpThreadData->_contentType = contentType;
httpThreadData->_postData = postData;
httpThreadData->_isPost = isPost;
httpThreadData->setCallback(callback);
HANDLE myHandle = CreateThread(0, 0, httpThread, httpThreadData, 0, &myThreadID);
if (myHandle) {
CloseHandle(myHandle);
return TRUE;
}
return FALSE;
}
HWND LauncherUtils::executeOnForeground(const CString& path, const CString& params) {
SHELLEXECUTEINFO info;
info.cbSize = sizeof(SHELLEXECUTEINFO);

View file

@ -55,15 +55,15 @@ public:
ULONG ulStatusCode, LPCWSTR szStatusText) {
float progress = (float)ulProgress / ulProgressMax;
if (!isnan(progress)) {
onProgressCallback(progress);
_onProgressCallback(progress);
}
return S_OK;
}
void setProgressCallback(std::function<void(float)> fn) {
onProgressCallback = std::bind(fn, std::placeholders::_1);
_onProgressCallback = std::bind(fn, std::placeholders::_1);
}
private:
std::function<void(float)> onProgressCallback;
std::function<void(float)> _onProgressCallback;
};
enum ResponseError {
@ -82,14 +82,14 @@ public:
int _type;
CString _url;
CString _file;
std::function<void(int, bool)> callback;
std::function<void(float)> progressCallback;
std::function<void(int, bool)> _callback;
std::function<void(float)> _progressCallback;
// function(type, errorType)
void setCallback(std::function<void(int, bool)> fn) {
callback = std::bind(fn, std::placeholders::_1, std::placeholders::_2);
_callback = std::bind(fn, std::placeholders::_1, std::placeholders::_2);
}
void setProgressCallback(std::function<void(float)> fn) {
progressCallback = std::bind(fn, std::placeholders::_1);
_progressCallback = std::bind(fn, std::placeholders::_1);
}
};
@ -98,23 +98,36 @@ public:
std::string _zipFile;
std::string _path;
// function(type, size)
std::function<void(int, int)> callback;
std::function<void(float)> progressCallback;
std::function<void(int, int)> _callback;
std::function<void(float)> _progressCallback;
void setCallback(std::function<void(int, int)> fn) {
callback = std::bind(fn, std::placeholders::_1, std::placeholders::_2);
_callback = std::bind(fn, std::placeholders::_1, std::placeholders::_2);
}
void setProgressCallback(std::function<void(float)> fn) {
progressCallback = std::bind(fn, std::placeholders::_1);
_progressCallback = std::bind(fn, std::placeholders::_1);
}
};
struct DeleteThreadData {
CString _dirPath;
std::function<void(bool)> callback;
std::function<void(float)> progressCallback;
void setCallback(std::function<void(bool)> fn) { callback = std::bind(fn, std::placeholders::_1); }
std::function<void(bool)> _callback;
std::function<void(float)> _progressCallback;
void setCallback(std::function<void(bool)> fn) { _callback = std::bind(fn, std::placeholders::_1); }
void setProgressCallback(std::function<void(float)> fn) {
progressCallback = std::bind(fn, std::placeholders::_1);
_progressCallback = std::bind(fn, std::placeholders::_1);
}
};
struct HttpThreadData {
CString _callerName;
CString _mainUrl;
CString _dirUrl;
CString _contentType;
CStringA _postData;
bool _isPost { false };
std::function<void(CString, int)> _callback;
void setCallback(std::function<void(CString, int)> fn) {
_callback = std::bind(fn, std::placeholders::_1, std::placeholders::_2);
}
};
@ -150,6 +163,9 @@ public:
std::function<void(int, bool)> callback,
std::function<void(float)> progressCallback);
static BOOL deleteDirectoryOnThread(const CString& dirPath, std::function<void(bool)> callback);
static BOOL httpCallOnThread(const CString& callerName, const CString& mainUrl, const CString& dirUrl,
const CString& contentType, CStringA& postData, bool isPost,
std::function<void(CString, int)> callback);
static CString urlEncodeString(const CString& url);
static HWND executeOnForeground(const CString& path, const CString& params);
@ -159,4 +175,5 @@ private:
static DWORD WINAPI unzipThread(LPVOID lpParameter);
static DWORD WINAPI downloadThread(LPVOID lpParameter);
static DWORD WINAPI deleteDirectoryThread(LPVOID lpParameter);
};
static DWORD WINAPI httpThread(LPVOID lpParameter);
};

View file

@ -431,7 +431,6 @@ void AnimInverseKinematics::solveTargetWithCCD(const AnimContext& context, const
constrained = constraint->apply(tipRelativeRotation);
if (constrained) {
tipOrientation = tipParentOrientation * tipRelativeRotation;
tipRelativeRotation = tipRelativeRotation;
}
}

View file

@ -47,5 +47,9 @@ void AbstractHMDScriptingInterface::setIPDScale(float IPDScale) {
}
bool AbstractHMDScriptingInterface::isHMDMode() const {
return PluginContainer::getInstance().getActiveDisplayPlugin()->isHmd();
}
auto displayPlugin = PluginContainer::getInstance().getActiveDisplayPlugin();
if (displayPlugin) {
return displayPlugin->isHmd();
}
return false;
}

View file

@ -0,0 +1,104 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// DrawTextureWithVisionSqueeze.frag
//
// Draw texture 0 fetched at texcoord.xy
//
// Created by Seth Alves on 2019-2-15
// Copyright 2019 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 display-plugins/VisionSqueeze.slh@>
struct DrawTextureWithVisionSqueezeParams {
float _visionSqueezeX;
float _visionSqueezeY;
float _spareA;
float _spareB;
mat4 _leftProjection;
mat4 _rightProjection;
mat4 _hmdSensorMatrix;
float _visionSqueezeTransition;
int _visionSqueezePerEye;
float _visionSqueezeGroundPlaneY;
float _visionSqueezeSpotlightSize;
};
LAYOUT(binding=0) uniform sampler2D colorMap;
// binding=1 must match drawTextureWithSqueezeParamsSlot in OpenGLDisplayPlugin.h
LAYOUT(binding=1) uniform drawTextureWithSqueezeMappingParamsBuffer {
DrawTextureWithVisionSqueezeParams params;
};
layout(location=0) in vec2 varTexCoord0;
layout(location=0) out vec4 outFragColor;
float getVisionSqueezeX() {
return params._visionSqueezeX;
}
float getVisionSqueezeY() {
return params._visionSqueezeY;
}
float getVisionSqueezeTransitionRatio() {
return params._visionSqueezeTransition;
}
int getVisionSqueezePerEye() {
return params._visionSqueezePerEye;
}
float getVisionSqueezeGroundPlaneY() {
return params._visionSqueezeGroundPlaneY;
}
float getVisionSqueezeSpotlightSize() {
return params._visionSqueezeSpotlightSize;
}
mat4 getProjectionMatrix(float eye) {
if (eye == 0.0) {
return params._leftProjection;
} else {
return params._rightProjection;
}
}
mat4 getHMDSensorMatrix() {
return params._hmdSensorMatrix;
}
void main(void) {
float side = float(varTexCoord0.x > 0.5);
mat4 leftProjectionMatrix = getProjectionMatrix(0.0);
vec4 fovTan = extractFovTan(leftProjectionMatrix);
vec2 focalPointNDC = extractFocalPoint(fovTan);
focalPointNDC.x -= 2.0 * focalPointNDC.x * (1.0 - side);
vec2 focalPointUV = 0.5 * (focalPointNDC + vec2(1.0));
// block edges of vision to avoid sickness
vec2 visionSqueezeRatios = vec2(getVisionSqueezeX(), getVisionSqueezeY());
bool perEye = getVisionSqueezePerEye() > 0;
float frac = squeezeVision(perEye, varTexCoord0, visionSqueezeRatios, getVisionSqueezeTransitionRatio(), focalPointUV);
if (frac == 0.0) {
// world only
outFragColor = texture(colorMap, varTexCoord0);
} else {
// grid on the floor only or mixed
mat4 hmdSensorMatrix = getHMDSensorMatrix();
mat4 projectionMatrix = getProjectionMatrix(side);
mat4 projectionInverse = inverse(projectionMatrix);
float groundPlaneY = getVisionSqueezeGroundPlaneY();
float spotLightSize = getVisionSqueezeSpotlightSize();
vec4 gridColor = vec4(gridFloor(varTexCoord0, hmdSensorMatrix, projectionInverse, groundPlaneY, spotLightSize), 1.0);
vec4 preSqueezeColor = texture(colorMap, varTexCoord0);
// mix between grid and world
outFragColor = mix(preSqueezeColor, gridColor, frac);
}
}

View file

@ -0,0 +1 @@
VERTEX gpu::vertex::DrawUnitQuadTexcoord

View file

@ -392,6 +392,9 @@ void OpenGLDisplayPlugin::customizeContext() {
_drawTexturePipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTexture), scissorState);
_drawTextureSqueezePipeline =
gpu::Pipeline::create(gpu::Shader::createProgram(shader::display_plugins::program::DrawTextureWithVisionSqueeze), scissorState);
_linearToSRGBPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureLinearToSRGB), scissorState);
_SRGBToLinearPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureSRGBToLinear), scissorState);
@ -407,6 +410,7 @@ void OpenGLDisplayPlugin::customizeContext() {
void OpenGLDisplayPlugin::uncustomizeContext() {
_drawTexturePipeline.reset();
_drawTextureSqueezePipeline.reset();
_linearToSRGBPipeline.reset();
_SRGBToLinearPipeline.reset();
_cursorPipeline.reset();
@ -629,6 +633,10 @@ void OpenGLDisplayPlugin::compositePointer() {
});
}
void OpenGLDisplayPlugin::setupCompositeScenePipeline(gpu::Batch& batch) {
batch.setPipeline(_drawTexturePipeline);
}
void OpenGLDisplayPlugin::compositeScene() {
render([&](gpu::Batch& batch) {
batch.enableStereo(false);
@ -637,8 +645,8 @@ void OpenGLDisplayPlugin::compositeScene() {
batch.setStateScissorRect(ivec4(uvec2(), _compositeFramebuffer->getSize()));
batch.resetViewTransform();
batch.setProjectionTransform(mat4());
batch.setPipeline(_drawTexturePipeline);
batch.setResourceTexture(0, _currentFrame->framebuffer->getRenderBuffer(0));
setupCompositeScenePipeline(batch);
batch.draw(gpu::TRIANGLE_STRIP, 4);
});
}
@ -958,4 +966,3 @@ void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer ne
gpu::PipelinePointer OpenGLDisplayPlugin::getRenderTexturePipeline() {
return _drawTexturePipeline;
}

View file

@ -100,6 +100,7 @@ protected:
virtual QThread::Priority getPresentPriority() { return QThread::HighPriority; }
virtual void compositeLayers();
virtual void setupCompositeScenePipeline(gpu::Batch& batch);
virtual void compositeScene();
virtual void compositePointer();
virtual void compositeExtra(){};
@ -155,6 +156,7 @@ protected:
gpu::PipelinePointer _mirrorHUDPipeline;
gpu::ShaderPointer _mirrorHUDPS;
gpu::PipelinePointer _drawTexturePipeline;
gpu::PipelinePointer _drawTextureSqueezePipeline;
gpu::PipelinePointer _linearToSRGBPipeline;
gpu::PipelinePointer _SRGBToLinearPipeline;
gpu::PipelinePointer _cursorPipeline;

View file

@ -0,0 +1,106 @@
// Generated on <$_SCRIBE_DATE$>
//
// Created by Seth Alves on 2019-2-13.
// Copyright 2019 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
//
<@if not VISION_SQUEEZE_SLH@>
<@def VISION_SQUEEZE_SLH@>
float ellipse(vec2 coord, vec2 centerUV, vec2 semiAxis) {
return pow(coord.x - centerUV.x, 2.0) / semiAxis.x + pow(coord.y - centerUV.y, 2.0) / semiAxis.y;
}
vec4 extractFovTan(mat4 m) {
mat4 mt = transpose(m);
vec4 v;
vec4 result;
// x -- Left
v = mt * vec4(1.0, 0.0, 0.0, 1.0);
result.x = -(v.z / v.x);
// y -- Right
v = mt * vec4(-1.0, 0.0, 0.0, 1.0);
result.y = (v.z / v.x);
// z -- Down
v = mt * vec4(0.0, 1.0, 0.0, 1.0);
result.z = -(v.z / v.y);
// w -- Up
v = mt * vec4(0.0, -1.0, 0.0, 1.0);
result.w = v.z / v.y;
return result;
}
// takes left-side projection matrix, returns NDC for right eye. to get left, invert sign on x coord of result.
vec2 extractFocalPoint(vec4 fovTan) {
float fovwidth = fovTan.x + fovTan.y;
float fovheight = fovTan.z + fovTan.w;
vec2 focalPoint = vec2(fovTan.y / fovwidth, (fovTan.z / fovheight) - 0.5f);
return focalPoint;
}
float squeezeVision(bool perEye, vec2 varTexCoord0, vec2 visionSqueezeRatios, float transitionRatio, vec2 focalPointUV) {
if (visionSqueezeRatios.x == 0.0 && visionSqueezeRatios.y == 0.0) {
return 0.0;
}
vec2 centerUV;
vec2 semiAxis;
if (perEye) {
// tubes in front of each eye
centerUV = focalPointUV;
semiAxis = vec2(0.25) - visionSqueezeRatios * 0.25;
} else {
// one tube in front of face
centerUV = vec2(0.5, focalPointUV.y);
semiAxis = vec2(0.5) - visionSqueezeRatios * 0.5;
}
float ellipseValue = ellipse(varTexCoord0, centerUV, semiAxis);
float frac = clamp((ellipseValue - 1.0) / clamp(transitionRatio, 0.01, 0.7), 0.0, 1.0);
return frac;
}
vec3 gridFloor(vec2 varTexCoord0, mat4 hmdSensorMatrix, mat4 projectionInverse, float groundPlaneY, float spotLightSize) {
vec4 ndc = vec4(varTexCoord0.x * 4.0 - 1.0 - 2.0 * float(varTexCoord0.x > 0.5), varTexCoord0.y * 2.0 - 1.0, -1.0, 1.0);
vec4 fragmentEyeCoords = hmdSensorMatrix * projectionInverse * ndc;
vec4 near4 = hmdSensorMatrix * vec4(0.0, 0.0, 0.0, 1.0);
vec3 near = (near4 / near4.w).xyz;
vec3 far = fragmentEyeCoords.xyz / fragmentEyeCoords.w;
// intersect a line from near to far with the plane y = groundPlaneY
float t = -(near.y - groundPlaneY) / (far.y - near.y);
vec2 R = (near + t * (far - near)).xz;
float lineThickness = 1.5 / length(R);
vec4 gridColor = vec4(0.35);
vec4 baseColor = vec4(0.1);
vec4 skyColor = vec4(0.0, 0.0, 0.0, 0.0);
vec2 wrapped = fract(R) - 0.5f;
vec2 range = abs(wrapped);
vec2 speeds = fwidth(R);
vec2 pixelRange = range/speeds;
float lineWeight = clamp(min(pixelRange.x, pixelRange.y) - lineThickness, 0.0, 1.0);
float horizonFuzz = 0.02;
if (t < 0.0) {
return mix(gridColor, skyColor, clamp(0.0, 1.0, -t)).xyz;
} else if (t < horizonFuzz) {
lineWeight = lineWeight * max(0.0, t);
}
vec4 c = mix(gridColor, baseColor, lineWeight);
// fade out grid to avoid shimmer
float fadeVal = 0.7;
return mix(c, baseColor * fadeVal + gridColor * (1.0 - fadeVal),
0.1 * clamp((length(R) - spotLightSize), 0.0, 1.0)).xyz;
}
<@endif@>

View file

@ -1,4 +1,4 @@
//
//
// Created by Bradley Austin Davis on 2016/02/15
// Copyright 2016 High Fidelity, Inc.
//
@ -113,6 +113,11 @@ void HmdDisplayPlugin::internalDeactivate() {
}
void HmdDisplayPlugin::customizeContext() {
VisionSqueezeParameters parameters;
_visionSqueezeParametersBuffer =
gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(VisionSqueezeParameters), (const gpu::Byte*) &parameters));
Parent::customizeContext();
_hudRenderer.build();
}
@ -478,3 +483,48 @@ HmdDisplayPlugin::~HmdDisplayPlugin() {
float HmdDisplayPlugin::stutterRate() const {
return _stutterRate.rate();
}
float adjustVisionSqueezeRatioForDevice(float visionSqueezeRatio, float visionSqueezeDeviceLow, float visionSqueezeDeviceHigh) {
if (visionSqueezeRatio <= 0.0f) {
return 0.0f;
}
float deviceRange = visionSqueezeDeviceHigh - visionSqueezeDeviceLow;
const float SQUEEZE_ADJUSTMENT = 0.75f; // magic number picked through experimentation
return deviceRange * (SQUEEZE_ADJUSTMENT * visionSqueezeRatio) + visionSqueezeDeviceLow;
}
void HmdDisplayPlugin::updateVisionSqueezeParameters(float visionSqueezeX, float visionSqueezeY,
float visionSqueezeTransition,
int visionSqueezePerEye, float visionSqueezeGroundPlaneY,
float visionSqueezeSpotlightSize) {
visionSqueezeX = adjustVisionSqueezeRatioForDevice(visionSqueezeX, _visionSqueezeDeviceLowX, _visionSqueezeDeviceHighX);
visionSqueezeY = adjustVisionSqueezeRatioForDevice(visionSqueezeY, _visionSqueezeDeviceLowY, _visionSqueezeDeviceHighY);
auto& params = _visionSqueezeParametersBuffer.get<VisionSqueezeParameters>();
if (params._visionSqueezeX != visionSqueezeX) {
_visionSqueezeParametersBuffer.edit<VisionSqueezeParameters>()._visionSqueezeX = visionSqueezeX;
}
if (params._visionSqueezeY != visionSqueezeY) {
_visionSqueezeParametersBuffer.edit<VisionSqueezeParameters>()._visionSqueezeY = visionSqueezeY;
}
if (params._visionSqueezeTransition != visionSqueezeTransition) {
_visionSqueezeParametersBuffer.edit<VisionSqueezeParameters>()._visionSqueezeTransition = visionSqueezeTransition;
}
if (params._visionSqueezePerEye != visionSqueezePerEye) {
_visionSqueezeParametersBuffer.edit<VisionSqueezeParameters>()._visionSqueezePerEye = visionSqueezePerEye;
}
if (params._visionSqueezeGroundPlaneY != visionSqueezeGroundPlaneY) {
_visionSqueezeParametersBuffer.edit<VisionSqueezeParameters>()._visionSqueezeGroundPlaneY = visionSqueezeGroundPlaneY;
}
if (params._visionSqueezeSpotlightSize != visionSqueezeSpotlightSize) {
_visionSqueezeParametersBuffer.edit<VisionSqueezeParameters>()._visionSqueezeSpotlightSize = visionSqueezeSpotlightSize;
}
}
void HmdDisplayPlugin::setupCompositeScenePipeline(gpu::Batch& batch) {
batch.setPipeline(_drawTextureSqueezePipeline);
_visionSqueezeParametersBuffer.edit<VisionSqueezeParameters>()._hmdSensorMatrix = _currentPresentFrameInfo.presentPose;
batch.setUniformBuffer(drawTextureWithVisionSqueezeParamsSlot, _visionSqueezeParametersBuffer);
}

View file

@ -50,6 +50,9 @@ public:
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> getHUDOperator() override;
virtual StencilMaskMode getStencilMaskMode() const override { return StencilMaskMode::PAINT; }
void updateVisionSqueezeParameters(float visionSqueezeX, float visionSqueezeY, float visionSqueezeTransition,
int visionSqueezePerEye, float visionSqueezeGroundPlaneY,
float visionSqueezeSpotlightSize);
signals:
void hmdMountedChanged();
@ -91,6 +94,33 @@ protected:
RateCounter<> _stutterRate;
bool _disablePreview { true };
class VisionSqueezeParameters {
public:
float _visionSqueezeX { 0.0f };
float _visionSqueezeY { 0.0f };
float _spareA { 0.0f };
float _spareB { 0.0f };
glm::mat4 _leftProjection;
glm::mat4 _rightProjection;
glm::mat4 _hmdSensorMatrix;
float _visionSqueezeTransition { 0.15f };
int _visionSqueezePerEye { 0 };
float _visionSqueezeGroundPlaneY { 0.0f };
float _visionSqueezeSpotlightSize { 0.0f };
VisionSqueezeParameters() {}
};
typedef gpu::BufferView UniformBufferView;
gpu::BufferView _visionSqueezeParametersBuffer;
virtual void setupCompositeScenePipeline(gpu::Batch& batch) override;
float _visionSqueezeDeviceLowX { 0.0f };
float _visionSqueezeDeviceHighX { 1.0f };
float _visionSqueezeDeviceLowY { 0.0f };
float _visionSqueezeDeviceHighY { 1.0f };
private:
ivec4 getViewportForSourceSize(const uvec2& size) const;
float getLeftCenterPixel() const;
@ -112,7 +142,7 @@ private:
struct Uniforms {
float alpha { 1.0f };
} uniforms;
struct Vertex {
vec3 pos;
vec2 uv;
@ -126,3 +156,5 @@ private:
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> render();
} _hudRenderer;
};
const int drawTextureWithVisionSqueezeParamsSlot = 1; // must match binding in DrawTextureWithVisionSqueeze.slf

View file

@ -122,7 +122,7 @@ void GridEntityRenderer::doRender(RenderArgs* args) {
forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD;
});
if (!_visible) {
if (!_visible || color.a == 0.0f) {
return;
}

View file

@ -282,27 +282,26 @@ bool RenderableModelEntityItem::findDetailedParabolaIntersection(const glm::vec3
}
void RenderableModelEntityItem::fetchCollisionGeometryResource() {
_compoundShapeResource = DependencyManager::get<ModelCache>()->getCollisionGeometryResource(getCollisionShapeURL());
_collisionGeometryResource = DependencyManager::get<ModelCache>()->getCollisionGeometryResource(getCollisionShapeURL());
}
bool RenderableModelEntityItem::computeShapeFailedToLoad() {
if (!_compoundShapeResource) {
bool RenderableModelEntityItem::unableToLoadCollisionShape() {
if (!_collisionGeometryResource) {
fetchCollisionGeometryResource();
}
return (_compoundShapeResource && _compoundShapeResource->isFailed());
return (_collisionGeometryResource && _collisionGeometryResource->isFailed());
}
void RenderableModelEntityItem::setShapeType(ShapeType type) {
ModelEntityItem::setShapeType(type);
auto shapeType = getShapeType();
if (shapeType == SHAPE_TYPE_COMPOUND || shapeType == SHAPE_TYPE_SIMPLE_COMPOUND) {
if (!_compoundShapeResource && !getCollisionShapeURL().isEmpty()) {
if (!_collisionGeometryResource && !getCollisionShapeURL().isEmpty()) {
fetchCollisionGeometryResource();
}
} else if (_compoundShapeResource && !getCompoundShapeURL().isEmpty()) {
} else if (_collisionGeometryResource && !getCompoundShapeURL().isEmpty()) {
// the compoundURL has been set but the shapeType does not agree
_compoundShapeResource.reset();
_collisionGeometryResource.reset();
}
}
@ -333,11 +332,11 @@ bool RenderableModelEntityItem::isReadyToComputeShape() const {
}
if (model->isLoaded()) {
if (!shapeURL.isEmpty() && !_compoundShapeResource) {
if (!shapeURL.isEmpty() && !_collisionGeometryResource) {
const_cast<RenderableModelEntityItem*>(this)->fetchCollisionGeometryResource();
}
if (_compoundShapeResource && _compoundShapeResource->isLoaded()) {
if (_collisionGeometryResource && _collisionGeometryResource->isLoaded()) {
// we have both URLs AND both geometries AND they are both fully loaded.
if (_needsInitialSimulation) {
// the _model's offset will be wrong until _needsInitialSimulation is false
@ -368,7 +367,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
}
if (type == SHAPE_TYPE_COMPOUND) {
if (!_compoundShapeResource || !_compoundShapeResource->isLoaded()) {
if (!_collisionGeometryResource || !_collisionGeometryResource->isLoaded()) {
return;
}
@ -376,8 +375,8 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
// should never fall in here when collision model not fully loaded
// TODO: assert that all geometries exist and are loaded
//assert(_model && _model->isLoaded() && _compoundShapeResource && _compoundShapeResource->isLoaded());
const HFMModel& collisionGeometry = _compoundShapeResource->getHFMModel();
//assert(_model && _model->isLoaded() && _collisionGeometryResource && _collisionGeometryResource->isLoaded());
const HFMModel& collisionGeometry = _collisionGeometryResource->getHFMModel();
ShapeInfo::PointCollection& pointCollection = shapeInfo.getPointCollection();
pointCollection.clear();
@ -499,7 +498,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
std::vector<std::shared_ptr<const graphics::Mesh>> meshes;
if (type == SHAPE_TYPE_SIMPLE_COMPOUND) {
auto& hfmMeshes = _compoundShapeResource->getHFMModel().meshes;
auto& hfmMeshes = _collisionGeometryResource->getHFMModel().meshes;
meshes.reserve(hfmMeshes.size());
for (auto& hfmMesh : hfmMeshes) {
meshes.push_back(hfmMesh._mesh);
@ -727,10 +726,10 @@ int RenderableModelEntityItem::avatarJointIndex(int modelJointIndex) {
bool RenderableModelEntityItem::contains(const glm::vec3& point) const {
auto model = getModel();
if (EntityItem::contains(point) && model && _compoundShapeResource && _compoundShapeResource->isLoaded()) {
if (EntityItem::contains(point) && model && _collisionGeometryResource && _collisionGeometryResource->isLoaded()) {
glm::mat4 worldToHFMMatrix = model->getWorldToHFMMatrix();
glm::vec3 hfmPoint = worldToHFMMatrix * glm::vec4(point, 1.0f);
return _compoundShapeResource->getHFMModel().convexHullContains(hfmPoint);
return _collisionGeometryResource->getHFMModel().convexHullContains(hfmPoint);
}
return false;

View file

@ -79,7 +79,7 @@ public:
virtual bool isReadyToComputeShape() const override;
virtual void computeShapeInfo(ShapeInfo& shapeInfo) override;
bool computeShapeFailedToLoad();
bool unableToLoadCollisionShape();
virtual bool contains(const glm::vec3& point) const override;
void stopModelOverrideIfNoParent();
@ -120,7 +120,7 @@ private:
bool readyToAnimate() const;
void fetchCollisionGeometryResource();
GeometryResource::Pointer _compoundShapeResource;
GeometryResource::Pointer _collisionGeometryResource;
std::vector<int> _jointMap;
QVariantMap _originalTextures;
bool _jointMapCompleted { false };

View file

@ -23,7 +23,7 @@ static uint8_t CUSTOM_PIPELINE_NUMBER = 0;
static gpu::Stream::FormatPointer _vertexFormat;
static std::weak_ptr<gpu::Pipeline> _texturedPipeline;
static ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, gpu::Batch& batch) {
static ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, RenderArgs* args) {
auto texturedPipeline = _texturedPipeline.lock();
if (!texturedPipeline) {
auto state = std::make_shared<gpu::State>();

View file

@ -34,9 +34,7 @@
#include "EntityTreeRenderer.h"
#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT
# include <FadeEffect.h>
#endif
#include <FadeEffect.h>
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
@ -1553,52 +1551,49 @@ using namespace render;
using namespace render::entities;
static uint8_t CUSTOM_PIPELINE_NUMBER;
static gpu::PipelinePointer _pipelines[2];
static gpu::PipelinePointer _wireframePipelines[2];
static std::map<std::tuple<bool, bool, bool>, ShapePipelinePointer> _pipelines;
static gpu::Stream::FormatPointer _vertexFormat;
ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, gpu::Batch& batch) {
if (!_pipelines[0]) {
ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, RenderArgs* args) {
// FIXME: custom pipelines like this don't handle shadows or renderLayers correctly
if (_pipelines.empty()) {
using namespace shader::entities_renderer::program;
int programsIds[2] = { polyvox, polyvox_fade };
auto state = std::make_shared<gpu::State>();
state->setCullMode(gpu::State::CULL_BACK);
state->setDepthTest(true, true, gpu::LESS_EQUAL);
PrepareStencil::testMaskDrawShape(*state);
static const std::vector<std::tuple<bool, bool, uint32_t>> keys = {
std::make_tuple(false, false, polyvox), std::make_tuple(true, false, polyvox_forward)
#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT
, std::make_tuple(false, true, polyvox_fade), std::make_tuple(true, true, polyvox_forward_fade)
#else
, std::make_tuple(false, true, polyvox), std::make_tuple(true, true, polyvox_forward)
#endif
};
for (auto& key : keys) {
for (int i = 0; i < 2; ++i) {
bool wireframe = i != 0;
auto wireframeState = std::make_shared<gpu::State>();
wireframeState->setCullMode(gpu::State::CULL_BACK);
wireframeState->setDepthTest(true, true, gpu::LESS_EQUAL);
wireframeState->setFillMode(gpu::State::FILL_LINE);
PrepareStencil::testMaskDrawShape(*wireframeState);
auto state = std::make_shared<gpu::State>();
state->setCullMode(gpu::State::CULL_BACK);
state->setDepthTest(true, true, gpu::LESS_EQUAL);
PrepareStencil::testMaskDrawShape(*state);
// Two sets of pipelines: normal and fading
for (auto i = 0; i < 2; i++) {
gpu::ShaderPointer program = gpu::Shader::createProgram(programsIds[i]);
_pipelines[i] = gpu::Pipeline::create(program, state);
_wireframePipelines[i] = gpu::Pipeline::create(program, wireframeState);
if (wireframe) {
state->setFillMode(gpu::State::FILL_LINE);
}
auto pipeline = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<2>(key)), state);
if (std::get<1>(key)) {
_pipelines[std::make_tuple(std::get<0>(key), std::get<1>(key), wireframe)] = std::make_shared<render::ShapePipeline>(pipeline, nullptr, nullptr, nullptr);
} else {
const auto& fadeEffect = DependencyManager::get<FadeEffect>();
_pipelines[std::make_tuple(std::get<0>(key), std::get<1>(key), wireframe)] = std::make_shared<render::ShapePipeline>(pipeline, nullptr,
fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter());
}
}
}
}
#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT
if (key.isFaded()) {
const auto& fadeEffect = DependencyManager::get<FadeEffect>();
if (key.isWireframe()) {
return std::make_shared<render::ShapePipeline>(_wireframePipelines[1], nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter());
} else {
return std::make_shared<render::ShapePipeline>(_pipelines[1], nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter());
}
} else {
#endif
if (key.isWireframe()) {
return std::make_shared<render::ShapePipeline>(_wireframePipelines[0], nullptr, nullptr, nullptr);
} else {
return std::make_shared<render::ShapePipeline>(_pipelines[0], nullptr, nullptr, nullptr);
}
#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT
}
#endif
return _pipelines[std::make_tuple(args->_renderMethod == Args::RenderMethod::FORWARD, key.isFaded(), key.isWireframe())];
}
PolyVoxEntityRenderer::PolyVoxEntityRenderer(const EntityItemPointer& entity) : Parent(entity) {

View file

@ -30,14 +30,11 @@ using namespace render::entities;
// is a half unit sphere. However, the geometry cache renders a UNIT sphere, so we need to scale down.
static const float SPHERE_ENTITY_SCALE = 0.5f;
static_assert(shader::render_utils::program::simple != 0, "Validate simple program exists");
static_assert(shader::render_utils::program::simple_transparent != 0, "Validate simple transparent program exists");
ShapeEntityRenderer::ShapeEntityRenderer(const EntityItemPointer& entity) : Parent(entity) {
_procedural._vertexSource = gpu::Shader::getVertexShaderSource(shader::render_utils::vertex::simple);
_procedural._vertexSource = gpu::Shader::getVertexShaderSource(shader::render_utils::vertex::simple_procedural);
// FIXME: Setup proper uniform slots and use correct pipelines for forward rendering
_procedural._opaqueFragmentSource = gpu::Shader::Source::get(shader::render_utils::fragment::simple);
_procedural._transparentFragmentSource = gpu::Shader::Source::get(shader::render_utils::fragment::simple_transparent);
_procedural._opaqueFragmentSource = gpu::Shader::Source::get(shader::render_utils::fragment::simple_procedural);
_procedural._transparentFragmentSource = gpu::Shader::Source::get(shader::render_utils::fragment::simple_procedural_translucent);
// TODO: move into Procedural.cpp
PrepareStencil::testMaskDrawShape(*_procedural._opaqueState);

View file

@ -315,12 +315,19 @@ void WebEntityRenderer::doRender(RenderArgs* args) {
gpu::Batch& batch = *args->_batch;
glm::vec4 color;
Transform transform;
bool forward;
withReadLock([&] {
float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
color = glm::vec4(toGlm(_color), _alpha * fadeRatio);
color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created);
transform = _renderTransform;
forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == render::Args::FORWARD;
});
if (color.a == 0.0f) {
return;
}
batch.setResourceTexture(0, _texture);
transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition()));
@ -328,7 +335,7 @@ void WebEntityRenderer::doRender(RenderArgs* args) {
// Turn off jitter for these entities
batch.pushProjectionJitter();
DependencyManager::get<GeometryCache>()->bindWebBrowserProgram(batch, color.a < OPAQUE_ALPHA_THRESHOLD);
DependencyManager::get<GeometryCache>()->bindWebBrowserProgram(batch, color.a < OPAQUE_ALPHA_THRESHOLD, forward);
DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, texMin, texMax, color, _geometryId);
batch.popProjectionJitter();
batch.setResourceTexture(0, nullptr);

View file

@ -317,6 +317,8 @@ void ZoneEntityRenderer::updateKeySunFromEntity(const TypedEntityPointer& entity
sunLight->setIntensity(_keyLightProperties.getIntensity());
sunLight->setDirection(_lastRotation * _keyLightProperties.getDirection());
sunLight->setCastShadows(_keyLightProperties.getCastShadows());
sunLight->setShadowBias(_keyLightProperties.getShadowBias());
sunLight->setShadowsMaxDistance(_keyLightProperties.getShadowMaxDistance());
}
void ZoneEntityRenderer::updateAmbientLightFromEntity(const TypedEntityPointer& entity) {

View file

@ -0,0 +1 @@
DEFINES forward

View file

@ -0,0 +1 @@
DEFINES (shadow fade)/forward

View file

@ -1,10 +1,8 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// <$_SCRIBE_FILENAME$>
// Generated on <$_SCRIBE_DATE$>
//
// paintStroke.frag
// fragment shader
//
// Created by Eric Levin on 8/10/2015
// Copyright 2015 High Fidelity, Inc.
//
@ -12,29 +10,32 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
<@include DeferredBufferWrite.slh@>
<@if not HIFI_USE_FORWARD@>
<@include DeferredBufferWrite.slh@>
<@else@>
layout(location=0) out vec4 _fragColor0;
<@endif@>
<@include paintStroke.slh@>
<$declarePolyLineBuffers()$>
LAYOUT(binding=0) uniform sampler2D _texture;
layout(location=0) in vec3 _normalWS;
<@if not HIFI_USE_FORWARD@>
layout(location=0) in vec3 _normalWS;
<@endif@>
layout(location=1) in vec2 _texCoord;
layout(location=2) in vec4 _color;
layout(location=3) in float _distanceFromCenter;
void main(void) {
vec4 texel = texture(_texture, _texCoord);
float frontCondition = 2.0 * float(gl_FrontFacing) - 1.0;
vec3 color = _color.rgb * texel.rgb;
float alpha = texel.a * _color.a;
texel *= _color;
texel.a *= mix(1.0, pow(1.0 - abs(_distanceFromCenter), 10.0), _polylineData.faceCameraGlow.y);
alpha *= mix(1.0, pow(1.0 - abs(_distanceFromCenter), 10.0), _polylineData.faceCameraGlow.y);
packDeferredFragmentTranslucent(
_normalWS * frontCondition,
alpha,
color,
DEFAULT_ROUGHNESS);
<@if not HIFI_USE_FORWARD@>
packDeferredFragmentTranslucent((2.0 * float(gl_FrontFacing) - 1.0) * _normalWS, texel.a, texel.rgb, DEFAULT_ROUGHNESS);
<@else@>
_fragColor0 = texel;
<@endif@>
}

View file

@ -1,10 +1,8 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// <$_SCRIBE_FILENAME$>
// Generated on <$_SCRIBE_DATE$>
//
// paintStroke.vert
// vertex shader
//
// Created by Eric Levin on 7/20/15.
// Copyright 2014 High Fidelity, Inc.
//
@ -20,7 +18,9 @@
<@include paintStroke.slh@>
<$declarePolyLineBuffers()$>
layout(location=0) out vec3 _normalWS;
<@if not HIFI_USE_FORWARD@>
layout(location=0) out vec3 _normalWS;
<@endif@>
layout(location=1) out vec2 _texCoord;
layout(location=2) out vec4 _color;
layout(location=3) out float _distanceFromCenter;
@ -50,11 +50,15 @@ void main(void) {
vec3 binormalEye = normalize(cross(normalEye, tangentEye));
posEye.xyz += _distanceFromCenter * vertex.binormalAndHalfWidth.w * binormalEye;
<$transformEyeToClipPos(cam, posEye, gl_Position)$>
<@if not HIFI_USE_FORWARD@>
<$transformEyeToWorldDir(cam, normalEye, _normalWS)$>
<@endif@>
} else {
vec3 normal = vertex.normal.xyz;
position.xyz += _distanceFromCenter * vertex.binormalAndHalfWidth.w * binormal;
<$transformModelToClipPos(cam, obj, position, gl_Position)$>
<@if not HIFI_USE_FORWARD@>
<$transformModelToWorldDir(cam, obj, normal, _normalWS)$>
<@endif@>
}
}

View file

@ -1,35 +0,0 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// paintStroke.frag
// fragment shader
//
// Created by Eric Levin on 8/10/2015
// 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 paintStroke.slh@>
<$declarePolyLineBuffers()$>
LAYOUT(binding=0) uniform sampler2D _texture;
layout(location=0) in vec3 _normalWS;
layout(location=1) in vec2 _texCoord;
layout(location=2) in vec4 _color;
layout(location=3) in float _distanceFromCenter;
layout(location=0) out vec4 _fragColor0;
void main(void) {
vec4 texel = texture(_texture, _texCoord);
int frontCondition = 1 - 2 * int(gl_FrontFacing);
vec3 color = _color.rgb * texel.rgb;
float alpha = texel.a * _color.a;
alpha *= mix(1.0, pow(1.0 - abs(_distanceFromCenter), 10.0), _polylineData.faceCameraGlow.y);
_fragColor0 = vec4(color, alpha);
}

View file

@ -1,8 +1,7 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// <$_SCRIBE_FILENAME$>
// Generated on <$_SCRIBE_DATE$>
// polyvox.frag
// fragment shader
//
// Created by Seth Alves on 2015-8-3
// Copyright 2015 High Fidelity, Inc.
@ -11,51 +10,111 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
<@include graphics/Material.slh@>
<@include DeferredBufferWrite.slh@>
<@include render-utils/ShaderConstants.h@>
<@include entities-renderer/ShaderConstants.h@>
<@if HIFI_USE_FADE@>
<@include Fade.slh@>
<$declareFadeFragment()$>
layout(location=RENDER_UTILS_ATTR_NORMAL_MS) in vec3 _normal;
layout(location=RENDER_UTILS_ATTR_POSITION_MS) in vec4 _position;
layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _worldPosition;
layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS;
<@endif@>
LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_XMAP) uniform sampler2D xMap;
LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_YMAP) uniform sampler2D yMap;
LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_ZMAP) uniform sampler2D zMap;
<@if not HIFI_USE_SHADOW@>
<@include graphics/Material.slh@>
<@include render-utils/ShaderConstants.h@>
<@include entities-renderer/ShaderConstants.h@>
struct PolyvoxParams {
vec4 voxelVolumeSize;
};
<@if not HIFI_USE_FORWARD@>
<@include DeferredBufferWrite.slh@>
<@else@>
<@include DefaultMaterials.slh@>
LAYOUT(binding=0) uniform polyvoxParamsBuffer {
PolyvoxParams params;
};
<@include GlobalLight.slh@>
<$declareEvalSkyboxGlobalColor(_SCRIBE_NULL, HIFI_USE_FORWARD)$>
<@include gpu/Transform.slh@>
<$declareStandardCameraTransform()$>
<@endif@>
<@if HIFI_USE_FORWARD@>
layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES;
<@endif@>
layout(location=RENDER_UTILS_ATTR_POSITION_MS) in vec3 _positionMS;
layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS;
LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_XMAP) uniform sampler2D xMap;
LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_YMAP) uniform sampler2D yMap;
LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_ZMAP) uniform sampler2D zMap;
struct PolyvoxParams {
vec4 voxelVolumeSize;
};
LAYOUT(binding=0) uniform polyvoxParamsBuffer {
PolyvoxParams params;
};
<@endif@>
<@if HIFI_USE_SHADOW or HIFI_USE_FORWARD@>
layout(location=0) out vec4 _fragColor0;
<@endif@>
void main(void) {
vec3 worldNormal = cross(dFdy(_worldPosition.xyz), dFdx(_worldPosition.xyz));
worldNormal = normalize(worldNormal);
<@if HIFI_USE_FADE@>
<@if not HIFI_USE_SHADOW@>
vec3 fadeEmissive;
FadeObjectParams fadeParams;
<$fetchFadeObjectParams(fadeParams)$>
applyFade(fadeParams, _positionWS.xyz, fadeEmissive);
<@else@>
FadeObjectParams fadeParams;
<$fetchFadeObjectParams(fadeParams)$>
applyFadeClip(fadeParams, _positionWS.xyz);
<@endif@>
<@endif@>
float inPositionX = (_worldPosition.x - 0.5) / params.voxelVolumeSize.x;
float inPositionY = (_worldPosition.y - 0.5) / params.voxelVolumeSize.y;
float inPositionZ = (_worldPosition.z - 0.5) / params.voxelVolumeSize.z;
<@if not HIFI_USE_SHADOW@>
float inPositionX = (_positionMS.x - 0.5) / params.voxelVolumeSize.x;
float inPositionY = (_positionMS.y - 0.5) / params.voxelVolumeSize.y;
float inPositionZ = (_positionMS.z - 0.5) / params.voxelVolumeSize.z;
vec4 xyDiffuse = texture(xMap, vec2(-inPositionX, -inPositionY));
vec4 xzDiffuse = texture(yMap, vec2(-inPositionX, inPositionZ));
vec4 yzDiffuse = texture(zMap, vec2(inPositionZ, -inPositionY));
vec3 xyDiffuseScaled = xyDiffuse.rgb * abs(worldNormal.z);
vec3 xzDiffuseScaled = xzDiffuse.rgb * abs(worldNormal.y);
vec3 yzDiffuseScaled = yzDiffuse.rgb * abs(worldNormal.x);
vec4 diffuse = vec4(xyDiffuseScaled + xzDiffuseScaled + yzDiffuseScaled, 1.0);
vec3 normalMS = normalize(cross(dFdy(_positionMS.xyz), dFdx(_positionMS.xyz)));
vec3 xyDiffuseScaled = xyDiffuse.rgb * abs(normalMS.z);
vec3 xzDiffuseScaled = xzDiffuse.rgb * abs(normalMS.y);
vec3 yzDiffuseScaled = yzDiffuse.rgb * abs(normalMS.x);
vec3 diffuse = vec3(xyDiffuseScaled + xzDiffuseScaled + yzDiffuseScaled);
packDeferredFragment(
_normal,
1.0,
vec3(diffuse),
DEFAULT_ROUGHNESS,
DEFAULT_METALLIC,
DEFAULT_EMISSIVE,
DEFAULT_OCCLUSION,
DEFAULT_SCATTERING);
<@if not HIFI_USE_FORWARD@>
packDeferredFragment(
normalize(_normalWS),
1.0,
diffuse,
DEFAULT_ROUGHNESS,
DEFAULT_METALLIC,
DEFAULT_EMISSIVE
<@if HIFI_USE_FADE@>
+ fadeEmissive
<@endif@>
,
DEFAULT_OCCLUSION,
DEFAULT_SCATTERING);
<@else@>
TransformCamera cam = getTransformCamera();
_fragColor0 = vec4(evalSkyboxGlobalColor(
cam._viewInverse,
1.0,
DEFAULT_OCCLUSION,
_positionES.xyz,
normalize(_normalWS),
diffuse,
DEFAULT_FRESNEL,
DEFAULT_METALLIC,
DEFAULT_ROUGHNESS),
1.0);
<@endif@>
<@else@>
_fragColor0 = vec4(1.0);
<@endif@>
}

View file

@ -1,8 +1,7 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// <$_SCRIBE_FILENAME$>
// Generated on <$_SCRIBE_DATE$>
// polyvox.vert
// vertex shader
//
// Copyright 2015 High Fidelity, Inc.
//
@ -11,20 +10,39 @@
//
<@include gpu/Inputs.slh@>
<@include gpu/Transform.slh@>
<@include render-utils/ShaderConstants.h@>
<@include gpu/Transform.slh@>
<$declareStandardTransform()$>
layout(location=RENDER_UTILS_ATTR_POSITION_MS) out vec4 _position;
layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _worldPosition;
layout(location=RENDER_UTILS_ATTR_NORMAL_MS) out vec3 _normal;
<@if HIFI_USE_FADE@>
layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS;
<@endif@>
<@if not HIFI_USE_SHADOW@>
<@if HIFI_USE_FORWARD@>
layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES;
<@endif@>
layout(location=RENDER_UTILS_ATTR_POSITION_MS) out vec3 _positionMS;
layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS;
<@endif@>
void main(void) {
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$>
<$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$>
_worldPosition = inPosition;
<@if HIFI_USE_SHADOW@>
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
<@else@>
<@if not HIFI_USE_FORWARD@>
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
<@else@>
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _positionES, gl_Position)$>
<@endif@>
<$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$>
_positionMS = inPosition.xyz;
<@endif@>
<@if HIFI_USE_FADE@>
<$transformModelToWorldPos(obj, inPosition, _positionWS)$>
<@endif@>
}

View file

@ -1,73 +0,0 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
// polyvox_fade.frag
// fragment shader
//
// Created by Olivier Prat on 2017-06-08
// 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 graphics/Material.slh@>
<@include DeferredBufferWrite.slh@>
<@include render-utils/ShaderConstants.h@>
<@include entities-renderer/ShaderConstants.h@>
<@include Fade.slh@>
layout(location=RENDER_UTILS_ATTR_NORMAL_MS) in vec3 _normal;
layout(location=RENDER_UTILS_ATTR_POSITION_MS) in vec4 _position;
layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _worldPosition;
layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _worldFadePosition;
LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_XMAP) uniform sampler2D xMap;
LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_YMAP) uniform sampler2D yMap;
LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_ZMAP) uniform sampler2D zMap;
struct PolyvoxParams {
vec4 voxelVolumeSize;
};
LAYOUT(binding=0) uniform polyvoxParamsBuffer {
PolyvoxParams params;
};
// Declare after all samplers to prevent sampler location mix up with voxel shading (sampler locations are hardcoded in RenderablePolyVoxEntityItem)
<$declareFadeFragment()$>
void main(void) {
vec3 emissive;
FadeObjectParams fadeParams;
<$fetchFadeObjectParams(fadeParams)$>
applyFade(fadeParams, _worldFadePosition.xyz, emissive);
vec3 worldNormal = cross(dFdy(_worldPosition.xyz), dFdx(_worldPosition.xyz));
worldNormal = normalize(worldNormal);
float inPositionX = (_worldPosition.x - 0.5) / params.voxelVolumeSize.x;
float inPositionY = (_worldPosition.y - 0.5) / params.voxelVolumeSize.y;
float inPositionZ = (_worldPosition.z - 0.5) / params.voxelVolumeSize.z;
vec4 xyDiffuse = texture(xMap, vec2(-inPositionX, -inPositionY));
vec4 xzDiffuse = texture(yMap, vec2(-inPositionX, inPositionZ));
vec4 yzDiffuse = texture(zMap, vec2(inPositionZ, -inPositionY));
vec3 xyDiffuseScaled = xyDiffuse.rgb * abs(worldNormal.z);
vec3 xzDiffuseScaled = xzDiffuse.rgb * abs(worldNormal.y);
vec3 yzDiffuseScaled = yzDiffuse.rgb * abs(worldNormal.x);
vec4 diffuse = vec4(xyDiffuseScaled + xzDiffuseScaled + yzDiffuseScaled, 1.0);
packDeferredFragment(
_normal,
1.0,
vec3(diffuse),
DEFAULT_ROUGHNESS,
DEFAULT_METALLIC,
DEFAULT_EMISSIVE+emissive,
DEFAULT_OCCLUSION,
DEFAULT_SCATTERING);
}

View file

@ -1,33 +0,0 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
// polyvox_fade.vert
// vertex shader
//
// Created by Seth Alves on 2015-8-3
// 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 gpu/Inputs.slh@>
<@include gpu/Transform.slh@>
<@include render-utils/ShaderConstants.h@>
<$declareStandardTransform()$>
layout(location=RENDER_UTILS_ATTR_POSITION_MS) out vec4 _position;
layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _worldPosition;
layout(location=RENDER_UTILS_ATTR_NORMAL_MS) out vec3 _normal;
layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _worldFadePosition;
void main(void) {
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$>
<$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$>
<$transformModelToWorldPos(obj, inPosition, _worldFadePosition)$>
_worldPosition = inPosition;
}

View file

@ -2753,6 +2753,8 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr
ADD_GROUP_PROPERTY_TO_MAP(PROP_KEYLIGHT_INTENSITY, KeyLight, keyLight, Intensity, intensity);
ADD_GROUP_PROPERTY_TO_MAP(PROP_KEYLIGHT_DIRECTION, KeyLight, keylight, Direction, direction);
ADD_GROUP_PROPERTY_TO_MAP(PROP_KEYLIGHT_CAST_SHADOW, KeyLight, keyLight, CastShadows, castShadows);
ADD_GROUP_PROPERTY_TO_MAP_WITH_RANGE(PROP_KEYLIGHT_SHADOW_BIAS, KeyLight, keyLight, ShadowBias, shadowBias, 0.0f, 1.0f);
ADD_GROUP_PROPERTY_TO_MAP_WITH_RANGE(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, KeyLight, keyLight, ShadowMaxDistance, shadowMaxDistance, 1.0f, 250.0f);
}
{ // Ambient light
ADD_GROUP_PROPERTY_TO_MAP(PROP_AMBIENT_LIGHT_INTENSITY, AmbientLight, ambientLight, Intensity, intensity);

View file

@ -159,6 +159,8 @@ enum EntityPropertyList {
PROP_DERIVED_29,
PROP_DERIVED_30,
PROP_DERIVED_31,
PROP_DERIVED_32,
PROP_DERIVED_33,
PROP_AFTER_LAST_ITEM,
@ -249,39 +251,41 @@ enum EntityPropertyList {
PROP_KEYLIGHT_INTENSITY = PROP_DERIVED_1,
PROP_KEYLIGHT_DIRECTION = PROP_DERIVED_2,
PROP_KEYLIGHT_CAST_SHADOW = PROP_DERIVED_3,
PROP_KEYLIGHT_SHADOW_BIAS = PROP_DERIVED_4,
PROP_KEYLIGHT_SHADOW_MAX_DISTANCE = PROP_DERIVED_5,
// Ambient light
PROP_AMBIENT_LIGHT_INTENSITY = PROP_DERIVED_4,
PROP_AMBIENT_LIGHT_URL = PROP_DERIVED_5,
PROP_AMBIENT_LIGHT_INTENSITY = PROP_DERIVED_6,
PROP_AMBIENT_LIGHT_URL = PROP_DERIVED_7,
// Skybox
PROP_SKYBOX_COLOR = PROP_DERIVED_6,
PROP_SKYBOX_URL = PROP_DERIVED_7,
PROP_SKYBOX_COLOR = PROP_DERIVED_8,
PROP_SKYBOX_URL = PROP_DERIVED_9,
// Haze
PROP_HAZE_RANGE = PROP_DERIVED_8,
PROP_HAZE_COLOR = PROP_DERIVED_9,
PROP_HAZE_GLARE_COLOR = PROP_DERIVED_10,
PROP_HAZE_ENABLE_GLARE = PROP_DERIVED_11,
PROP_HAZE_GLARE_ANGLE = PROP_DERIVED_12,
PROP_HAZE_ALTITUDE_EFFECT = PROP_DERIVED_13,
PROP_HAZE_CEILING = PROP_DERIVED_14,
PROP_HAZE_BASE_REF = PROP_DERIVED_15,
PROP_HAZE_BACKGROUND_BLEND = PROP_DERIVED_16,
PROP_HAZE_ATTENUATE_KEYLIGHT = PROP_DERIVED_17,
PROP_HAZE_KEYLIGHT_RANGE = PROP_DERIVED_18,
PROP_HAZE_KEYLIGHT_ALTITUDE = PROP_DERIVED_19,
PROP_HAZE_RANGE = PROP_DERIVED_10,
PROP_HAZE_COLOR = PROP_DERIVED_11,
PROP_HAZE_GLARE_COLOR = PROP_DERIVED_12,
PROP_HAZE_ENABLE_GLARE = PROP_DERIVED_13,
PROP_HAZE_GLARE_ANGLE = PROP_DERIVED_14,
PROP_HAZE_ALTITUDE_EFFECT = PROP_DERIVED_15,
PROP_HAZE_CEILING = PROP_DERIVED_16,
PROP_HAZE_BASE_REF = PROP_DERIVED_17,
PROP_HAZE_BACKGROUND_BLEND = PROP_DERIVED_18,
PROP_HAZE_ATTENUATE_KEYLIGHT = PROP_DERIVED_19,
PROP_HAZE_KEYLIGHT_RANGE = PROP_DERIVED_20,
PROP_HAZE_KEYLIGHT_ALTITUDE = PROP_DERIVED_21,
// Bloom
PROP_BLOOM_INTENSITY = PROP_DERIVED_20,
PROP_BLOOM_THRESHOLD = PROP_DERIVED_21,
PROP_BLOOM_SIZE = PROP_DERIVED_22,
PROP_FLYING_ALLOWED = PROP_DERIVED_23,
PROP_GHOSTING_ALLOWED = PROP_DERIVED_24,
PROP_FILTER_URL = PROP_DERIVED_25,
PROP_KEY_LIGHT_MODE = PROP_DERIVED_26,
PROP_AMBIENT_LIGHT_MODE = PROP_DERIVED_27,
PROP_SKYBOX_MODE = PROP_DERIVED_28,
PROP_HAZE_MODE = PROP_DERIVED_29,
PROP_BLOOM_MODE = PROP_DERIVED_30,
PROP_BLOOM_INTENSITY = PROP_DERIVED_22,
PROP_BLOOM_THRESHOLD = PROP_DERIVED_23,
PROP_BLOOM_SIZE = PROP_DERIVED_24,
PROP_FLYING_ALLOWED = PROP_DERIVED_25,
PROP_GHOSTING_ALLOWED = PROP_DERIVED_26,
PROP_FILTER_URL = PROP_DERIVED_27,
PROP_KEY_LIGHT_MODE = PROP_DERIVED_28,
PROP_AMBIENT_LIGHT_MODE = PROP_DERIVED_29,
PROP_SKYBOX_MODE = PROP_DERIVED_30,
PROP_HAZE_MODE = PROP_DERIVED_31,
PROP_BLOOM_MODE = PROP_DERIVED_32,
// Avatar priority
PROP_AVATAR_PRIORITY = PROP_DERIVED_31,
PROP_AVATAR_PRIORITY = PROP_DERIVED_33,
// Polyvox
PROP_VOXEL_VOLUME_SIZE = PROP_DERIVED_0,

View file

@ -22,6 +22,8 @@ const float KeyLightPropertyGroup::DEFAULT_KEYLIGHT_INTENSITY = 1.0f;
const float KeyLightPropertyGroup::DEFAULT_KEYLIGHT_AMBIENT_INTENSITY = 0.5f;
const glm::vec3 KeyLightPropertyGroup::DEFAULT_KEYLIGHT_DIRECTION = { 0.0f, -1.0f, 0.0f };
const bool KeyLightPropertyGroup::DEFAULT_KEYLIGHT_CAST_SHADOWS { false };
const float KeyLightPropertyGroup::DEFAULT_KEYLIGHT_SHADOW_BIAS { 0.5f };
const float KeyLightPropertyGroup::DEFAULT_KEYLIGHT_SHADOW_MAX_DISTANCE { 40.0f };
void KeyLightPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties,
QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const {
@ -30,6 +32,8 @@ void KeyLightPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desired
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_INTENSITY, KeyLight, keyLight, Intensity, intensity);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_DIRECTION, KeyLight, keyLight, Direction, direction);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_CAST_SHADOW, KeyLight, keyLight, CastShadows, castShadows);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_SHADOW_BIAS, KeyLight, keyLight, ShadowBias, shadowBias);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, KeyLight, keyLight, ShadowMaxDistance, shadowMaxDistance);
}
void KeyLightPropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) {
@ -37,6 +41,8 @@ void KeyLightPropertyGroup::copyFromScriptValue(const QScriptValue& object, bool
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, intensity, float, setIntensity);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, direction, vec3, setDirection);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, castShadows, bool, setCastShadows);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, shadowBias, float, setShadowBias);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, shadowMaxDistance, float, setShadowMaxDistance);
// legacy property support
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(keyLightColor, u8vec3Color, setColor, getColor);
@ -50,14 +56,18 @@ void KeyLightPropertyGroup::merge(const KeyLightPropertyGroup& other) {
COPY_PROPERTY_IF_CHANGED(intensity);
COPY_PROPERTY_IF_CHANGED(direction);
COPY_PROPERTY_IF_CHANGED(castShadows);
COPY_PROPERTY_IF_CHANGED(shadowBias);
COPY_PROPERTY_IF_CHANGED(shadowMaxDistance);
}
void KeyLightPropertyGroup::debugDump() const {
qCDebug(entities) << " KeyLightPropertyGroup: ---------------------------------------------";
qCDebug(entities) << " color:" << getColor(); // << "," << getColor()[1] << "," << getColor()[2];
qCDebug(entities) << " intensity:" << getIntensity();
qCDebug(entities) << " direction:" << getDirection();
qCDebug(entities) << " castShadows:" << getCastShadows();
qCDebug(entities) << " color:" << getColor();
qCDebug(entities) << " intensity:" << getIntensity();
qCDebug(entities) << " direction:" << getDirection();
qCDebug(entities) << " castShadows:" << getCastShadows();
qCDebug(entities) << " shadowBias:" << getShadowBias();
qCDebug(entities) << " shadowMaxDistance:" << getShadowMaxDistance();
}
void KeyLightPropertyGroup::listChangedProperties(QList<QString>& out) {
@ -73,6 +83,12 @@ void KeyLightPropertyGroup::listChangedProperties(QList<QString>& out) {
if (castShadowsChanged()) {
out << "keyLight-castShadows";
}
if (shadowBiasChanged()) {
out << "keyLight-shadowBias";
}
if (shadowMaxDistanceChanged()) {
out << "keyLight-shadowMaxDistance";
}
}
bool KeyLightPropertyGroup::appendToEditPacket(OctreePacketData* packetData,
@ -88,6 +104,8 @@ bool KeyLightPropertyGroup::appendToEditPacket(OctreePacketData* packetData,
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, getIntensity());
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, getDirection());
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOW, getCastShadows());
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_SHADOW_BIAS, getShadowBias());
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, getShadowMaxDistance());
return true;
}
@ -103,11 +121,15 @@ bool KeyLightPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFl
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, float, setIntensity);
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, glm::vec3, setDirection);
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOW, bool, setCastShadows);
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_SHADOW_BIAS, float, setShadowBias);
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, float, setShadowMaxDistance);
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_COLOR, Color);
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_INTENSITY, Intensity);
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_DIRECTION, Direction);
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_CAST_SHADOW, CastShadows);
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_SHADOW_BIAS, ShadowBias);
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, ShadowMaxDistance);
processedBytes += bytesRead;
@ -121,6 +143,8 @@ void KeyLightPropertyGroup::markAllChanged() {
_intensityChanged = true;
_directionChanged = true;
_castShadowsChanged = true;
_shadowBiasChanged = true;
_shadowMaxDistanceChanged = true;
}
EntityPropertyFlags KeyLightPropertyGroup::getChangedProperties() const {
@ -130,6 +154,8 @@ EntityPropertyFlags KeyLightPropertyGroup::getChangedProperties() const {
CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_INTENSITY, intensity);
CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_DIRECTION, direction);
CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_CAST_SHADOW, castShadows);
CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_SHADOW_BIAS, shadowBias);
CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, shadowMaxDistance);
return changedProperties;
}
@ -139,6 +165,8 @@ void KeyLightPropertyGroup::getProperties(EntityItemProperties& properties) cons
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(KeyLight, Intensity, getIntensity);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(KeyLight, Direction, getDirection);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(KeyLight, CastShadows, getCastShadows);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(KeyLight, ShadowBias, getShadowBias);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(KeyLight, ShadowMaxDistance, getShadowMaxDistance);
}
bool KeyLightPropertyGroup::setProperties(const EntityItemProperties& properties) {
@ -148,6 +176,8 @@ bool KeyLightPropertyGroup::setProperties(const EntityItemProperties& properties
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(KeyLight, Intensity, intensity, setIntensity);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(KeyLight, Direction, direction, setDirection);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(KeyLight, CastShadows, castShadows, setCastShadows);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(KeyLight, ShadowBias, shadowBias, setShadowBias);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(KeyLight, ShadowMaxDistance, shadowMaxDistance, setShadowMaxDistance);
return somethingChanged;
}
@ -159,6 +189,8 @@ EntityPropertyFlags KeyLightPropertyGroup::getEntityProperties(EncodeBitstreamPa
requestedProperties += PROP_KEYLIGHT_INTENSITY;
requestedProperties += PROP_KEYLIGHT_DIRECTION;
requestedProperties += PROP_KEYLIGHT_CAST_SHADOW;
requestedProperties += PROP_KEYLIGHT_SHADOW_BIAS;
requestedProperties += PROP_KEYLIGHT_SHADOW_MAX_DISTANCE;
return requestedProperties;
}
@ -177,6 +209,8 @@ void KeyLightPropertyGroup::appendSubclassData(OctreePacketData* packetData, Enc
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, getIntensity());
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, getDirection());
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOW, getCastShadows());
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_SHADOW_BIAS, getShadowBias());
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, getShadowMaxDistance());
}
int KeyLightPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
@ -191,6 +225,8 @@ int KeyLightPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char*
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, float, setIntensity);
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, glm::vec3, setDirection);
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOW, bool, setCastShadows);
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_SHADOW_BIAS, float, setShadowBias);
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, float, setShadowMaxDistance);
return bytesRead;
}

View file

@ -37,6 +37,10 @@ class ReadBitstreamToTreeParams;
* are cast by avatars, plus {@link Entities.EntityProperties-Model|Model} and
* {@link Entities.EntityProperties-Shape|Shape} entities that have their
* <code>{@link Entities.EntityProperties|canCastShadow}</code> property set to <code>true</code>.
* @property {number} shadowBias=0.5 - The bias of the shadows cast by the light. Use this to fine-tune your shadows to your scene
* to prevent shadow acne and peter panning. In the range <code>0.0</code> &ndash; <code>1.0</code>.
* @property {number} shadowMaxDistance=40.0 - The max distance from your view at which shadows will be computed. Higher values will
* cover more of your scene, but with less precision. In the range <code>1.0</code> &ndash; <code>250.0</code>.
*/
class KeyLightPropertyGroup : public PropertyGroup {
public:
@ -90,11 +94,15 @@ public:
static const float DEFAULT_KEYLIGHT_AMBIENT_INTENSITY;
static const glm::vec3 DEFAULT_KEYLIGHT_DIRECTION;
static const bool DEFAULT_KEYLIGHT_CAST_SHADOWS;
static const float DEFAULT_KEYLIGHT_SHADOW_BIAS;
static const float DEFAULT_KEYLIGHT_SHADOW_MAX_DISTANCE;
DEFINE_PROPERTY_REF(PROP_KEYLIGHT_COLOR, Color, color, glm::u8vec3, DEFAULT_KEYLIGHT_COLOR);
DEFINE_PROPERTY(PROP_KEYLIGHT_INTENSITY, Intensity, intensity, float, DEFAULT_KEYLIGHT_INTENSITY);
DEFINE_PROPERTY_REF(PROP_KEYLIGHT_DIRECTION, Direction, direction, glm::vec3, DEFAULT_KEYLIGHT_DIRECTION);
DEFINE_PROPERTY(PROP_KEYLIGHT_CAST_SHADOW, CastShadows, castShadows, bool, DEFAULT_KEYLIGHT_CAST_SHADOWS);
DEFINE_PROPERTY(PROP_KEYLIGHT_SHADOW_BIAS, ShadowBias, shadowBias, float, DEFAULT_KEYLIGHT_SHADOW_BIAS);
DEFINE_PROPERTY(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, ShadowMaxDistance, shadowMaxDistance, float, DEFAULT_KEYLIGHT_SHADOW_MAX_DISTANCE);
};
#endif // hifi_KeyLightPropertyGroup_h

View file

@ -26,13 +26,19 @@ size_t evalGLFormatSwapchainPixelSize(const QSurfaceFormat& format) {
return pixelSize;
}
static bool FORCE_DISABLE_OPENGL_45 = false;
void gl::setDisableGl45(bool disable) {
FORCE_DISABLE_OPENGL_45 = disable;
}
bool gl::disableGl45() {
#if defined(USE_GLES)
return false;
#else
static const QString DEBUG_FLAG("HIFI_DISABLE_OPENGL_45");
static bool disableOpenGL45 = QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG);
return disableOpenGL45;
return FORCE_DISABLE_OPENGL_45 || disableOpenGL45;
#endif
}
@ -202,6 +208,15 @@ uint16_t gl::getAvailableVersion() {
return;
}
gl::initModuleGl();
std::string glvendor{ (const char*)glGetString(GL_VENDOR) };
std::transform(glvendor.begin(), glvendor.end(), glvendor.begin(), ::tolower);
// Intel has *notoriously* buggy DSA implementations, especially around cubemaps
if (std::string::npos != glvendor.find("intel")) {
gl::setDisableGl45(true);
}
wglMakeCurrent(0, 0);
hGLRC.reset();
if (!wglChoosePixelFormatARB || !wglCreateContextAttribsARB) {

View file

@ -55,6 +55,7 @@ namespace gl {
bool checkGLErrorDebug(const char* name);
bool disableGl45();
void setDisableGl45(bool disable);
uint16_t getTargetVersion();

View file

@ -220,7 +220,7 @@ double Context::getFrameTimerBatchAverage() const {
const Backend::TransformCamera& Backend::TransformCamera::recomputeDerived(const Transform& xformView) const {
_projectionInverse = glm::inverse(_projection);
// Get the viewEyeToWorld matrix form the transformView as passed to the gpu::Batch
// Get the viewEyeToWorld matrix from the transformView as passed to the gpu::Batch
// this is the "_viewInverse" fed to the shader
// Genetrate the "_view" matrix as well from the xform
xformView.getMatrix(_viewInverse);

View file

@ -98,7 +98,7 @@ void Haze::setHazeGlareColor(const glm::vec3 hazeGlareColor) {
void Haze::setHazeActive(const bool isHazeActive) {
auto& params = _hazeParametersBuffer.get<Parameters>();
if (((params.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE )&& !isHazeActive) {
if (((params.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) && !isHazeActive) {
_hazeParametersBuffer.edit<Parameters>().hazeMode &= ~HAZE_MODE_IS_ACTIVE;
} else if (((params.hazeMode & HAZE_MODE_IS_ACTIVE) != HAZE_MODE_IS_ACTIVE) && isHazeActive) {
_hazeParametersBuffer.edit<Parameters>().hazeMode |= HAZE_MODE_IS_ACTIVE;

View file

@ -10,7 +10,7 @@
<@if not HAZE_SLH@>
<@def HAZE_SLH@>
<@include render-utils/ShaderConstants.h@>
<@include graphics/ShaderConstants.h@>
const int HAZE_MODE_IS_ACTIVE = 1 << 0;
const int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;
@ -38,8 +38,7 @@ struct HazeParams {
float hazeKeyLightAltitudeFactor;
};
// See ShapePipeline::Slot::BUFFER in ShapePipeline.h
LAYOUT_STD140(binding=RENDER_UTILS_BUFFER_HAZE_PARAMS) uniform hazeBuffer {
LAYOUT_STD140(binding=GRAPHICS_BUFFER_HAZE_PARAMS) uniform hazeBuffer {
HazeParams hazeParams;
};

View file

@ -81,20 +81,12 @@ float Light::getShadowsMaxDistance() const {
return _shadowsMaxDistance;
}
void Light::setShadowsBiasScale(const float scale) {
_shadowsBiasScale = std::max(0.0f, scale);
void Light::setShadowBias(float bias) {
_shadowBias = bias;
}
float Light::getShadowsBiasScale() const {
return _shadowsBiasScale;
}
void Light::setBiasInput(float bias) {
_biasInput = bias;
}
float Light::getBiasInput() const {
return _biasInput;
float Light::getShadowBias() const {
return _shadowBias;
}
void Light::setColor(const Color& color) {

View file

@ -109,11 +109,8 @@ public:
void setShadowsMaxDistance(const float maxDistance);
float getShadowsMaxDistance() const;
void setShadowsBiasScale(const float scale);
float getShadowsBiasScale() const;
void setBiasInput(float bias);
float getBiasInput() const;
void setShadowBias(float bias);
float getShadowBias() const;
void setOrientation(const Quat& orientation);
const glm::quat& getOrientation() const { return _transform.getRotation(); }
@ -201,9 +198,8 @@ protected:
Type _type { SUN };
float _spotCos { -1.0f }; // stored here to be able to reset the spot angle when turning the type spot on/off
float _shadowsMaxDistance{ 40.0f };
float _shadowsBiasScale{ 1.0f };
float _biasInput{ 0.5f }; // 0.23f will roughly give the default constant and slope values
float _shadowsMaxDistance { 40.0f };
float _shadowBias { 0.5f };
bool _castShadows{ false };
void updateLightRadius();

View file

@ -32,6 +32,8 @@
#define GRAPHICS_TEXTURE_SKYBOX 11
#define GRAPHICS_BUFFER_SKYBOX_PARAMS 5
#define GRAPHICS_BUFFER_HAZE_PARAMS 7
// <!
namespace graphics { namespace slot {
@ -43,7 +45,8 @@ enum Buffer {
Light = GRAPHICS_BUFFER_LIGHT,
KeyLight = GRAPHICS_BUFFER_KEY_LIGHT,
AmbientLight = GRAPHICS_BUFFER_AMBIENT_LIGHT,
SkyboxParams = GRAPHICS_BUFFER_SKYBOX_PARAMS
SkyboxParams = GRAPHICS_BUFFER_SKYBOX_PARAMS,
HazeParams = GRAPHICS_BUFFER_HAZE_PARAMS
};
} // namespace buffer

View file

@ -73,29 +73,29 @@ void Skybox::prepare(gpu::Batch& batch) const {
}
}
void Skybox::render(gpu::Batch& batch, const ViewFrustum& frustum) const {
void Skybox::render(gpu::Batch& batch, const ViewFrustum& frustum, bool forward) const {
updateSchemaBuffer();
Skybox::render(batch, frustum, (*this));
Skybox::render(batch, frustum, (*this), forward);
}
void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Skybox& skybox) {
// Create the static shared elements used to render the skybox
static gpu::BufferPointer theConstants;
static gpu::PipelinePointer thePipeline;
static std::once_flag once;
std::call_once(once, [&] {
{
auto skyShader = gpu::Shader::createProgram(shader::graphics::program::skybox);
auto skyState = std::make_shared<gpu::State>();
static std::map<bool, gpu::PipelinePointer> _pipelines;
void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Skybox& skybox, bool forward) {
if (_pipelines.empty()) {
static const std::vector<std::tuple<bool, uint32_t>> keys = {
std::make_tuple(false, shader::graphics::program::skybox),
std::make_tuple(true, shader::graphics::program::skybox_forward)
};
for (auto& key : keys) {
auto state = std::make_shared<gpu::State>();
// Must match PrepareStencil::STENCIL_BACKGROUND
const int8_t STENCIL_BACKGROUND = 0;
skyState->setStencilTest(true, 0xFF, gpu::State::StencilTest(STENCIL_BACKGROUND, 0xFF, gpu::EQUAL,
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(STENCIL_BACKGROUND, 0xFF, gpu::EQUAL,
gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
thePipeline = gpu::Pipeline::create(skyShader, skyState);
_pipelines[std::get<0>(key)] = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<1>(key)), state);
}
});
}
// Render
glm::mat4 projMat;
@ -111,7 +111,7 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky
batch.setViewTransform(viewTransform);
batch.setModelTransform(Transform()); // only for Mac
batch.setPipeline(thePipeline);
batch.setPipeline(_pipelines[forward]);
skybox.prepare(batch);
batch.draw(gpu::TRIANGLE_STRIP, 4);

View file

@ -44,9 +44,9 @@ public:
virtual void clear();
void prepare(gpu::Batch& batch) const;
virtual void render(gpu::Batch& batch, const ViewFrustum& frustum) const;
virtual void render(gpu::Batch& batch, const ViewFrustum& frustum, bool forward) const;
static void render(gpu::Batch& batch, const ViewFrustum& frustum, const Skybox& skybox);
static void render(gpu::Batch& batch, const ViewFrustum& frustum, const Skybox& skybox, bool forward);
const UniformBufferView& getSchemaBuffer() const { return _schemaBuffer; }

View file

@ -1,8 +1,7 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// <$_SCRIBE_FILENAME$>
// Generated on <$_SCRIBE_DATE$>
// skybox.frag
// fragment shader
//
// Created by Sam Gateau on 5/5/2015.
// Copyright 2015 High Fidelity, Inc.
@ -12,6 +11,16 @@
//
<@include graphics/ShaderConstants.h@>
<@if HIFI_USE_FORWARD@>
<@include gpu/Transform.slh@>
<$declareStandardCameraTransform()$>
<@include graphics/Light.slh@>
<$declareLightBuffer()$>
<@include graphics/Haze.slh@>
<@endif@>
LAYOUT(binding=GRAPHICS_TEXTURE_SKYBOX) uniform samplerCube cubeMap;
struct Skybox {
@ -32,8 +41,28 @@ void main(void) {
// mix(skyboxColor, skyboxTexel, skybox.color.a)
// and the blend factor should be user controlled
vec3 skyboxTexel = texture(cubeMap, normalize(_normal)).rgb;
vec3 normal = normalize(_normal);
vec3 skyboxTexel = texture(cubeMap, normal).rgb;
vec3 skyboxColor = skybox.color.rgb;
_fragColor = vec4(mix(vec3(1.0), skyboxTexel, float(skybox.color.a > 0.0)) *
mix(vec3(1.0), skyboxColor, float(skybox.color.a < 1.0)), 1.0);
<@if HIFI_USE_FORWARD@>
// FIXME: either move this elsewhere or give it access to isHazeEnabled() (which is in render-utils/LightingModel.slh)
if (/*(isHazeEnabled() > 0.0) && */(hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {
TransformCamera cam = getTransformCamera();
vec4 eyePositionWS = cam._viewInverse[3];
// We choose an arbitrary large number > BLEND_DISTANCE in Haze.slh
const float SKYBOX_DISTANCE = 32000.0;
vec4 fragPositionWS = eyePositionWS + SKYBOX_DISTANCE * vec4(normal, 0.0);
vec4 fragPositionES = cam._view * fragPositionWS;
Light light = getKeyLight();
vec3 lightDirectionWS = getLightDirection(light);
vec4 hazeColor = computeHazeColor(fragPositionES.xyz, fragPositionWS.xyz, eyePositionWS.xyz, lightDirectionWS);
_fragColor.rgb = mix(_fragColor.rgb, hazeColor.rgb, hazeColor.a);
}
<@endif@>
}

View file

@ -0,0 +1 @@
DEFINES forward:f

View file

@ -1,8 +1,7 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// <$_SCRIBE_FILENAME$>
// Generated on <$_SCRIBE_DATE$>
// skybox.vert
// vertex shader
//
// Created by Sam Gateau on 5/5/2015.
// Copyright 2015 High Fidelity, Inc.
@ -12,7 +11,6 @@
//
<@include gpu/Transform.slh@>
<$declareStandardTransform()$>
layout(location=0) out vec3 _normal;

View file

@ -86,6 +86,7 @@ AccountManager::AccountManager(UserAgentGetter userAgentGetter) :
qRegisterMetaType<QHttpMultiPart*>("QHttpMultiPart*");
qRegisterMetaType<AccountManagerAuth::Type>();
connect(this, &AccountManager::loginComplete, this, &AccountManager::uploadPublicKey);
}
const QString DOUBLE_SLASH_SUBSTITUTE = "slashslash";
@ -838,18 +839,30 @@ void AccountManager::generateNewKeypair(bool isUserKeypair, const QUuid& domainI
connect(keypairGenerator, &RSAKeypairGenerator::errorGeneratingKeypair, this,
&AccountManager::handleKeypairGenerationError);
qCDebug(networking) << "Starting worker thread to generate 2048-bit RSA keypair.";
static constexpr int RSA_THREAD_PRIORITY = 1;
qCDebug(networking) << "Starting worker thread to generate 2048-bit RSA keypair, priority"
<< RSA_THREAD_PRIORITY << "- QThreadPool::maxThreadCount =" << QThreadPool::globalInstance()->maxThreadCount();
// Start on Qt's global thread pool.
QThreadPool::globalInstance()->start(keypairGenerator);
QThreadPool::globalInstance()->start(keypairGenerator, RSA_THREAD_PRIORITY);
}
}
void AccountManager::processGeneratedKeypair(QByteArray publicKey, QByteArray privateKey) {
qCDebug(networking) << "Generated 2048-bit RSA keypair. Uploading public key now.";
qCDebug(networking) << "Generated 2048-bit RSA keypair.";
// hold the private key to later set our metaverse API account info if upload succeeds
_pendingPublicKey = publicKey;
_pendingPrivateKey = privateKey;
uploadPublicKey();
}
void AccountManager::uploadPublicKey() {
if (_pendingPrivateKey.isEmpty()) {
return;
}
qCDebug(networking) << "Attempting upload of public key";
// upload the public key so data-web has an up-to-date key
const QString USER_PUBLIC_KEY_UPDATE_PATH = "api/v1/user/public_key";
@ -871,7 +884,7 @@ void AccountManager::processGeneratedKeypair(QByteArray publicKey, QByteArray pr
publicKeyPart.setHeader(QNetworkRequest::ContentDispositionHeader,
QVariant("form-data; name=\"public_key\"; filename=\"public_key\""));
publicKeyPart.setBody(publicKey);
publicKeyPart.setBody(_pendingPublicKey);
requestMultiPart->append(publicKeyPart);
// Currently broken? We don't have the temporary domain key.
@ -900,6 +913,7 @@ void AccountManager::publicKeyUploadSucceeded(QNetworkReply* reply) {
// public key upload complete - store the matching private key and persist the account to settings
_accountInfo.setPrivateKey(_pendingPrivateKey);
_pendingPublicKey.clear();
_pendingPrivateKey.clear();
persistAccountToFile();
@ -915,9 +929,6 @@ void AccountManager::publicKeyUploadFailed(QNetworkReply* reply) {
// we aren't waiting for a response any longer
_isWaitingForKeypairResponse = false;
// clear our pending private key
_pendingPrivateKey.clear();
}
void AccountManager::handleKeypairGenerationError() {
@ -961,3 +972,7 @@ void AccountManager::saveLoginStatus(bool isLoggedIn) {
}
}
}
bool AccountManager::hasKeyPair() const {
return _accountInfo.hasPrivateKey();
}

View file

@ -81,6 +81,7 @@ public:
bool needsToRefreshToken();
Q_INVOKABLE bool checkAndSignalForAccessToken();
void setAccessTokenForCurrentAuthURL(const QString& accessToken);
bool hasKeyPair() const;
void requestProfile();
@ -139,6 +140,7 @@ signals:
private slots:
void handleKeypairGenerationError();
void processGeneratedKeypair(QByteArray publicKey, QByteArray privateKey);
void uploadPublicKey();
void publicKeyUploadSucceeded(QNetworkReply* reply);
void publicKeyUploadFailed(QNetworkReply* reply);
void generateNewKeypair(bool isUserKeypair = true, const QUuid& domainID = QUuid());
@ -162,6 +164,7 @@ private:
bool _isWaitingForKeypairResponse { false };
QByteArray _pendingPrivateKey;
QByteArray _pendingPublicKey;
QUuid _sessionID { QUuid::createUuid() };

View file

@ -842,7 +842,8 @@ bool Resource::handleFailedRequest(ResourceRequest::Result result) {
// FALLTHRU
default: {
_attemptsRemaining = 0;
qCDebug(networking) << "Error loading, attempt:" << _attempts << "attemptsRemaining:" << _attemptsRemaining;
QMetaEnum metaEnum = QMetaEnum::fromType<ResourceRequest::Result>();
qCDebug(networking) << "Error loading:" << metaEnum.valueToKey(result) << "resource:" << _url.toString();
auto error = (result == ResourceRequest::Timeout) ? QNetworkReply::TimeoutError
: QNetworkReply::UnknownNetworkError;
emit failed(error);

View file

@ -272,6 +272,7 @@ enum class EntityVersion : PacketVersion {
ParticleShapeTypeDeadlockFix,
PrivateUserData,
TextUnlit,
ShadowBiasAndDistance,
// Add new versions above here
NUM_PACKET_TYPE,

View file

@ -49,9 +49,9 @@ void PhysicalEntitySimulation::addEntityInternal(EntityItemPointer entity) {
assert(entity);
assert(!entity->isDead());
uint8_t region = _space->getRegion(entity->getSpaceIndex());
bool shouldBePhysical = region < workload::Region::R3 && entity->shouldBePhysical();
bool maybeShouldBePhysical = (region < workload::Region::R3 || region == workload::Region::UNKNOWN) && entity->shouldBePhysical();
bool canBeKinematic = region <= workload::Region::R3;
if (shouldBePhysical) {
if (maybeShouldBePhysical) {
EntityMotionState* motionState = static_cast<EntityMotionState*>(entity->getPhysicsInfo());
if (motionState) {
motionState->setRegion(region);
@ -330,6 +330,18 @@ void PhysicalEntitySimulation::buildMotionStatesForEntitiesThatNeedThem() {
continue;
}
uint8_t region = _space->getRegion(entity->getSpaceIndex());
if (region == workload::Region::UNKNOWN) {
// the workload hasn't categorized it yet --> skip for later
++entityItr;
continue;
}
if (region > workload::Region::R2) {
// not in physical zone --> remove from list
entityItr = _entitiesToAddToPhysics.erase(entityItr);
continue;
}
if (entity->isReadyToComputeShape()) {
ShapeRequest shapeRequest(entity);
ShapeRequests::iterator requestItr = _shapeRequests.find(shapeRequest);

View file

@ -214,6 +214,9 @@ public:
virtual StencilMaskMode getStencilMaskMode() const { return StencilMaskMode::NONE; }
using StencilMaskMeshOperator = std::function<void(gpu::Batch&)>;
virtual StencilMaskMeshOperator getStencilMaskMeshOperator() { return nullptr; }
virtual void updateParameters(float visionSqueezeX, float visionSqueezeY, float visionSqueezeTransition,
int visionSqueezePerEye, float visionSqueezeGroundPlaneY,
float visionSqueezeSpotlightSize) {}
signals:
void recommendedFramebufferSizeChanged(const QSize& size);

View file

@ -18,6 +18,7 @@
#include <shaders/Shaders.h>
ProceduralSkybox::ProceduralSkybox(uint64_t created) : graphics::Skybox(), _created(created) {
// FIXME: support forward rendering for procedural skyboxes (needs haze calculation)
_procedural._vertexSource = gpu::Shader::createVertex(shader::graphics::vertex::skybox)->getSource();
_procedural._opaqueFragmentSource = shader::Source::get(shader::procedural::fragment::proceduralSkybox);
// Adjust the pipeline state for background using the stencil test
@ -40,15 +41,15 @@ void ProceduralSkybox::clear() {
Skybox::clear();
}
void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& frustum) const {
void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& frustum, bool forward) const {
if (_procedural.isReady()) {
ProceduralSkybox::render(batch, frustum, (*this));
ProceduralSkybox::render(batch, frustum, (*this), forward);
} else {
Skybox::render(batch, frustum);
Skybox::render(batch, frustum, forward);
}
}
void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const ProceduralSkybox& skybox) {
void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const ProceduralSkybox& skybox, bool forward) {
glm::mat4 projMat;
viewFrustum.evalProjectionMatrix(projMat);

View file

@ -26,8 +26,8 @@ public:
bool empty() override;
void clear() override;
void render(gpu::Batch& batch, const ViewFrustum& frustum) const override;
static void render(gpu::Batch& batch, const ViewFrustum& frustum, const ProceduralSkybox& skybox);
void render(gpu::Batch& batch, const ViewFrustum& frustum, bool forward) const override;
static void render(gpu::Batch& batch, const ViewFrustum& frustum, const ProceduralSkybox& skybox, bool forward);
uint64_t getCreated() const { return _created; }

View file

@ -13,6 +13,8 @@
#include <gpu/Context.h>
#include <graphics/ShaderConstants.h>
std::string BackgroundStage::_stageName { "BACKGROUND_STAGE"};
const BackgroundStage::Index BackgroundStage::INVALID_INDEX { render::indexed_container::INVALID_INDEX };
@ -71,6 +73,8 @@ void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext,
}
}
const auto& hazeFrame = inputs.get2();
if (skybox && !skybox->empty()) {
PerformanceTimer perfTimer("skybox");
auto args = renderContext->args;
@ -91,7 +95,18 @@ void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext,
batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat);
skybox->render(batch, args->getViewFrustum());
// If we're using forward rendering, we need to calculate haze
if (args->_renderMethod == render::Args::RenderMethod::FORWARD) {
const auto& hazeStage = args->_scene->getStage<HazeStage>();
if (hazeStage && hazeFrame->_hazes.size() > 0) {
const auto& hazePointer = hazeStage->getHaze(hazeFrame->_hazes.front());
if (hazePointer) {
batch.setUniformBuffer(graphics::slot::buffer::Buffer::HazeParams, hazePointer->getHazeParametersBuffer());
}
}
}
skybox->render(batch, args->getViewFrustum(), args->_renderMethod == render::Args::RenderMethod::FORWARD);
});
args->_batch = nullptr;
}

View file

@ -16,6 +16,7 @@
#include <unordered_map>
#include <render/IndexedContainer.h>
#include <render/Stage.h>
#include "HazeStage.h"
#include "LightingModel.h"
@ -81,7 +82,7 @@ public:
class DrawBackgroundStage {
public:
using Inputs = render::VaryingSet2<LightingModelPointer, BackgroundStage::FramePointer>;
using Inputs = render::VaryingSet3<LightingModelPointer, BackgroundStage::FramePointer, HazeStage::FramePointer>;
using JobModel = render::Job::ModelI<DrawBackgroundStage, Inputs>;
DrawBackgroundStage() {}

View file

@ -432,7 +432,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
if (hazeStage && hazeFrame->_hazes.size() > 0) {
const auto& hazePointer = hazeStage->getHaze(hazeFrame->_hazes.front());
if (hazePointer) {
batch.setUniformBuffer(ru::Buffer::HazeParams, hazePointer->getHazeParametersBuffer());
batch.setUniformBuffer(graphics::slot::buffer::Buffer::HazeParams, hazePointer->getHazeParametersBuffer());
}
}
@ -655,7 +655,6 @@ void DefaultLightingSetup::run(const RenderContextPointer& renderContext) {
if (!_defaultHaze) {
auto hazeStage = renderContext->_scene->getStage<HazeStage>();
if (hazeStage) {
auto haze = std::make_shared<graphics::Haze>();
_defaultHaze = haze;

View file

@ -78,7 +78,7 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu
batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(outputFramebufferSize, args->_viewport));
batch.setPipeline(_hazePipeline);
batch.setUniformBuffer(ru::Buffer::HazeParams, haze->getHazeParametersBuffer());
batch.setUniformBuffer(graphics::slot::buffer::Buffer::HazeParams, haze->getHazeParametersBuffer());
batch.setUniformBuffer(ru::Buffer::DeferredFrameTransform, transformBuffer->getFrameTransformBuffer());
batch.setUniformBuffer(ru::Buffer::LightModel, lightingModel->getParametersBuffer());

View file

@ -1,247 +0,0 @@
<!
// ForwardGlobalLight.slh
// libraries/render-utils/src
//
// Created by Gabriel Calero & Cristian Duarte on 4/7/17.
// 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
!>
<@if not DEFERRED_GLOBAL_LIGHT_SLH@>
<@def DEFERRED_GLOBAL_LIGHT_SLH@>
<@include graphics/Light.slh@>
<@include LightingModel.slh@>
<$declareLightBuffer()$>
<$declareLightAmbientBuffer()$>
<@include LightAmbient.slh@>
<@include LightDirectional.slh@>
<@func prepareGlobalLight(positionES, normalWS)@>
// prepareGlobalLight
// Transform directions to worldspace
vec3 fragNormalWS = vec3(<$normalWS$>);
vec3 fragPositionWS = vec3(invViewMat * vec4(<$positionES$>, 1.0));
vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;
vec3 fragEyeDirWS = normalize(fragEyeVectorWS);
// Get light
Light light = getKeyLight();
LightAmbient lightAmbient = getLightAmbient();
vec3 lightDirection = getLightDirection(light);
vec3 lightIrradiance = getLightIrradiance(light);
vec3 color = vec3(0.0);
<@endfunc@>
<@func declareEvalAmbientGlobalColor()@>
vec3 evalAmbientGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, float roughness) {
<$prepareGlobalLight(position, normal)$>
color += albedo * getLightColor(light) * obscurance * getLightAmbientIntensity(lightAmbient);
return color;
}
<@endfunc@>
<@func declareEvalAmbientSphereGlobalColor(supportScattering)@>
<$declareLightingAmbient(1, _SCRIBE_NULL, _SCRIBE_NULL, $supportScattering$)$>
<$declareLightingDirectional($supportScattering$)$>
<@if supportScattering@>
<$declareDeferredCurvature()$>
<@endif@>
vec3 evalAmbientSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal,
vec3 albedo, vec3 fresnel, float metallic, float roughness
<@if supportScattering@>
, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature
<@endif@> ) {
<$prepareGlobalLight(position, normal)$>
SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);
// Ambient
vec3 ambientDiffuse;
vec3 ambientSpecular;
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance
<@if supportScattering@>
,scattering, midNormalCurvature, lowNormalCurvature
<@endif@> );
color += ambientDiffuse;
color += ambientSpecular;
// Directional
vec3 directionalDiffuse;
vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation
<@if supportScattering@>
,scattering, midNormalCurvature, lowNormalCurvature
<@endif@> );
color += directionalDiffuse;
color += directionalSpecular;
return color;
}
<@endfunc@>
<@func declareEvalSkyboxGlobalColor(supportScattering)@>
<$declareLightingAmbient(_SCRIBE_NULL, 1, _SCRIBE_NULL, $supportScattering$)$>
<$declareLightingDirectional($supportScattering$)$>
<@if supportScattering@>
<$declareDeferredCurvature()$>
<@endif@>
vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal,
vec3 albedo, vec3 fresnel, float metallic, float roughness
<@if supportScattering@>
, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature
<@endif@>
) {
<$prepareGlobalLight(position, normal)$>
SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);
// Ambient
vec3 ambientDiffuse;
vec3 ambientSpecular;
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance
<@if supportScattering@>
,scattering, midNormalCurvature, lowNormalCurvature
<@endif@>
);
color += ambientDiffuse;
color += ambientSpecular;
vec3 directionalDiffuse;
vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation
<@if supportScattering@>
,scattering, midNormalCurvature, lowNormalCurvature
<@endif@>
);
color += directionalDiffuse;
color += directionalSpecular;
// FIXME - temporarily removed until we support it for forward...
// Attenuate the light if haze effect selected
// if ((hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) {
// color = computeHazeColorKeyLightAttenuation(color, lightDirection, fragPositionWS);
// }
return color;
}
<@endfunc@>
<@func declareEvalLightmappedColor()@>
vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 albedo, vec3 lightmap) {
Light light = getKeyLight();
LightAmbient ambient = getLightAmbient();
// Catch normals perpendicular to the projection plane, hence the magic number for the threshold
// It should be just 0, but we have inaccuracy so we overshoot
const float PERPENDICULAR_THRESHOLD = -0.005;
vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); // transform to worldspace
float diffuseDot = dot(fragNormal, -getLightDirection(light));
float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot);
// Reevaluate the shadow attenuation for light facing fragments
float lightAttenuation = (1.0 - facingLight) + facingLight * shadowAttenuation;
// Diffuse light is the lightmap dimmed by shadow
vec3 diffuseLight = lightAttenuation * lightmap;
// Ambient light is the lightmap when in shadow
vec3 ambientLight = (1.0 - lightAttenuation) * lightmap * getLightAmbientIntensity(ambient);
return isLightmapEnabled() * obscurance * albedo * (diffuseLight + ambientLight);
}
<@endfunc@>
<@include Haze.slh@>
<@func declareEvalGlobalLightingAlphaBlended()@>
<$declareLightingAmbient(1, 1, 1)$>
<$declareLightingDirectional()$>
vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) {
<$prepareGlobalLight(position, normal)$>
SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);
color += emissive * isEmissiveEnabled();
// Ambient
vec3 ambientDiffuse;
vec3 ambientSpecular;
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);
color += ambientDiffuse;
// Directional
vec3 directionalDiffuse;
vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);
color += directionalDiffuse;
color += evalSpecularWithOpacity(ambientSpecular + directionalSpecular, opacity);
return color;
}
vec3 evalGlobalLightingAlphaBlendedWithHaze(
mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal,
vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity)
{
<$prepareGlobalLight(position, normal)$>
SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);
color += emissive * isEmissiveEnabled();
// Ambient
vec3 ambientDiffuse;
vec3 ambientSpecular;
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);
color += ambientDiffuse;
// Directional
vec3 directionalDiffuse;
vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);
color += directionalDiffuse;
color += evalSpecularWithOpacity(ambientSpecular + directionalSpecular, opacity);
// Haze
// FIXME - temporarily removed until we support it for forward...
/* if ((hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {
vec4 hazeColor = computeHazeColor(
positionES, // fragment position in eye coordinates
fragPositionWS, // fragment position in world coordinates
invViewMat[3].xyz, // eye position in world coordinates
lightDirection // keylight direction vector
);
color = mix(color.rgb, hazeColor.rgb, hazeColor.a);
}*/
return color;
}
<@endfunc@>
<@endif@>

View file

@ -113,6 +113,7 @@ static const uint SHAPE_NORMALS_OFFSET = offsetof(GeometryCache::ShapeVertex, no
static const uint SHAPE_TEXCOORD0_OFFSET = offsetof(GeometryCache::ShapeVertex, uv);
static const uint SHAPE_TANGENT_OFFSET = offsetof(GeometryCache::ShapeVertex, tangent);
std::map<std::pair<bool, bool>, gpu::PipelinePointer> GeometryCache::_webPipelines;
std::map<std::pair<bool, bool>, gpu::PipelinePointer> GeometryCache::_gridPipelines;
void GeometryCache::computeSimpleHullPointListForShape(const int entityShape, const glm::vec3 &entityExtents, QVector<glm::vec3> &outPointList) {
@ -2018,7 +2019,7 @@ void GeometryCache::useGridPipeline(gpu::Batch& batch, GridBuffer gridBuffer, bo
const float DEPTH_BIAS = 0.001f;
static const std::vector<std::tuple<bool, bool, uint32_t>> keys = {
std::make_tuple(false, false, grid), std::make_tuple(false, true, forward_grid), std::make_tuple(true, false, grid_translucent), std::make_tuple(true, true, forward_grid_translucent)
std::make_tuple(false, false, grid), std::make_tuple(false, true, grid_forward), std::make_tuple(true, false, grid_translucent), std::make_tuple(true, true, grid_translucent_forward)
};
for (auto& key : keys) {
@ -2109,34 +2110,35 @@ inline bool operator==(const SimpleProgramKey& a, const SimpleProgramKey& b) {
return a.getRaw() == b.getRaw();
}
static void buildWebShader(int programId, bool blendEnable,
gpu::ShaderPointer& shaderPointerOut, gpu::PipelinePointer& pipelinePointerOut) {
shaderPointerOut = gpu::Shader::createProgram(programId);
auto state = std::make_shared<gpu::State>();
state->setCullMode(gpu::State::CULL_NONE);
state->setDepthTest(true, true, gpu::LESS_EQUAL);
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);
PrepareStencil::testMaskDrawShapeNoAA(*state);
pipelinePointerOut = gpu::Pipeline::create(shaderPointerOut, state);
void GeometryCache::bindWebBrowserProgram(gpu::Batch& batch, bool transparent, bool forward) {
batch.setPipeline(getWebBrowserProgram(transparent, forward));
}
void GeometryCache::bindWebBrowserProgram(gpu::Batch& batch, bool transparent) {
batch.setPipeline(getWebBrowserProgram(transparent));
}
gpu::PipelinePointer GeometryCache::getWebBrowserProgram(bool transparent, bool forward) {
if (_webPipelines.empty()) {
using namespace shader::render_utils::program;
const int NUM_WEB_PIPELINES = 4;
for (int i = 0; i < NUM_WEB_PIPELINES; ++i) {
bool transparent = i & 1;
bool forward = i & 2;
gpu::PipelinePointer GeometryCache::getWebBrowserProgram(bool transparent) {
static std::once_flag once;
std::call_once(once, [&]() {
// FIXME: need a forward pipeline for this
buildWebShader(shader::render_utils::program::simple_opaque_web_browser, false, _simpleOpaqueWebBrowserShader, _simpleOpaqueWebBrowserPipeline);
buildWebShader(shader::render_utils::program::simple_transparent_web_browser, true, _simpleTransparentWebBrowserShader, _simpleTransparentWebBrowserPipeline);
});
// For any non-opaque or non-deferred pipeline, we use web_browser_forward
auto pipeline = (transparent || forward) ? web_browser_forward : web_browser;
return transparent ? _simpleTransparentWebBrowserPipeline : _simpleOpaqueWebBrowserPipeline;
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
state->setDepthTest(true, true, gpu::LESS_EQUAL);
// FIXME: do we need a testMaskDrawNoAA?
PrepareStencil::testMaskDrawShapeNoAA(*state);
state->setBlendFunction(transparent,
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);
state->setCullMode(gpu::State::CULL_NONE);
_webPipelines[{ transparent, forward }] = gpu::Pipeline::create(gpu::Shader::createProgram(pipeline), state);
}
}
return _webPipelines[{ transparent, forward }];
}
void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool transparent, bool culled, bool unlit, bool depthBiased, bool isAntiAliased, bool forward) {
@ -2164,24 +2166,24 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp
std::call_once(once, [&]() {
using namespace shader::render_utils::program;
_forwardSimpleShader = gpu::Shader::createProgram(forward_simple_textured);
_forwardTransparentShader = gpu::Shader::createProgram(forward_simple_textured_transparent);
_forwardUnlitShader = gpu::Shader::createProgram(forward_simple_textured_unlit);
_forwardSimpleShader = gpu::Shader::createProgram(simple_forward);
_forwardTransparentShader = gpu::Shader::createProgram(simple_translucent_forward);
_forwardUnlitShader = gpu::Shader::createProgram(simple_unlit_forward);
_simpleShader = gpu::Shader::createProgram(simple_textured);
_transparentShader = gpu::Shader::createProgram(simple_transparent_textured);
_unlitShader = gpu::Shader::createProgram(simple_textured_unlit);
_simpleShader = gpu::Shader::createProgram(simple);
_transparentShader = gpu::Shader::createProgram(simple_translucent);
_unlitShader = gpu::Shader::createProgram(simple_unlit);
});
} else {
static std::once_flag once;
std::call_once(once, [&]() {
using namespace shader::render_utils::program;
// FIXME: these aren't right...
_forwardSimpleFadeShader = gpu::Shader::createProgram(forward_simple_textured);
_forwardUnlitFadeShader = gpu::Shader::createProgram(forward_simple_textured_unlit);
// Fading is currently disabled during forward rendering
_forwardSimpleFadeShader = gpu::Shader::createProgram(simple_forward);
_forwardUnlitFadeShader = gpu::Shader::createProgram(simple_unlit_forward);
_simpleFadeShader = gpu::Shader::createProgram(simple_textured_fade);
_unlitFadeShader = gpu::Shader::createProgram(simple_textured_unlit_fade);
_simpleFadeShader = gpu::Shader::createProgram(simple_fade);
_unlitFadeShader = gpu::Shader::createProgram(simple_unlit_fade);
});
}

Some files were not shown because too many files have changed in this diff Show more