mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-13 03:32:31 +02:00
Merged with master
This commit is contained in:
commit
69ace03919
273 changed files with 5264 additions and 3368 deletions
.eslintrc.jsBUILD.mdBUILD_LINUX.mdBUILD_OSX.mdBUILD_WIN.mdCMakeLists.txt
android
assignment-client/src
cmake
compiler.cmakeinit.cmake
externals
glslang
serverless-content
spirv_binaries
spirv_cross
spirv_headers
spirv_tools
macros
AutoScribeShader.cmakeConfigureCCache.cmakeTargetPython.cmakeTargetSPIRV.cmakeTargetSpirvBinaries.cmakeTargetVulkan.cmake
templates
domain-server/resources/web/content/js
interface
resources
controllers
qml/hifi
avatarapp
commerce/marketplaceItemTester
tablet
src
libraries
avatars-renderer
avatars/src
display-plugins/src/display-plugins
entities-renderer/src
RenderableShapeEntityItem.cpppaintStroke.slfpaintStroke_fade.slfpolyvox.slfpolyvox_fade.slftextured_particle.slftextured_particle.slv
entities
fbx/src
gl/src/gl
gpu-gl-common
gpu-gl
gpu-gles
gpu/src/gpu
DrawColor.slfDrawColoredTexture.slfDrawTexcoordRectTransformUnitQuad.slvDrawTexture.slfDrawTexture.slpDrawTextureMirroredX.slfDrawTextureMirroredX.slpDrawTextureOpaque.slfDrawTransformedTexture.slpMipGeneration.slhShader.cppShader.hShaderConstants.hTransform.slh
graphics/src/graphics
|
@ -36,6 +36,7 @@ module.exports = {
|
|||
"GlobalServices": false,
|
||||
"GooglePoly": false,
|
||||
"Graphics": false,
|
||||
"HifiAbout": false,
|
||||
"HMD": false,
|
||||
"LaserPointers": false,
|
||||
"location": true,
|
||||
|
|
1
BUILD.md
1
BUILD.md
|
@ -9,6 +9,7 @@
|
|||
|
||||
- [cmake](https://cmake.org/download/): 3.9
|
||||
- [Qt](https://www.qt.io/download-open-source): 5.10.1
|
||||
- [Python](https://www.python.org/downloads/): 3.6 or higher
|
||||
- [OpenSSL](https://www.openssl.org/): Use the latest available 1.0 version (**NOT** 1.1) of OpenSSL to avoid security vulnerabilities.
|
||||
- [VHACD](https://github.com/virneo/v-hacd)(clone this repository)(Optional)
|
||||
|
||||
|
|
|
@ -40,6 +40,11 @@ Install build tools:
|
|||
sudo apt-get install cmake
|
||||
```
|
||||
|
||||
Install Python 3:
|
||||
```bash
|
||||
sudo apt-get install python3.6
|
||||
```
|
||||
|
||||
|
||||
### Get code and checkout the tag you need
|
||||
|
||||
|
|
|
@ -6,6 +6,10 @@ Please read the [general build guide](BUILD.md) for information on dependencies
|
|||
|
||||
brew install cmake openssl qt
|
||||
|
||||
### Python 3
|
||||
|
||||
Download an install Python 3.6.6 or higher from [here](https://www.python.org/downloads/). Execute the `Update Shell Profile.command` script that is provided with the installer.
|
||||
|
||||
### OpenSSL
|
||||
|
||||
Assuming you've installed OpenSSL using the homebrew instructions above, you'll need to set OPENSSL_ROOT_DIR so CMake can find your installations.
|
||||
|
@ -28,7 +32,9 @@ Note that this uses the version from the homebrew formula at the time of this wr
|
|||
|
||||
If Xcode is your editor of choice, you can ask CMake to generate Xcode project files instead of Unix Makefiles.
|
||||
|
||||
cmake .. -GXcode
|
||||
cmake .. -G Xcode
|
||||
|
||||
If `cmake` complains about Python 3 being missing, you may need to update your CMake binary with command `brew upgrade cmake`, or by downloading and running the latest CMake installer, depending on how you originally instaled CMake
|
||||
|
||||
After running cmake, you will have the make files or Xcode project file necessary to build all of the components. Open the hifi.xcodeproj file, choose ALL_BUILD from the Product > Scheme menu (or target drop down), and click Run.
|
||||
|
||||
|
|
10
BUILD_WIN.md
10
BUILD_WIN.md
|
@ -5,11 +5,17 @@ Note: We are now using Visual Studio 2017 and Qt 5.10.1. If you are upgrading fr
|
|||
|
||||
Note: The prerequisites will require about 10 GB of space on your drive. You will also need a system with at least 8GB of main memory.
|
||||
|
||||
### Step 1. Visual Studio 2017
|
||||
### Step 1. Visual Studio 2017 & Python
|
||||
|
||||
If you don’t have Community or Professional edition of Visual Studio 2017, download [Visual Studio Community 2017](https://www.visualstudio.com/downloads/).
|
||||
|
||||
When selecting components, check "Desktop development with C++." Also on the right on the Summary toolbar, check "Windows 8.1 SDK and UCRT SDK" and "VC++ 2015.3 v140 toolset (x86,x64)".
|
||||
When selecting components, check "Desktop development with C++". Also on the right on the Summary toolbar, check "Windows 8.1 SDK and UCRT SDK" and "VC++ 2015.3 v140 toolset (x86,x64)". If you do not already have a python development environment installed, also check "Python Development" in this screen.
|
||||
|
||||
If you already have Visual Studio installed and need to add python, open the "Add or remove programs" control panel and find the "Microsoft Visual Studio Installer". Select it and click "Modify". In the installer, select "Modify" again, then check "Python Development" and allow the installer to apply the changes.
|
||||
|
||||
### Step 1a. Alternate Python
|
||||
|
||||
If you do not wish to use the Python installation bundled with Visual Studio, you can download the installer from [here](https://www.python.org/downloads/). Ensure you get version 3.6.6 or higher.
|
||||
|
||||
### Step 2. Installing CMake
|
||||
|
||||
|
|
|
@ -7,6 +7,11 @@ else()
|
|||
cmake_minimum_required(VERSION 3.2)
|
||||
endif()
|
||||
|
||||
# squelch the Policy CMP0074 warning without requiring an update to cmake 3.12.
|
||||
if ((${CMAKE_MAJOR_VERSION} EQUAL 3 AND ${CMAKE_MINOR_VERSION} GREATER 11) OR ${CMAKE_MAJOR_VERSION} GREATER 3)
|
||||
cmake_policy(SET CMP0074 NEW)
|
||||
endif()
|
||||
|
||||
project(hifi)
|
||||
|
||||
include("cmake/init.cmake")
|
||||
|
|
|
@ -24,7 +24,6 @@ android {
|
|||
'-DANDROID_STL=c++_shared',
|
||||
'-DQT_CMAKE_PREFIX_PATH=' + HIFI_ANDROID_PRECOMPILED + '/qt/lib/cmake',
|
||||
'-DNATIVE_SCRIBE=' + HIFI_ANDROID_PRECOMPILED + '/scribe' + EXEC_SUFFIX,
|
||||
'-DNATIVE_SHREFLECT=' + HIFI_ANDROID_PRECOMPILED + '/shreflect' + EXEC_SUFFIX,
|
||||
'-DHIFI_ANDROID_PRECOMPILED=' + HIFI_ANDROID_PRECOMPILED,
|
||||
'-DRELEASE_NUMBER=' + RELEASE_NUMBER,
|
||||
'-DRELEASE_TYPE=' + RELEASE_TYPE,
|
||||
|
|
|
@ -161,31 +161,19 @@ def packages = [
|
|||
]
|
||||
]
|
||||
|
||||
|
||||
def scribeLocalFile='scribe' + EXEC_SUFFIX
|
||||
def scribeFile='scribe_linux_x86_64'
|
||||
def scribeChecksum='ca4b904f52f4f993c29175ba96798fa6'
|
||||
def scribeVersion='u_iTrJDaE95i2abTPXOpPZckGBIim53G'
|
||||
|
||||
def shreflectLocalFile='shreflect' + EXEC_SUFFIX
|
||||
def shreflectFile='shreflect_linux_x86_64'
|
||||
def shreflectChecksum='d6094a8580066c0b6f4e80b5adfb1d98'
|
||||
def shreflectVersion='jnrpudh6fptIg6T2.Z6fgKP2ultAdKmE'
|
||||
def scribeChecksum='4635c28192724281d2367ce9e94380ab'
|
||||
def scribeVersion='mPAY_N846oZH1tPY1bwChB_hzqkiYyoC'
|
||||
|
||||
if (Os.isFamily(Os.FAMILY_MAC)) {
|
||||
scribeFile = 'scribe_osx_x86_64'
|
||||
scribeChecksum='72db9d32d4e1e50add755570ac5eb749'
|
||||
scribeVersion='DAW0DmnjCRib4MD8x93bgc2Z2MpPojZC'
|
||||
shreflectFile='shreflect_osx_x86_64'
|
||||
shreflectChecksum='d613ef0703c21371fee93fd2e54b964f'
|
||||
shreflectVersion='.rYNzjSFq6WtWDnE5KIKRIAGyJtr__ad'
|
||||
scribeChecksum='1ead61c285d265eba9a5ef91ae3b7c26'
|
||||
scribeVersion='4TAXWdo9fviw60N2wUA8HNyQ9TabjZa3'
|
||||
} else if (Os.isFamily(Os.FAMILY_WINDOWS)) {
|
||||
scribeFile = 'scribe_win32_x86_64.exe'
|
||||
scribeChecksum='678e43d290c90fda670c6fefe038a06d'
|
||||
scribeVersion='PuullrA_bPlO9kXZRt8rLe536X1UI.m7'
|
||||
shreflectFile='shreflect_win32_x86_64.exe'
|
||||
shreflectChecksum='6f4a77b8cceb3f1bbc655132c3665060'
|
||||
shreflectVersion='iIyCyza1nelkbI7ihybF59bBlwrfAC3D'
|
||||
scribeChecksum='9c29a62595daf4844f95f6744d568c15'
|
||||
scribeVersion='DUoxjufeX8ZAIVRBKRczWTuZwT13enTv'
|
||||
}
|
||||
|
||||
def options = [
|
||||
|
@ -461,27 +449,11 @@ task fixScribePermissions(type: Exec, dependsOn: verifyScribe) {
|
|||
commandLine 'chmod', 'a+x', HIFI_ANDROID_PRECOMPILED + '/' + scribeLocalFile
|
||||
}
|
||||
|
||||
task downloadShreflect(type: Download) {
|
||||
src baseUrl + shreflectFile + '?versionId=' + shreflectVersion
|
||||
dest new File(baseFolder, shreflectLocalFile)
|
||||
onlyIfNewer true
|
||||
}
|
||||
|
||||
task verifyShreflect(type: Verify, dependsOn: downloadShreflect) {
|
||||
src new File(baseFolder, shreflectLocalFile);
|
||||
checksum shreflectChecksum
|
||||
}
|
||||
|
||||
task fixShreflectPermissions(type: Exec, dependsOn: verifyShreflect) {
|
||||
commandLine 'chmod', 'a+x', HIFI_ANDROID_PRECOMPILED + '/' + shreflectLocalFile
|
||||
}
|
||||
|
||||
task setupScribe(dependsOn: [verifyScribe, verifyShreflect]) { }
|
||||
task setupScribe(dependsOn: [verifyScribe]) { }
|
||||
|
||||
// On Windows, we don't need to set the executable bit, but on OSX and Unix we do
|
||||
if (!Os.isFamily(Os.FAMILY_WINDOWS)) {
|
||||
setupScribe.dependsOn fixScribePermissions
|
||||
setupScribe.dependsOn fixShreflectPermissions
|
||||
}
|
||||
|
||||
task extractGvrBinaries(dependsOn: extractDependencies) {
|
||||
|
|
|
@ -222,7 +222,8 @@ void Agent::requestScript() {
|
|||
return;
|
||||
}
|
||||
|
||||
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(this, scriptURL);
|
||||
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(
|
||||
this, scriptURL, true, -1, "Agent::requestScript");
|
||||
|
||||
if (!request) {
|
||||
qWarning() << "Could not create ResourceRequest for Agent script at" << scriptURL.toString();
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include <QtCore/QTimer>
|
||||
#include <QUuid>
|
||||
|
||||
#include <ClientTraitsHandler.h>
|
||||
#include <EntityEditPacketSender.h>
|
||||
#include <EntityTree.h>
|
||||
#include <ScriptEngine.h>
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include "AssignmentClientLogging.h"
|
||||
#include "AssignmentFactory.h"
|
||||
#include "ResourceRequestObserver.h"
|
||||
|
||||
const QString ASSIGNMENT_CLIENT_TARGET_NAME = "assignment-client";
|
||||
const long long ASSIGNMENT_REQUEST_INTERVAL_MSECS = 1 * 1000;
|
||||
|
@ -49,6 +50,7 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri
|
|||
DependencyManager::set<tracing::Tracer>();
|
||||
DependencyManager::set<StatTracker>();
|
||||
DependencyManager::set<AccountManager>();
|
||||
DependencyManager::set<ResourceRequestObserver>();
|
||||
|
||||
auto addressManager = DependencyManager::set<AddressManager>();
|
||||
|
||||
|
|
|
@ -6,6 +6,10 @@ if (NOT "${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
|
|||
message( FATAL_ERROR "Only 64 bit builds supported." )
|
||||
endif()
|
||||
|
||||
if (USE_CCACHE OR "$ENV{USE_CCACHE}")
|
||||
configure_ccache()
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
add_definitions(-DNOMINMAX -D_CRT_SECURE_NO_WARNINGS)
|
||||
|
||||
|
|
42
cmake/externals/glslang/CMakeLists.txt
vendored
Normal file
42
cmake/externals/glslang/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
set(EXTERNAL_NAME glslang)
|
||||
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||
|
||||
include(ExternalProject)
|
||||
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL https://github.com/KhronosGroup/glslang/archive/7.8.2853.zip
|
||||
URL_MD5 4f93e3818528176c622c137fba05cbf8
|
||||
CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>-$<CONFIG>
|
||||
LOG_DOWNLOAD 1
|
||||
LOG_CONFIGURE 1
|
||||
LOG_BUILD 1
|
||||
)
|
||||
|
||||
# Hide this external target (for ide users)
|
||||
set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
|
||||
|
||||
# includes
|
||||
ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR)
|
||||
set(SUFFIXED_INSTALL_DIR "${INSTALL_DIR}-$<CONFIG>")
|
||||
|
||||
list(APPEND INCLUDE_DIRS ${SUFFIXED_INSTALL_DIR}/include)
|
||||
#list(APPEND INCLUDE_DIRS ${INSTALL_DIR}/include)
|
||||
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${INCLUDE_DIRS} CACHE PATH "List of glslang include directories")
|
||||
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${${EXTERNAL_NAME_UPPER}_INCLUDE_DIR} CACHE PATH "List of glslang include directories")
|
||||
|
||||
|
||||
set(LIB_DIR ${SUFFIXED_INSTALL_DIR}/lib)
|
||||
list(APPEND LIB_NAMES glslang HLSL OGLCompiler OSDependent SPIRV SPVRemapper)
|
||||
include(SelectLibraryConfigurations)
|
||||
|
||||
foreach(BASE_LIB ${LIB_NAMES})
|
||||
string(TOUPPER ${BASE_LIB} BASE_LIB_UPPER)
|
||||
list(APPEND ${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE "${LIB_DIR}/${BASE_LIB}.lib")
|
||||
list(APPEND ${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG "${LIB_DIR}/${BASE_LIB}d.lib")
|
||||
endforeach()
|
||||
|
||||
select_library_configurations(${EXTERNAL_NAME_UPPER})
|
||||
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY ${${EXTERNAL_NAME_UPPER}_LIBRARY} CACHE FILEPATH "Location of glslang libraries")
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${${EXTERNAL_NAME_UPPER}_LIBRARIES} CACHE FILEPATH "Location of glslang libraries")
|
|
@ -4,8 +4,8 @@ set(EXTERNAL_NAME serverless-content)
|
|||
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC73.zip
|
||||
URL_MD5 0c5edfb63cafb042311d3cf25261fbf2
|
||||
URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC75.zip
|
||||
URL_MD5 b4225d058952e17976ac228330ce8d51
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
|
|
34
cmake/externals/spirv_binaries/CMakeLists.txt
vendored
Normal file
34
cmake/externals/spirv_binaries/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
set(EXTERNAL_NAME spirv_binaries)
|
||||
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||
|
||||
include(ExternalProject)
|
||||
if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
|
||||
set(DOWNLOAD_URL https://public.highfidelity.com/dependencies/vulkan/vulkansdk-win32-1.1.82.1.tar.gz)
|
||||
set(DOWNLOAD_MD5 3a83ef490bce248b1a4d6726a3e5893e)
|
||||
set(BIN_DIR "Bin")
|
||||
elseif (CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
|
||||
set(DOWNLOAD_URL https://public.highfidelity.com/dependencies/vulkan/vulkansdk-macos-1.1.82.1.tar.gz)
|
||||
set(DOWNLOAD_MD5 a57d37275b2c5db023ba8e84a63461ff)
|
||||
set(BIN_DIR "macOS/bin")
|
||||
else ()
|
||||
set(DOWNLOAD_URL https://public.highfidelity.com/dependencies/vulkan/vulkansdk-linux-x86_64-1.1.82.1.tar.gz)
|
||||
set(DOWNLOAD_MD5 5a7c9eeda8cee6b36724da7f7cbe5ec6)
|
||||
set(BIN_DIR "x86_64/bin")
|
||||
endif ()
|
||||
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL ${DOWNLOAD_URL}
|
||||
URL_MD5 ${DOWNLOAD_MD5}
|
||||
BUILD_COMMAND ""
|
||||
CONFIGURE_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
LOG_DOWNLOAD ON
|
||||
)
|
||||
|
||||
# Hide this external target (for ide users)
|
||||
set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
|
||||
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
|
||||
|
||||
set(${EXTERNAL_NAME_UPPER}_DIR "${SOURCE_DIR}/${BIN_DIR}" CACHE FILEPATH "SPIRV binary tools location")
|
||||
|
35
cmake/externals/spirv_cross/CMakeLists.txt
vendored
Normal file
35
cmake/externals/spirv_cross/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
set(EXTERNAL_NAME spirv_cross)
|
||||
|
||||
include(ExternalProject)
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL https://github.com/KhronosGroup/SPIRV-Cross/archive/2018-08-07.zip
|
||||
URL_MD5 11198e4dc6a815ffbdb7a0a56d2d9261
|
||||
CONFIGURE_COMMAND CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>-$<CONFIG> ${EXTRA_CMAKE_FLAGS}
|
||||
LOG_DOWNLOAD 1
|
||||
LOG_CONFIGURE 1
|
||||
LOG_BUILD 1
|
||||
)
|
||||
|
||||
# Hide this external target (for ide users)
|
||||
set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
|
||||
|
||||
ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR)
|
||||
set(SUFFIXED_INSTALL_DIR "${INSTALL_DIR}-$<CONFIG>")
|
||||
|
||||
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||
|
||||
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SUFFIXED_INSTALL_DIR}/include CACHE PATH "List of Draco include directories")
|
||||
|
||||
if (UNIX)
|
||||
set(LIB_PREFIX "lib")
|
||||
set(LIB_EXT "a")
|
||||
elseif (WIN32)
|
||||
set(LIB_EXT "lib")
|
||||
endif ()
|
||||
|
||||
foreach(lib glsl msl cpp hlsl reflect util core)
|
||||
list(APPEND ${EXTERNAL_NAME_UPPER}_LIBRARIES ${SUFFIXED_INSTALL_DIR}/lib/spirv-cross-${lib}.${LIB_EXT})
|
||||
endforeach()
|
||||
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${${EXTERNAL_NAME_UPPER}_LIBRARIES} CACHE FILEPATH "Path to SPIRV-Cross libraries")
|
18
cmake/externals/spirv_headers/CMakeLists.txt
vendored
Normal file
18
cmake/externals/spirv_headers/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
set(EXTERNAL_NAME spirv_headers)
|
||||
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||
|
||||
include(ExternalProject)
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL https://github.com/KhronosGroup/SPIRV-Headers/archive/2c512180ca03b5d4f56283efc85745775b45fdc4.zip
|
||||
URL_MD5 83e652221b5f21d5fdb61c45f5b4d9f9
|
||||
CONFIGURE_COMMAND CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> ${EXTRA_CMAKE_FLAGS}
|
||||
LOG_DOWNLOAD 1
|
||||
LOG_CONFIGURE 1
|
||||
LOG_BUILD 1
|
||||
)
|
||||
|
||||
# Hide this external target (for ide users)
|
||||
set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
|
||||
ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR)
|
||||
set(${EXTERNAL_NAME_UPPER}_ROOT ${INSTALL_DIR} CACHE PATH "List of include directories")
|
33
cmake/externals/spirv_tools/CMakeLists.txt
vendored
Normal file
33
cmake/externals/spirv_tools/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
set(EXTERNAL_NAME spirv_tools)
|
||||
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||
|
||||
include(ExternalProject)
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL https://github.com/KhronosGroup/SPIRV-Tools/archive/v2018.4.zip
|
||||
URL_MD5 7a7c69cf6ff0318910b4bfbdf30bcfc9
|
||||
CONFIGURE_COMMAND CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DSPIRV-Headers_SOURCE_DIR=${SPIRV_HEADERS_ROOT} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>-$<CONFIG> ${EXTRA_CMAKE_FLAGS}
|
||||
LOG_DOWNLOAD 1
|
||||
LOG_CONFIGURE 1
|
||||
LOG_BUILD 1
|
||||
)
|
||||
|
||||
# Hide this external target (for ide users)
|
||||
set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
|
||||
|
||||
ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR)
|
||||
set(SUFFIXED_INSTALL_DIR "${INSTALL_DIR}-$<CONFIG>")
|
||||
|
||||
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SUFFIXED_INSTALL_DIR}/include CACHE PATH "List of SPIRV-Tools include directories")
|
||||
|
||||
if (UNIX)
|
||||
set(LIB_PREFIX "lib")
|
||||
set(LIB_EXT "a")
|
||||
elseif (WIN32)
|
||||
set(LIB_EXT "lib")
|
||||
endif ()
|
||||
|
||||
list(APPEND ${EXTERNAL_NAME_UPPER}_LIBRARIES ${SUFFIXED_INSTALL_DIR}/lib/SPIRV-Tools-opt.${LIB_EXT})
|
||||
list(APPEND ${EXTERNAL_NAME_UPPER}_LIBRARIES ${SUFFIXED_INSTALL_DIR}/lib/SPIRV-Tools-link.${LIB_EXT})
|
||||
list(APPEND ${EXTERNAL_NAME_UPPER}_LIBRARIES ${SUFFIXED_INSTALL_DIR}/lib/SPIRV-Tools.${LIB_EXT})
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${${EXTERNAL_NAME_UPPER}_LIBRARIES} CACHE FILEPATH "Path to SPIRV-Tool libraries")
|
|
@ -10,6 +10,10 @@ if (POLICY CMP0042)
|
|||
cmake_policy(SET CMP0042 NEW)
|
||||
endif ()
|
||||
|
||||
if (POLICY CMP0074)
|
||||
cmake_policy(SET CMP0074 OLD)
|
||||
endif ()
|
||||
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMakeTargets")
|
||||
# Hide automoc folders (for IDEs)
|
||||
|
|
|
@ -8,34 +8,132 @@
|
|||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
|
||||
# FIXME use the built tools
|
||||
|
||||
macro(AUTOSCRIBE_APPEND_QRC)
|
||||
string(CONCAT SHADER_QRC "${SHADER_QRC}" "<file alias=\"${ARGV0}\">${ARGV1}</file>\n")
|
||||
endmacro()
|
||||
|
||||
set(VULKAN_DIR $ENV{VULKAN_SDK})
|
||||
set(GLSLANG_EXEC "${VULKAN_DIR}/Bin/glslangValidator.exe")
|
||||
set(SPIRV_CROSS_EXEC "${VULKAN_DIR}/Bin/spirv-cross.exe")
|
||||
set(SPIRV_OPT_EXEC "${VULKAN_DIR}/Bin/spirv-opt.exe")
|
||||
set(GLSLC_EXEC "${VULKAN_DIR}/Bin/glslc.exe")
|
||||
set(SCRIBE_EXEC "D:/scribe.exe")
|
||||
|
||||
macro(AUTOSCRIBE_PLATFORM_SHADER)
|
||||
set(AUTOSCRIBE_PLATFORM_PATH "${ARGV0}")
|
||||
string(REGEX MATCH "([0-9]+(es)?)(/stereo)?" PLATFORM_PATH_REGEX ${AUTOSCRIBE_PLATFORM_PATH})
|
||||
set(AUTOSCRIBE_DIALECT "${CMAKE_MATCH_1}")
|
||||
if (CMAKE_MATCH_3)
|
||||
set(AUTOSCRIBE_VARIANT "stereo")
|
||||
else()
|
||||
set(AUTOSCRIBE_VARIANT "mono")
|
||||
endif()
|
||||
string(REGEX REPLACE "/" "\\\\" SOURCE_GROUP_PATH ${AUTOSCRIBE_PLATFORM_PATH})
|
||||
set(SOURCE_GROUP_PATH "${SHADER_LIB}\\${SOURCE_GROUP_PATH}")
|
||||
set(AUTOSCRIBE_DIALECT_HEADER "${AUTOSCRIBE_HEADER_DIR}/${AUTOSCRIBE_DIALECT}/header.glsl")
|
||||
set(AUTOSCRIBE_VARIANT_HEADER "${AUTOSCRIBE_HEADER_DIR}/${AUTOSCRIBE_VARIANT}.glsl")
|
||||
|
||||
set(AUTOSCRIBE_OUTPUT_FILE "${SHADERS_DIR}/${SHADER_LIB}/${AUTOSCRIBE_PLATFORM_PATH}/${SHADER_NAME}.${SHADER_TYPE}")
|
||||
AUTOSCRIBE_APPEND_QRC("${SHADER_COUNT}/${AUTOSCRIBE_PLATFORM_PATH}/scribe" "${AUTOSCRIBE_OUTPUT_FILE}")
|
||||
source_group(${SOURCE_GROUP_PATH} FILES ${AUTOSCRIBE_OUTPUT_FILE})
|
||||
set_property(SOURCE ${AUTOSCRIBE_OUTPUT_FILE} PROPERTY SKIP_AUTOMOC ON)
|
||||
list(APPEND SCRIBED_SHADERS ${AUTOSCRIBE_OUTPUT_FILE})
|
||||
|
||||
set(AUTOSCRIBE_SPIRV_FILE "${AUTOSCRIBE_OUTPUT_FILE}.spv")
|
||||
# don't add unoptimized spirv to the QRC
|
||||
#AUTOSCRIBE_APPEND_QRC("${SHADER_COUNT}/${AUTOSCRIBE_PLATFORM_PATH}/spirv_unopt" "${AUTOSCRIBE_SPIRV_FILE}")
|
||||
source_group(${SOURCE_GROUP_PATH} FILES ${AUTOSCRIBE_SPIRV_FILE})
|
||||
set_property(SOURCE ${AUTOSCRIBE_SPIRV_FILE} PROPERTY SKIP_AUTOMOC ON)
|
||||
list(APPEND SPIRV_SHADERS ${AUTOSCRIBE_SPIRV_FILE})
|
||||
|
||||
set(AUTOSCRIBE_SPIRV_OPT_FILE "${AUTOSCRIBE_OUTPUT_FILE}.opt.spv")
|
||||
AUTOSCRIBE_APPEND_QRC("${SHADER_COUNT}/${AUTOSCRIBE_PLATFORM_PATH}/spirv" "${AUTOSCRIBE_SPIRV_OPT_FILE}")
|
||||
source_group(${SOURCE_GROUP_PATH} FILES ${AUTOSCRIBE_SPIRV_OPT_FILE})
|
||||
set_property(SOURCE ${AUTOSCRIBE_SPIRV_OPT_FILE} PROPERTY SKIP_AUTOMOC ON)
|
||||
list(APPEND SPIRV_SHADERS ${AUTOSCRIBE_SPIRV_OPT_FILE})
|
||||
|
||||
set(AUTOSCRIBE_SPIRV_GLSL_FILE "${AUTOSCRIBE_OUTPUT_FILE}.glsl")
|
||||
AUTOSCRIBE_APPEND_QRC("${SHADER_COUNT}/${AUTOSCRIBE_PLATFORM_PATH}/glsl" "${AUTOSCRIBE_SPIRV_GLSL_FILE}")
|
||||
source_group(${SOURCE_GROUP_PATH} FILES ${AUTOSCRIBE_SPIRV_GLSL_FILE})
|
||||
set_property(SOURCE ${AUTOSCRIBE_SPIRV_GLSL_FILE} PROPERTY SKIP_AUTOMOC ON)
|
||||
list(APPEND SPIRV_SHADERS ${AUTOSCRIBE_SPIRV_GLSL_FILE})
|
||||
|
||||
set(AUTOSCRIBE_SPIRV_JSON_FILE "${AUTOSCRIBE_OUTPUT_FILE}.json")
|
||||
AUTOSCRIBE_APPEND_QRC("${SHADER_COUNT}/${AUTOSCRIBE_PLATFORM_PATH}/json" "${AUTOSCRIBE_SPIRV_JSON_FILE}")
|
||||
source_group(${SOURCE_GROUP_PATH} FILES ${AUTOSCRIBE_SPIRV_JSON_FILE})
|
||||
set_property(SOURCE ${AUTOSCRIBE_SPIRV_JSON_FILE} PROPERTY SKIP_AUTOMOC ON)
|
||||
list(APPEND REFLECTED_SHADERS ${AUTOSCRIBE_SPIRV_JSON_FILE})
|
||||
|
||||
unset(SHADER_GEN_LINE)
|
||||
list(APPEND SHADER_GEN_LINE ${AUTOSCRIBE_DIALECT})
|
||||
list(APPEND SHADER_GEN_LINE ${AUTOSCRIBE_VARIANT})
|
||||
file(RELATIVE_PATH TEMP_PATH ${CMAKE_SOURCE_DIR} ${SHADER_FILE})
|
||||
list(APPEND SHADER_GEN_LINE ${TEMP_PATH})
|
||||
file(RELATIVE_PATH TEMP_PATH ${CMAKE_SOURCE_DIR} ${AUTOSCRIBE_OUTPUT_FILE})
|
||||
list(APPEND SHADER_GEN_LINE ${TEMP_PATH})
|
||||
list(APPEND SHADER_GEN_LINE ${AUTOSCRIBE_SHADER_SEEN_LIBS})
|
||||
string(CONCAT AUTOSCRIBE_SHADERGEN_COMMANDS "${AUTOSCRIBE_SHADERGEN_COMMANDS}" "${SHADER_GEN_LINE}\n")
|
||||
|
||||
# # FIXME need better mechanism for determining the include files
|
||||
# add_custom_command(
|
||||
# OUTPUT ${AUTOSCRIBE_OUTPUT_FILE}
|
||||
# COMMAND ${SCRIBE_COMMAND} ${SHADER_FILE} ${SCRIBE_ARGS} -o ${AUTOSCRIBE_OUTPUT_FILE} -h ${AUTOSCRIBE_DIALECT_HEADER} -h ${AUTOSCRIBE_VARIANT_HEADER}
|
||||
# DEPENDS ${SCRIBE_COMMAND} ${SHADER_FILE} ${AUTOSCRIBE_DIALECT_HEADER} ${AUTOSCRIBE_VARIANT_HEADER})
|
||||
|
||||
# # Generate the spirv file
|
||||
# add_custom_command(
|
||||
# OUTPUT ${AUTOSCRIBE_SPIRV_FILE}
|
||||
# COMMAND ${GLSLANG_EXEC} -V110 -o ${AUTOSCRIBE_SPIRV_FILE} ${AUTOSCRIBE_OUTPUT_FILE}
|
||||
# DEPENDS ${AUTOSCRIBE_OUTPUT_FILE} ${GLSLANG_EXEC})
|
||||
|
||||
# # Generate the optimized spirv file
|
||||
# add_custom_command(
|
||||
# OUTPUT ${AUTOSCRIBE_SPIRV_OPT_FILE}
|
||||
# COMMAND ${SPIRV_OPT_EXEC} -O ${AUTOSCRIBE_SPIRV_FILE} -o ${AUTOSCRIBE_SPIRV_OPT_FILE}
|
||||
# DEPENDS ${AUTOSCRIBE_SPIRV_FILE} ${SPIRV_OPT_EXEC})
|
||||
|
||||
# # Generate the optimized GLSL file
|
||||
# add_custom_command(
|
||||
# OUTPUT ${AUTOSCRIBE_SPIRV_GLSL_FILE}
|
||||
# COMMAND ${SPIRV_CROSS_EXEC} ${SPIRV_CROSS_ARGS} ${AUTOSCRIBE_SPIRV_OPT_FILE} --output ${AUTOSCRIBE_SPIRV_GLSL_FILE}
|
||||
# DEPENDS ${AUTOSCRIBE_SPIRV_OPT_FILE} ${SPIRV_CROSS_EXEC})
|
||||
|
||||
# # Generate the optimized spirv file
|
||||
# add_custom_command(
|
||||
# OUTPUT ${AUTOSCRIBE_SPIRV_JSON_FILE}
|
||||
# COMMAND ${SPIRV_CROSS_EXEC} --reflect json ${AUTOSCRIBE_SPIRV_OPT_FILE} --output ${AUTOSCRIBE_SPIRV_JSON_FILE}
|
||||
# DEPENDS ${AUTOSCRIBE_SPIRV_OPT_FILE} ${SPIRV_CROSS_EXEC})
|
||||
endmacro()
|
||||
|
||||
macro(AUTOSCRIBE_SHADER)
|
||||
#
|
||||
# Set the include paths
|
||||
#
|
||||
# FIXME base the include paths off of output from the scribe tool,
|
||||
# instead of treating every previously seen shader as a possible header
|
||||
unset(SHADER_INCLUDE_FILES)
|
||||
# Grab include files
|
||||
foreach(includeFile ${ARGN})
|
||||
list(APPEND SHADER_INCLUDE_FILES ${includeFile})
|
||||
endforeach()
|
||||
|
||||
foreach(SHADER_INCLUDE ${SHADER_INCLUDE_FILES})
|
||||
get_filename_component(INCLUDE_DIR ${SHADER_INCLUDE} PATH)
|
||||
list(APPEND SHADER_INCLUDES_PATHS ${INCLUDE_DIR})
|
||||
endforeach()
|
||||
|
||||
list(REMOVE_DUPLICATES SHADER_INCLUDES_PATHS)
|
||||
#Extract the unique include shader paths
|
||||
set(INCLUDES ${HIFI_LIBRARIES_SHADER_INCLUDE_FILES})
|
||||
foreach(EXTRA_SHADER_INCLUDE ${INCLUDES})
|
||||
list(APPEND SHADER_INCLUDES_PATHS ${EXTRA_SHADER_INCLUDE})
|
||||
endforeach()
|
||||
|
||||
list(REMOVE_DUPLICATES SHADER_INCLUDES_PATHS)
|
||||
#message(ready for includes ${SHADER_INCLUDES_PATHS})
|
||||
|
||||
# make the scribe include arguments
|
||||
set(SCRIBE_INCLUDES)
|
||||
unset(SCRIBE_INCLUDES)
|
||||
foreach(INCLUDE_PATH ${SHADER_INCLUDES_PATHS})
|
||||
set(SCRIBE_INCLUDES ${SCRIBE_INCLUDES} -I ${INCLUDE_PATH}/)
|
||||
endforeach()
|
||||
|
||||
#
|
||||
# Figure out the various output names
|
||||
#
|
||||
# Define the final name of the generated shader file
|
||||
get_filename_component(SHADER_NAME ${SHADER_FILE} NAME_WE)
|
||||
get_filename_component(SHADER_EXT ${SHADER_FILE} EXT)
|
||||
|
@ -46,38 +144,36 @@ macro(AUTOSCRIBE_SHADER)
|
|||
elseif(${SHADER_EXT} STREQUAL .slg)
|
||||
set(SHADER_TYPE geom)
|
||||
endif()
|
||||
file(MAKE_DIRECTORY "${SHADERS_DIR}/${SHADER_LIB}")
|
||||
set(SHADER_TARGET "${SHADERS_DIR}/${SHADER_LIB}/${SHADER_NAME}.${SHADER_TYPE}")
|
||||
file(TO_CMAKE_PATH "${SHADER_TARGET}" COMPILED_SHADER)
|
||||
set(REFLECTED_SHADER "${COMPILED_SHADER}.json")
|
||||
|
||||
set(SCRIBE_ARGS -T ${SHADER_TYPE} -D GLPROFILE ${GLPROFILE} ${SCRIBE_INCLUDES} -o ${SHADER_TARGET} ${SHADER_FILE})
|
||||
set(SCRIBE_ARGS -D GLPROFILE ${GLPROFILE} -T ${SHADER_TYPE} ${SCRIBE_INCLUDES} )
|
||||
|
||||
# Generate the frag/vert file
|
||||
add_custom_command(
|
||||
OUTPUT ${SHADER_TARGET}
|
||||
COMMAND ${SCRIBE_COMMAND} ${SCRIBE_ARGS}
|
||||
DEPENDS ${SHADER_FILE} ${SCRIBE_COMMAND} ${SHADER_INCLUDE_FILES})
|
||||
# SHADER_SCRIBED -> the output of scribe
|
||||
set(SHADER_SCRIBED "${SHADERS_DIR}/${SHADER_LIB}/${SHADER_NAME}.${SHADER_TYPE}")
|
||||
|
||||
# Generate the json reflection
|
||||
# FIXME move to spirv-cross for this task after we have spirv compatible shaders
|
||||
add_custom_command(
|
||||
OUTPUT ${REFLECTED_SHADER}
|
||||
COMMAND ${SHREFLECT_COMMAND} ${COMPILED_SHADER}
|
||||
DEPENDS ${SHREFLECT_DEPENDENCY} ${COMPILED_SHADER})
|
||||
# SHADER_NAME_FILE -> a file containing the shader name and extension (useful for debugging and for
|
||||
# determining the type of shader from the filename)
|
||||
set(SHADER_NAME_FILE "${SHADER_SCRIBED}.name")
|
||||
file(TO_CMAKE_PATH "${SHADER_SCRIBED}" SHADER_SCRIBED)
|
||||
file(WRITE "${SHADER_SCRIBED}.name" "${SHADER_NAME}.${SHADER_TYPE}")
|
||||
AUTOSCRIBE_APPEND_QRC("${SHADER_COUNT}/name" "${SHADER_NAME_FILE}")
|
||||
|
||||
#output the generated file name
|
||||
source_group("Compiled/${SHADER_LIB}" FILES ${COMPILED_SHADER})
|
||||
set_property(SOURCE ${COMPILED_SHADER} PROPERTY SKIP_AUTOMOC ON)
|
||||
list(APPEND COMPILED_SHADERS ${COMPILED_SHADER})
|
||||
if (USE_GLES)
|
||||
set(SPIRV_CROSS_ARGS --version 310es)
|
||||
AUTOSCRIBE_PLATFORM_SHADER("310es")
|
||||
AUTOSCRIBE_PLATFORM_SHADER("310es/stereo")
|
||||
else()
|
||||
set(SPIRV_CROSS_ARGS --version 410 --no-420pack-extension)
|
||||
AUTOSCRIBE_PLATFORM_SHADER("410")
|
||||
AUTOSCRIBE_PLATFORM_SHADER("410/stereo")
|
||||
if (NOT APPLE)
|
||||
set(SPIRV_CROSS_ARGS --version 450)
|
||||
AUTOSCRIBE_PLATFORM_SHADER("450")
|
||||
AUTOSCRIBE_PLATFORM_SHADER("450/stereo")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
source_group("Reflected/${SHADER_LIB}" FILES ${REFLECTED_SHADER})
|
||||
list(APPEND REFLECTED_SHADERS ${REFLECTED_SHADER})
|
||||
|
||||
string(CONCAT SHADER_QRC "${SHADER_QRC}" "<file alias=\"${SHADER_COUNT}\">${COMPILED_SHADER}</file>\n")
|
||||
string(CONCAT SHADER_QRC "${SHADER_QRC}" "<file alias=\"${SHADER_COUNT}_reflection\">${REFLECTED_SHADER}</file>\n")
|
||||
string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "${SHADER_NAME} = ${SHADER_COUNT},\n")
|
||||
|
||||
string(CONCAT SHADER_SHADERS_ARRAY "${SHADER_SHADERS_ARRAY}" "${SHADER_COUNT},\n")
|
||||
MATH(EXPR SHADER_COUNT "${SHADER_COUNT}+1")
|
||||
endmacro()
|
||||
|
||||
|
@ -86,6 +182,8 @@ macro(AUTOSCRIBE_SHADER_LIB)
|
|||
message(FATAL_ERROR "AUTOSCRIBE_SHADER_LIB can only be used by the shaders library")
|
||||
endif()
|
||||
|
||||
file(MAKE_DIRECTORY "${SHADERS_DIR}/${SHADER_LIB}")
|
||||
|
||||
list(APPEND HIFI_LIBRARIES_SHADER_INCLUDE_FILES "${CMAKE_SOURCE_DIR}/libraries/${SHADER_LIB}/src")
|
||||
string(REGEX REPLACE "[-]" "_" SHADER_NAMESPACE ${SHADER_LIB})
|
||||
string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "namespace ${SHADER_NAMESPACE} {\n")
|
||||
|
@ -165,66 +263,103 @@ macro(AUTOSCRIBE_SHADER_LIB)
|
|||
|
||||
# Finish the shader enums
|
||||
string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "} // namespace ${SHADER_NAMESPACE}\n")
|
||||
#file(RELATIVE_PATH RELATIVE_LIBRARY_DIR_PATH ${CMAKE_CURRENT_SOURCE_DIR} "${HIFI_LIBRARY_DIR}")
|
||||
#foreach(HIFI_LIBRARY ${ARGN})
|
||||
#list(APPEND HIFI_LIBRARIES_SHADER_INCLUDE_FILES ${HIFI_LIBRARY_DIR}/${HIFI_LIBRARY}/src)
|
||||
#endforeach()
|
||||
#endif()
|
||||
endmacro()
|
||||
|
||||
macro(AUTOSCRIBE_SHADER_LIBS)
|
||||
set(SCRIBE_COMMAND scribe)
|
||||
set(SHREFLECT_COMMAND shreflect)
|
||||
set(SHREFLECT_DEPENDENCY shreflect)
|
||||
|
||||
# Target dependant Custom rule on the SHADER_FILE
|
||||
if (ANDROID)
|
||||
set(GLPROFILE LINUX_GL)
|
||||
set(SCRIBE_COMMAND ${NATIVE_SCRIBE})
|
||||
set(SHREFLECT_COMMAND ${NATIVE_SHREFLECT})
|
||||
unset(SHREFLECT_DEPENDENCY)
|
||||
else()
|
||||
if (APPLE)
|
||||
set(GLPROFILE MAC_GL)
|
||||
elseif(UNIX)
|
||||
set(GLPROFILE LINUX_GL)
|
||||
else()
|
||||
set(GLPROFILE PC_GL)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
message(STATUS "Shader processing start")
|
||||
set(AUTOSCRIBE_HEADER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/headers)
|
||||
# Start the shader IDs
|
||||
set(SHADER_COUNT 1)
|
||||
set(SHADERS_DIR "${CMAKE_CURRENT_BINARY_DIR}/shaders")
|
||||
set(SHADER_ENUMS "")
|
||||
file(MAKE_DIRECTORY ${SHADERS_DIR})
|
||||
set(SHADER_ENUMS "")
|
||||
set(SHADER_COUNT 1)
|
||||
|
||||
#
|
||||
# Scribe generation & program defintiion
|
||||
#
|
||||
foreach(SHADER_LIB ${ARGN})
|
||||
list(APPEND AUTOSCRIBE_SHADER_SEEN_LIBS ${SHADER_LIB})
|
||||
AUTOSCRIBE_SHADER_LIB(${SHADER_LIB})
|
||||
endforeach()
|
||||
|
||||
# Generate the library files
|
||||
configure_file(
|
||||
ShaderEnums.cpp.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/shaders/ShaderEnums.cpp)
|
||||
${CMAKE_CURRENT_BINARY_DIR}/ShaderEnums.cpp)
|
||||
configure_file(
|
||||
ShaderEnums.h.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/shaders/ShaderEnums.h)
|
||||
configure_file(
|
||||
shaders.qrc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/shaders.qrc)
|
||||
${CMAKE_CURRENT_BINARY_DIR}/ShaderEnums.h)
|
||||
|
||||
set(AUTOSCRIBE_SHADER_LIB_SRC "${CMAKE_CURRENT_BINARY_DIR}/shaders/ShaderEnums.h;${CMAKE_CURRENT_BINARY_DIR}/shaders/ShaderEnums.cpp")
|
||||
set(QT_RESOURCES_FILE ${CMAKE_CURRENT_BINARY_DIR}/shaders.qrc)
|
||||
configure_file(shaders.qrc.in ${CMAKE_CURRENT_BINARY_DIR}/shaders.qrc)
|
||||
list(APPEND QT_RESOURCES_FILE ${CMAKE_CURRENT_BINARY_DIR}/shaders.qrc)
|
||||
|
||||
list(APPEND AUTOSCRIBE_SHADER_HEADERS ${AUTOSCRIBE_HEADER_DIR}/mono.glsl ${AUTOSCRIBE_HEADER_DIR}/stereo.glsl)
|
||||
list(APPEND AUTOSCRIBE_SHADER_HEADERS ${AUTOSCRIBE_HEADER_DIR}/450/header.glsl ${AUTOSCRIBE_HEADER_DIR}/410/header.glsl ${AUTOSCRIBE_HEADER_DIR}/310es/header.glsl)
|
||||
source_group("Shader Headers" FILES ${AUTOSCRIBE_HEADER_DIR}/mono.glsl ${AUTOSCRIBE_HEADER_DIR}/stereo.glsl)
|
||||
source_group("Shader Headers\\450" FILES ${AUTOSCRIBE_HEADER_DIR}/450/header.glsl)
|
||||
source_group("Shader Headers\\410" FILES ${AUTOSCRIBE_HEADER_DIR}/410/header.glsl)
|
||||
source_group("Shader Headers\\310es" FILES ${AUTOSCRIBE_HEADER_DIR}/310es/header.glsl)
|
||||
|
||||
list(APPEND AUTOSCRIBE_SHADER_LIB_SRC ${AUTOSCRIBE_SHADER_HEADERS})
|
||||
list(APPEND AUTOSCRIBE_SHADER_LIB_SRC ${CMAKE_CURRENT_BINARY_DIR}/ShaderEnums.h ${CMAKE_CURRENT_BINARY_DIR}/ShaderEnums.cpp)
|
||||
|
||||
# Write the shadergen command list
|
||||
set(AUTOSCRIBE_SHADERGEN_COMMANDS_FILE ${CMAKE_CURRENT_BINARY_DIR}/shadergen.txt)
|
||||
file(WRITE ${AUTOSCRIBE_SHADERGEN_COMMANDS_FILE} "${AUTOSCRIBE_SHADERGEN_COMMANDS}")
|
||||
|
||||
# grab the SPIRV binaries we require
|
||||
# note we don't use the normal ADD_DEPENDENCY_EXTERNAL_PROJECTS macro because only a custom command
|
||||
# depends on these, not any of our build artifacts, so there's no valid target for the add_dependencies
|
||||
# call in ADD_DEPENDENCY_EXTERNAL_PROJECTS to use
|
||||
add_subdirectory(${EXTERNAL_PROJECT_DIR}/spirv_binaries ${EXTERNALS_BINARY_DIR}/spirv_binaries)
|
||||
|
||||
target_python()
|
||||
|
||||
# A custom python script which will generate
|
||||
if (ANDROID)
|
||||
add_custom_command(
|
||||
OUTPUT ${SCRIBED_SHADERS} ${SPIRV_SHADERS} ${REFLECTED_SHADERS}
|
||||
COMMENT "Generating/updating shaders"
|
||||
COMMAND ${HIFI_PYTHON_EXEC} ${CMAKE_SOURCE_DIR}/tools/shadergen.py
|
||||
--commands ${AUTOSCRIBE_SHADERGEN_COMMANDS_FILE}
|
||||
--spirv-binaries ${SPIRV_BINARIES_DIR}
|
||||
--scribe ${NATIVE_SCRIBE}
|
||||
--build-dir ${CMAKE_CURRENT_BINARY_DIR}
|
||||
--source-dir ${CMAKE_SOURCE_DIR}
|
||||
DEPENDS ${AUTOSCRIBE_SHADER_HEADERS} spirv_binaries ${CMAKE_SOURCE_DIR}/tools/shadergen.py ${ALL_SCRIBE_SHADERS})
|
||||
else()
|
||||
add_custom_command(
|
||||
OUTPUT ${SCRIBED_SHADERS} ${SPIRV_SHADERS} ${REFLECTED_SHADERS}
|
||||
COMMENT "Generating/updating shaders"
|
||||
COMMAND ${HIFI_PYTHON_EXEC} ${CMAKE_SOURCE_DIR}/tools/shadergen.py
|
||||
--commands ${AUTOSCRIBE_SHADERGEN_COMMANDS_FILE}
|
||||
--spirv-binaries ${SPIRV_BINARIES_DIR}
|
||||
--scribe $<TARGET_FILE:scribe>
|
||||
--build-dir ${CMAKE_CURRENT_BINARY_DIR}
|
||||
--source-dir ${CMAKE_SOURCE_DIR}
|
||||
DEPENDS ${AUTOSCRIBE_SHADER_HEADERS} scribe spirv_binaries ${CMAKE_SOURCE_DIR}/tools/shadergen.py ${ALL_SCRIBE_SHADERS})
|
||||
endif()
|
||||
|
||||
add_custom_target(shadergen DEPENDS ${SCRIBED_SHADERS} ${SPIRV_SHADERS} ${REFLECTED_SHADERS})
|
||||
set_target_properties(shadergen PROPERTIES FOLDER "Shaders")
|
||||
|
||||
# Custom targets required to force generation of the shaders via scribe
|
||||
add_custom_target(scribe_shaders SOURCES ${ALL_SCRIBE_SHADERS})
|
||||
add_custom_target(compiled_shaders SOURCES ${COMPILED_SHADERS})
|
||||
add_custom_target(reflected_shaders SOURCES ${REFLECTED_SHADERS})
|
||||
add_custom_target(scribe_shaders SOURCES ${ALL_SCRIBE_SHADERS} ${AUTOSCRIBE_SHADER_HEADERS})
|
||||
set_target_properties(scribe_shaders PROPERTIES FOLDER "Shaders")
|
||||
set_target_properties(compiled_shaders PROPERTIES FOLDER "Shaders")
|
||||
|
||||
add_custom_target(scribed_shaders SOURCES ${SCRIBED_SHADERS})
|
||||
set_target_properties(scribed_shaders PROPERTIES FOLDER "Shaders")
|
||||
add_dependencies(scribed_shaders shadergen)
|
||||
|
||||
add_custom_target(spirv_shaders SOURCES ${SPIRV_SHADERS})
|
||||
set_target_properties(spirv_shaders PROPERTIES FOLDER "Shaders")
|
||||
add_dependencies(spirv_shaders shadergen)
|
||||
|
||||
add_custom_target(reflected_shaders SOURCES ${REFLECTED_SHADERS})
|
||||
set_target_properties(reflected_shaders PROPERTIES FOLDER "Shaders")
|
||||
add_dependencies(reflected_shaders shadergen)
|
||||
|
||||
message(STATUS "Shader processing end")
|
||||
endmacro()
|
||||
|
||||
|
||||
|
|
45
cmake/macros/ConfigureCCache.cmake
Normal file
45
cmake/macros/ConfigureCCache.cmake
Normal file
|
@ -0,0 +1,45 @@
|
|||
#
|
||||
# ConfigureCCache.cmake
|
||||
# cmake/macros
|
||||
#
|
||||
# Created by Clement Brisset on 10/10/18.
|
||||
# Copyright 2018 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
|
||||
#
|
||||
|
||||
macro(configure_ccache)
|
||||
find_program(CCACHE_PROGRAM ccache)
|
||||
if(CCACHE_PROGRAM)
|
||||
message(STATUS "Configuring ccache")
|
||||
|
||||
# Set up wrapper scripts
|
||||
set(C_LAUNCHER "${CCACHE_PROGRAM}")
|
||||
set(CXX_LAUNCHER "${CCACHE_PROGRAM}")
|
||||
|
||||
set(LAUNCH_C_IN "${CMAKE_CURRENT_SOURCE_DIR}/cmake/templates/launch-c.in")
|
||||
set(LAUNCH_CXX_IN "${CMAKE_CURRENT_SOURCE_DIR}/cmake/templates/launch-cxx.in")
|
||||
set(LAUNCH_C "${CMAKE_BINARY_DIR}/CMakeFiles/launch-c")
|
||||
set(LAUNCH_CXX "${CMAKE_BINARY_DIR}/CMakeFiles/launch-cxx")
|
||||
|
||||
configure_file(${LAUNCH_C_IN} ${LAUNCH_C})
|
||||
configure_file(${LAUNCH_CXX_IN} ${LAUNCH_CXX})
|
||||
execute_process(COMMAND chmod a+rx ${LAUNCH_C} ${LAUNCH_CXX})
|
||||
|
||||
if(CMAKE_GENERATOR STREQUAL "Xcode")
|
||||
# Set Xcode project attributes to route compilation and linking
|
||||
# through our scripts
|
||||
set(CMAKE_XCODE_ATTRIBUTE_CC ${LAUNCH_C})
|
||||
set(CMAKE_XCODE_ATTRIBUTE_CXX ${LAUNCH_CXX})
|
||||
set(CMAKE_XCODE_ATTRIBUTE_LD ${LAUNCH_C})
|
||||
set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS ${LAUNCH_CXX})
|
||||
else()
|
||||
# Support Unix Makefiles and Ninja
|
||||
set(CMAKE_C_COMPILER_LAUNCHER ${LAUNCH_C})
|
||||
set(CMAKE_CXX_COMPILER_LAUNCHER ${LAUNCH_CXX})
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "Could not find ccache")
|
||||
endif()
|
||||
endmacro()
|
22
cmake/macros/TargetPython.cmake
Normal file
22
cmake/macros/TargetPython.cmake
Normal file
|
@ -0,0 +1,22 @@
|
|||
macro(TARGET_PYTHON)
|
||||
if (NOT HIFI_PYTHON_EXEC)
|
||||
# Find the python interpreter
|
||||
if (CAME_VERSION VERSION_LESS 3.12)
|
||||
# this logic is deprecated in CMake after 3.12
|
||||
# FIXME eventually we should make 3.12 the min cmake verion and just use the Python3 find_package path
|
||||
set(Python_ADDITIONAL_VERSIONS 3)
|
||||
find_package(PythonInterp)
|
||||
set(HIFI_PYTHON_VERSION ${PYTHON_VERSION_STRING})
|
||||
set(HIFI_PYTHON_EXEC ${PYTHON_EXECUTABLE})
|
||||
else()
|
||||
# the new hotness
|
||||
find_package(Python3)
|
||||
set(HIFI_PYTHON_VERSION ${Python3_VERSION})
|
||||
set(HIFI_PYTHON_EXEC ${Python3_EXECUTABLE})
|
||||
endif()
|
||||
|
||||
if ((NOT HIFI_PYTHON_EXEC) OR (HIFI_PYTHON_VERSION VERSION_LESS 3.5))
|
||||
message(FATAL_ERROR "Unable to locate Python interpreter 3.5 or higher")
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
15
cmake/macros/TargetSPIRV.cmake
Normal file
15
cmake/macros/TargetSPIRV.cmake
Normal file
|
@ -0,0 +1,15 @@
|
|||
macro(TARGET_SPIRV)
|
||||
add_dependency_external_projects(spirv_cross)
|
||||
target_link_libraries(${TARGET_NAME} ${SPIRV_CROSS_LIBRARIES})
|
||||
target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${SPIRV_CROSS_INCLUDE_DIRS})
|
||||
|
||||
# spirv-tools requires spirv-headers
|
||||
add_dependency_external_projects(spirv_headers)
|
||||
add_dependency_external_projects(spirv_tools)
|
||||
target_link_libraries(${TARGET_NAME} ${SPIRV_TOOLS_LIBRARIES})
|
||||
target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${SPIRV_TOOLS_INCLUDE_DIRS})
|
||||
|
||||
add_dependency_external_projects(glslang)
|
||||
target_link_libraries(${TARGET_NAME} ${GLSLANG_LIBRARIES})
|
||||
target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${GLSLANG_INCLUDE_DIRS})
|
||||
endmacro()
|
10
cmake/macros/TargetSpirvBinaries.cmake
Normal file
10
cmake/macros/TargetSpirvBinaries.cmake
Normal file
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
# Created by Bradley Austin Davis on 2016/02/16
|
||||
#
|
||||
# Distributed under the Apache License, Version 2.0.
|
||||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
macro(TARGET_SPIRV_BINARIES)
|
||||
add_dependency_external_projects(spirv_binaries)
|
||||
endmacro()
|
||||
|
19
cmake/macros/TargetVulkan.cmake
Normal file
19
cmake/macros/TargetVulkan.cmake
Normal file
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# Created by Bradley Austin Davis on 2016/02/16
|
||||
#
|
||||
# Distributed under the Apache License, Version 2.0.
|
||||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
macro(TARGET_VULKAN)
|
||||
find_package(Vulkan)
|
||||
|
||||
if (Vulkan_FOUND)
|
||||
add_definitions(-DHAVE_VULKAN)
|
||||
target_include_directories(${TARGET_NAME} PRIVATE ${Vulkan_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_NAME} ${Vulkan_LIBRARIES})
|
||||
|
||||
add_dependency_external_projects(glslang)
|
||||
target_include_directories(${TARGET_NAME} PRIVATE ${GLSLANG_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_NAME} ${GLSLANG_LIBRARIES})
|
||||
endif()
|
||||
endmacro()
|
12
cmake/templates/launch-c.in
Normal file
12
cmake/templates/launch-c.in
Normal file
|
@ -0,0 +1,12 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Xcode generator doesn't include the compiler as the
|
||||
# first argument, Ninja and Makefiles do. Handle both cases.
|
||||
if [[ "$1" = "${CMAKE_C_COMPILER}" ]] ; then
|
||||
shift
|
||||
fi
|
||||
|
||||
export CCACHE_CPP2=true
|
||||
export CCACHE_HARDLINK=true
|
||||
export CCACHE_SLOPPINESS=file_macro,time_macros,include_file_mtime,include_file_ctime,file_stat_matches
|
||||
exec "${C_LAUNCHER}" "${CMAKE_C_COMPILER}" "$@"
|
12
cmake/templates/launch-cxx.in
Normal file
12
cmake/templates/launch-cxx.in
Normal file
|
@ -0,0 +1,12 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Xcode generator doesn't include the compiler as the
|
||||
# first argument, Ninja and Makefiles do. Handle both cases.
|
||||
if [[ "$1" = "${CMAKE_CXX_COMPILER}" ]] ; then
|
||||
shift
|
||||
fi
|
||||
|
||||
export CCACHE_CPP2=true
|
||||
export CCACHE_HARDLINK=true
|
||||
export CCACHE_SLOPPINESS=file_macro,time_macros,include_file_mtime,include_file_ctime,file_stat_matches
|
||||
exec "${CXX_LAUNCHER}" "${CMAKE_CXX_COMPILER}" "$@"
|
|
@ -59,6 +59,7 @@ $(document).ready(function(){
|
|||
$.ajax({
|
||||
url: '/content/upload',
|
||||
type: 'POST',
|
||||
timeout: 3600000, // Set timeout to 1h
|
||||
cache: false,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
|
|
|
@ -133,7 +133,7 @@
|
|||
{ "from": "Keyboard.W", "when": "!Keyboard.Control", "to": "Actions.LONGITUDINAL_FORWARD" },
|
||||
{ "from": "Keyboard.S", "when": "!Keyboard.Control", "to": "Actions.LONGITUDINAL_BACKWARD" },
|
||||
{ "from": "Keyboard.Shift", "when": ["!Keyboard.Left", "!Keyboard.Right"], "to": "Actions.SPRINT" },
|
||||
{ "from": "Keyboard.C", "to": "Actions.VERTICAL_DOWN" },
|
||||
{ "from": "Keyboard.C", "when": "!Keyboard.Control", "to": "Actions.VERTICAL_DOWN" },
|
||||
{ "from": "Keyboard.Left", "when": "Keyboard.Shift", "to": "Actions.LATERAL_LEFT" },
|
||||
{ "from": "Keyboard.Right", "when": "Keyboard.Shift", "to": "Actions.LATERAL_RIGHT" },
|
||||
{ "from": "Keyboard.Up", "when": "Application.CameraFirstPerson", "to": "Actions.LONGITUDINAL_FORWARD" },
|
||||
|
|
|
@ -31,7 +31,7 @@ Rectangle {
|
|||
|
||||
scaleSlider.notify = false;
|
||||
scaleSlider.value = Math.round(avatarScale * 10);
|
||||
scaleSlider.notify = true;;
|
||||
scaleSlider.notify = true;
|
||||
|
||||
if (settings.dominantHand === 'left') {
|
||||
leftHandRadioButton.checked = true;
|
||||
|
|
|
@ -0,0 +1,364 @@
|
|||
//
|
||||
// ItemUnderTest
|
||||
// qml/hifi/commerce/marketplaceItemTester
|
||||
//
|
||||
// Load items not in the marketplace for testing purposes
|
||||
//
|
||||
// Created by Kerry Ivan Kurian on 2018-10-18
|
||||
// Copyright 2018 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 QtQuick 2.10
|
||||
import QtQuick.Controls 2.3
|
||||
import Hifi 1.0 as Hifi
|
||||
import "qrc:////qml//styles-uit" as HifiStylesUit
|
||||
import "qrc:////qml//controls-uit" as HifiControlsUit
|
||||
|
||||
Rectangle {
|
||||
id: root;
|
||||
color: hifi.colors.baseGray
|
||||
width: parent.width - 16
|
||||
height: childrenRect.height + itemHeaderContainer.anchors.topMargin + detailsContainer.anchors.topMargin
|
||||
|
||||
property var detailsExpanded: false
|
||||
|
||||
property var actions: {
|
||||
"forward": function(resource, assetType, resourceObjectId){
|
||||
switch(assetType) {
|
||||
case "application":
|
||||
Commerce.installApp(resource, true);
|
||||
break;
|
||||
case "avatar":
|
||||
MyAvatar.useFullAvatarURL(resource);
|
||||
break;
|
||||
case "content set":
|
||||
urlHandler.handleUrl("hifi://localhost/0,0,0");
|
||||
Commerce.replaceContentSet(toUrl(resource), "");
|
||||
break;
|
||||
case "entity":
|
||||
case "wearable":
|
||||
rezEntity(resource, assetType, resourceObjectId);
|
||||
break;
|
||||
default:
|
||||
print("Marketplace item tester unsupported assetType " + assetType);
|
||||
}
|
||||
},
|
||||
"trash": function(resource, assetType){
|
||||
if ("application" === assetType) {
|
||||
Commerce.uninstallApp(resource);
|
||||
}
|
||||
sendToScript({
|
||||
method: "tester_deleteResourceObject",
|
||||
objectId: resourceListModel.get(index).resourceObjectId});
|
||||
resourceListModel.remove(index);
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: itemHeaderContainer
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 8
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 8
|
||||
width: parent.width - 16
|
||||
height: childrenRect.height
|
||||
|
||||
Item {
|
||||
id: itemNameContainer
|
||||
width: parent.width * 0.5
|
||||
height: childrenRect.height
|
||||
|
||||
HifiStylesUit.RalewaySemiBold {
|
||||
id: resourceName
|
||||
height: paintedHeight
|
||||
width: parent.width
|
||||
text: {
|
||||
var match = resource.match(/\/([^/]*)$/);
|
||||
return match ? match[1] : resource;
|
||||
}
|
||||
size: 14
|
||||
color: hifi.colors.white
|
||||
wrapMode: Text.WrapAnywhere
|
||||
}
|
||||
|
||||
HifiStylesUit.RalewayRegular {
|
||||
id: resourceUrl
|
||||
anchors.top: resourceName.bottom;
|
||||
anchors.topMargin: 4;
|
||||
height: paintedHeight
|
||||
width: parent.width
|
||||
text: resource
|
||||
size: 12
|
||||
color: hifi.colors.faintGray;
|
||||
wrapMode: Text.WrapAnywhere
|
||||
}
|
||||
}
|
||||
|
||||
HifiControlsUit.ComboBox {
|
||||
id: comboBox
|
||||
anchors.left: itemNameContainer.right
|
||||
anchors.leftMargin: 4
|
||||
anchors.verticalCenter: itemNameContainer.verticalCenter
|
||||
height: 30
|
||||
width: parent.width * 0.3 - anchors.leftMargin
|
||||
|
||||
model: [
|
||||
"application",
|
||||
"avatar",
|
||||
"content set",
|
||||
"entity",
|
||||
"wearable",
|
||||
"unknown"
|
||||
]
|
||||
|
||||
currentIndex: (("entity or wearable" === assetType) ?
|
||||
model.indexOf("unknown") : model.indexOf(assetType))
|
||||
|
||||
Component.onCompleted: {
|
||||
onCurrentIndexChanged.connect(function() {
|
||||
assetType = model[currentIndex];
|
||||
sendToScript({
|
||||
method: "tester_updateResourceObjectAssetType",
|
||||
objectId: resourceListModel.get(index)["resourceObjectId"],
|
||||
assetType: assetType });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: actionButton
|
||||
property var glyphs: {
|
||||
"application": hifi.glyphs.install,
|
||||
"avatar": hifi.glyphs.avatar,
|
||||
"content set": hifi.glyphs.globe,
|
||||
"entity": hifi.glyphs.wand,
|
||||
"trash": hifi.glyphs.trash,
|
||||
"unknown": hifi.glyphs.circleSlash,
|
||||
"wearable": hifi.glyphs.hat
|
||||
}
|
||||
property int color: hifi.buttons.blue;
|
||||
property int colorScheme: hifi.colorSchemes.dark;
|
||||
anchors.left: comboBox.right
|
||||
anchors.leftMargin: 4
|
||||
anchors.verticalCenter: itemNameContainer.verticalCenter
|
||||
width: parent.width * 0.10 - anchors.leftMargin
|
||||
height: width
|
||||
enabled: comboBox.model[comboBox.currentIndex] !== "unknown"
|
||||
|
||||
onClicked: {
|
||||
if (model.currentlyRecordingResources) {
|
||||
model.currentlyRecordingResources = false;
|
||||
} else {
|
||||
model.resourceAccessEventText = "";
|
||||
model.currentlyRecordingResources = true;
|
||||
root.actions["forward"](resource, comboBox.currentText, resourceObjectId);
|
||||
}
|
||||
sendToScript({
|
||||
method: "tester_updateResourceRecordingStatus",
|
||||
objectId: resourceListModel.get(index).resourceObjectId,
|
||||
status: model.currentlyRecordingResources
|
||||
});
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
radius: 4;
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0.2
|
||||
color: {
|
||||
if (!actionButton.enabled) {
|
||||
hifi.buttons.disabledColorStart[actionButton.colorScheme]
|
||||
} else if (actionButton.pressed) {
|
||||
hifi.buttons.pressedColor[actionButton.color]
|
||||
} else if (actionButton.hovered) {
|
||||
hifi.buttons.hoveredColor[actionButton.color]
|
||||
} else {
|
||||
hifi.buttons.colorStart[actionButton.color]
|
||||
}
|
||||
}
|
||||
}
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: {
|
||||
if (!actionButton.enabled) {
|
||||
hifi.buttons.disabledColorFinish[actionButton.colorScheme]
|
||||
} else if (actionButton.pressed) {
|
||||
hifi.buttons.pressedColor[actionButton.color]
|
||||
} else if (actionButton.hovered) {
|
||||
hifi.buttons.hoveredColor[actionButton.color]
|
||||
} else {
|
||||
hifi.buttons.colorFinish[actionButton.color]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
HifiStylesUit.HiFiGlyphs {
|
||||
id: rezIcon;
|
||||
text: model.currentlyRecordingResources ? hifi.glyphs.scriptStop : actionButton.glyphs[comboBox.model[comboBox.currentIndex]];
|
||||
anchors.fill: parent
|
||||
size: 30;
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
color: enabled ? hifi.buttons.textColor[actionButton.color]
|
||||
: hifi.buttons.disabledTextColor[actionButton.colorScheme]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: trashButton
|
||||
property int color: hifi.buttons.red;
|
||||
property int colorScheme: hifi.colorSchemes.dark;
|
||||
anchors.left: actionButton.right
|
||||
anchors.verticalCenter: itemNameContainer.verticalCenter
|
||||
anchors.leftMargin: 4
|
||||
width: parent.width * 0.10 - anchors.leftMargin
|
||||
height: width
|
||||
|
||||
onClicked: {
|
||||
root.actions["trash"](resource, comboBox.currentText, resourceObjectId);
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
radius: 4;
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0.2
|
||||
color: {
|
||||
if (!trashButton.enabled) {
|
||||
hifi.buttons.disabledColorStart[trashButton.colorScheme]
|
||||
} else if (trashButton.pressed) {
|
||||
hifi.buttons.pressedColor[trashButton.color]
|
||||
} else if (trashButton.hovered) {
|
||||
hifi.buttons.hoveredColor[trashButton.color]
|
||||
} else {
|
||||
hifi.buttons.colorStart[trashButton.color]
|
||||
}
|
||||
}
|
||||
}
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: {
|
||||
if (!trashButton.enabled) {
|
||||
hifi.buttons.disabledColorFinish[trashButton.colorScheme]
|
||||
} else if (trashButton.pressed) {
|
||||
hifi.buttons.pressedColor[trashButton.color]
|
||||
} else if (trashButton.hovered) {
|
||||
hifi.buttons.hoveredColor[trashButton.color]
|
||||
} else {
|
||||
hifi.buttons.colorFinish[trashButton.color]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
HifiStylesUit.HiFiGlyphs {
|
||||
id: trashIcon;
|
||||
text: hifi.glyphs.trash
|
||||
anchors.fill: parent
|
||||
size: 22;
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: enabled ? hifi.buttons.textColor[trashButton.color]
|
||||
: hifi.buttons.disabledTextColor[trashButton.colorScheme]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: detailsContainer
|
||||
|
||||
width: parent.width - 16
|
||||
height: root.detailsExpanded ? 300 : 26
|
||||
anchors.top: itemHeaderContainer.bottom
|
||||
anchors.topMargin: 12
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 8
|
||||
|
||||
HifiStylesUit.HiFiGlyphs {
|
||||
id: detailsToggle
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: -4
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: -2
|
||||
width: 22
|
||||
text: root.detailsExpanded ? hifi.glyphs.minimize : hifi.glyphs.maximize
|
||||
color: hifi.colors.white
|
||||
size: 22
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: root.detailsExpanded = !root.detailsExpanded
|
||||
}
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
id: detailsTextContainer
|
||||
anchors.top: parent.top
|
||||
anchors.left: detailsToggle.right
|
||||
anchors.leftMargin: 4
|
||||
anchors.right: parent.right
|
||||
height: detailsContainer.height - (root.detailsExpanded ? (copyToClipboardButton.height + copyToClipboardButton.anchors.topMargin) : 0)
|
||||
clip: true
|
||||
|
||||
TextArea {
|
||||
id: detailsText
|
||||
readOnly: true
|
||||
color: hifi.colors.white
|
||||
text: {
|
||||
var numUniqueResources = (model.resourceAccessEventText.split("\n").length - 1);
|
||||
if (root.detailsExpanded && numUniqueResources > 0) {
|
||||
return model.resourceAccessEventText
|
||||
} else {
|
||||
return numUniqueResources.toString() + " unique source/resource url pair" + (numUniqueResources === 1 ? "" : "s") + " recorded"
|
||||
}
|
||||
}
|
||||
font: Qt.font({ family: "Courier", pointSize: 8, weight: Font.Normal })
|
||||
wrapMode: TextEdit.NoWrap
|
||||
|
||||
background: Rectangle {
|
||||
anchors.fill: parent;
|
||||
color: hifi.colors.baseGrayShadow;
|
||||
border.width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
if (root.detailsExpanded) {
|
||||
detailsText.selectAll();
|
||||
} else {
|
||||
root.detailsExpanded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HifiControlsUit.Button {
|
||||
id: copyToClipboardButton;
|
||||
visible: root.detailsExpanded
|
||||
color: hifi.buttons.noneBorderlessWhite
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
|
||||
anchors.top: detailsTextContainer.bottom
|
||||
anchors.topMargin: 8
|
||||
anchors.right: parent.right
|
||||
width: 160
|
||||
height: 30
|
||||
text: "Copy to Clipboard"
|
||||
|
||||
onClicked: {
|
||||
Window.copyToClipboard(detailsText.text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,21 +4,19 @@
|
|||
//
|
||||
// Load items not in the marketplace for testing purposes
|
||||
//
|
||||
// Created by Zach Fox on 2018-09-05
|
||||
// Created by Kerry Ivan Kurian on 2018-09-05
|
||||
// Copyright 2018 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 QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import QtQuick.Dialogs 1.0
|
||||
import QtQuick 2.10
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Controls 2.3
|
||||
import Hifi 1.0 as Hifi
|
||||
import "../../../styles-uit" as HifiStylesUit
|
||||
import "../../../controls-uit" as HifiControlsUit
|
||||
import "qrc:////qml//styles-uit" as HifiStylesUit
|
||||
import "qrc:////qml//controls-uit" as HifiControlsUit
|
||||
|
||||
|
||||
|
||||
|
@ -27,33 +25,223 @@ Rectangle {
|
|||
|
||||
property string installedApps
|
||||
property var nextResourceObjectId: 0
|
||||
signal sendToScript(var message)
|
||||
|
||||
HifiStylesUit.HifiConstants { id: hifi }
|
||||
ListModel { id: resourceListModel }
|
||||
|
||||
color: hifi.colors.white
|
||||
color: hifi.colors.darkGray
|
||||
|
||||
AnimatedImage {
|
||||
id: spinner;
|
||||
source: "spinner.gif"
|
||||
width: 74;
|
||||
height: width;
|
||||
anchors.verticalCenter: parent.verticalCenter;
|
||||
anchors.horizontalCenter: parent.horizontalCenter;
|
||||
//
|
||||
// TITLE BAR START
|
||||
//
|
||||
Item {
|
||||
id: titleBarContainer
|
||||
// Size
|
||||
width: root.width
|
||||
height: 50
|
||||
// Anchors
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
|
||||
// Title bar text
|
||||
HifiStylesUit.RalewaySemiBold {
|
||||
id: titleBarText
|
||||
text: "Marketplace Item Tester"
|
||||
// Text size
|
||||
size: 24
|
||||
// Anchors
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 16
|
||||
width: paintedWidth
|
||||
// Style
|
||||
color: hifi.colors.lightGrayText
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHLeft
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
// Separator
|
||||
HifiControlsUit.Separator {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 1
|
||||
}
|
||||
}
|
||||
//
|
||||
// TITLE BAR END
|
||||
//
|
||||
|
||||
Rectangle {
|
||||
id: spinner
|
||||
z: 999
|
||||
anchors.top: titleBarContainer.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: buttonContainer.top
|
||||
color: hifi.colors.darkGray
|
||||
|
||||
AnimatedImage {
|
||||
source: "spinner.gif"
|
||||
width: 74
|
||||
height: width
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: instructionsContainer
|
||||
z: 998
|
||||
color: hifi.colors.darkGray
|
||||
visible: resourceListModel.count === 0 && !spinner.visible
|
||||
anchors.top: titleBarContainer.bottom
|
||||
anchors.topMargin: 20
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 20
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 20
|
||||
anchors.bottom: buttonContainer.top
|
||||
anchors.bottomMargin: 20
|
||||
|
||||
HifiStylesUit.RalewayRegular {
|
||||
text: "Use Marketplace Item Tester to test out your items before submitting them to the Marketplace." +
|
||||
"\n\nUse one of the buttons below to load your item."
|
||||
// Text size
|
||||
size: 20
|
||||
// Anchors
|
||||
anchors.fill: parent
|
||||
// Style
|
||||
color: hifi.colors.lightGrayText
|
||||
wrapMode: Text.Wrap
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: itemList
|
||||
visible: !instructionsContainer.visible
|
||||
anchors.top: titleBarContainer.bottom
|
||||
anchors.topMargin: 20
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: buttonContainer.top
|
||||
anchors.bottomMargin: 20
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
visible: !instructionsContainer.visible
|
||||
policy: ScrollBar.AlwaysOn
|
||||
parent: itemList.parent
|
||||
anchors.top: itemList.top
|
||||
anchors.right: itemList.right
|
||||
anchors.bottom: itemList.bottom
|
||||
width: 16
|
||||
}
|
||||
clip: true
|
||||
model: resourceListModel
|
||||
spacing: 8
|
||||
|
||||
delegate: ItemUnderTest { }
|
||||
}
|
||||
|
||||
Item {
|
||||
id: buttonContainer
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 12
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 12
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 12
|
||||
height: 40
|
||||
|
||||
property string currentAction
|
||||
property var actions: {
|
||||
"Load File": function() {
|
||||
buttonContainer.currentAction = "load file";
|
||||
Window.browseChanged.connect(onResourceSelected);
|
||||
Window.browseAsync("Please select a file (*.app.json *.json *.fst *.json.gz)", "", "Assets (*.app.json *.json *.fst *.json.gz)");
|
||||
},
|
||||
"Load URL": function() {
|
||||
buttonContainer.currentAction = "load url";
|
||||
Window.promptTextChanged.connect(onResourceSelected);
|
||||
Window.promptAsync("Please enter a URL", "");
|
||||
}
|
||||
}
|
||||
|
||||
function onResourceSelected(resource) {
|
||||
// It is possible that we received the present signal
|
||||
// from something other than our browserAsync window.
|
||||
// Alas, there is nothing we can do about that so charge
|
||||
// ahead as though we are sure the present signal is one
|
||||
// we expect.
|
||||
print("!!!! resource selected");
|
||||
switch(currentAction) {
|
||||
case "load file":
|
||||
Window.browseChanged.disconnect(onResourceSelected);
|
||||
break
|
||||
case "load url":
|
||||
Window.promptTextChanged.disconnect(onResourceSelected);
|
||||
break;
|
||||
}
|
||||
if (resource) {
|
||||
print("!!!! building resource object");
|
||||
var resourceObj = buildResourceObj(resource);
|
||||
print("!!!! notifying script of resource object");
|
||||
sendToScript({
|
||||
method: 'tester_newResourceObject',
|
||||
resourceObject: resourceObj
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
HifiControlsUit.Button {
|
||||
enabled: !spinner.visible
|
||||
anchors.right: parent.horizontalCenter
|
||||
anchors.rightMargin: width/4
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: hifi.buttons.blue
|
||||
fontSize: 20
|
||||
text: "Load File"
|
||||
width: parent.width / 3
|
||||
height: parent.height
|
||||
onClicked: buttonContainer.actions[text]()
|
||||
}
|
||||
|
||||
HifiControlsUit.Button {
|
||||
enabled: !spinner.visible
|
||||
anchors.left: parent.horizontalCenter
|
||||
anchors.leftMargin: width/4
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: hifi.buttons.blue
|
||||
fontSize: 20
|
||||
text: "Load URL"
|
||||
width: parent.width / 3
|
||||
height: parent.height
|
||||
onClicked: buttonContainer.actions[text]()
|
||||
}
|
||||
}
|
||||
|
||||
function fromScript(message) {
|
||||
switch (message.method) {
|
||||
case "newResourceObjectInTest":
|
||||
var resourceObject = message.resourceObject;
|
||||
resourceListModel.clear(); // REMOVE THIS once we support specific referrers
|
||||
resourceListModel.append(resourceObject);
|
||||
spinner.visible = false;
|
||||
break;
|
||||
case "nextObjectIdInTest":
|
||||
print("!!!! message from script! " + JSON.stringify(message));
|
||||
nextResourceObjectId = message.id;
|
||||
spinner.visible = false;
|
||||
break;
|
||||
case "resourceRequestEvent":
|
||||
// When we support multiple items under test simultaneously,
|
||||
// we'll have to replace "0" with the correct index.
|
||||
resourceListModel.setProperty(0, "resourceAccessEventText", message.resourceAccessEventText);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,227 +252,26 @@ Rectangle {
|
|||
resource.match(/\.json\.gz$/) ? "content set" :
|
||||
resource.match(/\.json$/) ? "entity or wearable" :
|
||||
"unknown");
|
||||
return { "id": nextResourceObjectId++,
|
||||
// Uncomment this once we support more than one item in test at the same time
|
||||
//nextResourceObjectId++;
|
||||
return { "resourceObjectId": nextResourceObjectId,
|
||||
"resource": resource,
|
||||
"assetType": assetType };
|
||||
}
|
||||
|
||||
function installResourceObj(resourceObj) {
|
||||
if ("application" === resourceObj.assetType) {
|
||||
Commerce.installApp(resourceObj.resource);
|
||||
}
|
||||
}
|
||||
|
||||
function addAllInstalledAppsToList() {
|
||||
var i, apps = Commerce.getInstalledApps().split(","), len = apps.length;
|
||||
for(i = 0; i < len - 1; ++i) {
|
||||
if (i in apps) {
|
||||
resourceListModel.append(buildResourceObj(apps[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function toUrl(resource) {
|
||||
var httpPattern = /^http/i;
|
||||
return httpPattern.test(resource) ? resource : "file:///" + resource;
|
||||
}
|
||||
|
||||
function rezEntity(resource, entityType) {
|
||||
function rezEntity(resource, entityType, resourceObjectId) {
|
||||
print("!!!! tester_rezClicked");
|
||||
sendToScript({
|
||||
method: 'tester_rezClicked',
|
||||
itemHref: toUrl(resource),
|
||||
itemType: entityType});
|
||||
itemType: entityType,
|
||||
itemId: resourceObjectId });
|
||||
}
|
||||
|
||||
ListView {
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: 12
|
||||
anchors.bottomMargin: 40
|
||||
anchors.rightMargin: 12
|
||||
model: resourceListModel
|
||||
spacing: 5
|
||||
interactive: false
|
||||
|
||||
delegate: RowLayout {
|
||||
anchors.left: parent.left
|
||||
width: parent.width
|
||||
spacing: 5
|
||||
|
||||
property var actions: {
|
||||
"forward": function(resource, assetType){
|
||||
switch(assetType) {
|
||||
case "application":
|
||||
Commerce.openApp(resource);
|
||||
break;
|
||||
case "avatar":
|
||||
MyAvatar.useFullAvatarURL(resource);
|
||||
break;
|
||||
case "content set":
|
||||
urlHandler.handleUrl("hifi://localhost/0,0,0");
|
||||
Commerce.replaceContentSet(toUrl(resource), "");
|
||||
break;
|
||||
case "entity":
|
||||
case "wearable":
|
||||
rezEntity(resource, assetType);
|
||||
break;
|
||||
default:
|
||||
print("Marketplace item tester unsupported assetType " + assetType);
|
||||
}
|
||||
},
|
||||
"trash": function(resource, assetType){
|
||||
if ("application" === assetType) {
|
||||
Commerce.uninstallApp(resource);
|
||||
}
|
||||
sendToScript({
|
||||
method: "tester_deleteResourceObject",
|
||||
objectId: resourceListModel.get(index).id});
|
||||
resourceListModel.remove(index);
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
Layout.preferredWidth: root.width * .6
|
||||
spacing: 5
|
||||
Text {
|
||||
text: {
|
||||
var match = resource.match(/\/([^/]*)$/);
|
||||
return match ? match[1] : resource;
|
||||
}
|
||||
font.pointSize: 12
|
||||
horizontalAlignment: Text.AlignBottom
|
||||
}
|
||||
Text {
|
||||
text: resource
|
||||
font.pointSize: 8
|
||||
width: root.width * .6
|
||||
horizontalAlignment: Text.AlignBottom
|
||||
wrapMode: Text.WrapAnywhere
|
||||
}
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
id: comboBox
|
||||
|
||||
Layout.preferredWidth: root.width * .2
|
||||
|
||||
model: [
|
||||
"application",
|
||||
"avatar",
|
||||
"content set",
|
||||
"entity",
|
||||
"wearable",
|
||||
"unknown"
|
||||
]
|
||||
|
||||
currentIndex: (("entity or wearable" === assetType) ?
|
||||
model.indexOf("unknown") : model.indexOf(assetType))
|
||||
|
||||
Component.onCompleted: {
|
||||
onCurrentIndexChanged.connect(function() {
|
||||
assetType = model[currentIndex];
|
||||
sendToScript({
|
||||
method: "tester_updateResourceObjectAssetType",
|
||||
objectId: resourceListModel.get(index)["id"],
|
||||
assetType: assetType });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: [ "forward", "trash" ]
|
||||
|
||||
HifiStylesUit.HiFiGlyphs {
|
||||
property var glyphs: {
|
||||
"application": hifi.glyphs.install,
|
||||
"avatar": hifi.glyphs.avatar,
|
||||
"content set": hifi.glyphs.globe,
|
||||
"entity": hifi.glyphs.wand,
|
||||
"trash": hifi.glyphs.trash,
|
||||
"unknown": hifi.glyphs.circleSlash,
|
||||
"wearable": hifi.glyphs.hat,
|
||||
}
|
||||
text: (("trash" === modelData) ?
|
||||
glyphs.trash :
|
||||
glyphs[comboBox.model[comboBox.currentIndex]])
|
||||
size: ("trash" === modelData) ? 22 : 30
|
||||
color: hifi.colors.black
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
actions[modelData](resource, comboBox.currentText);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
headerPositioning: ListView.OverlayHeader
|
||||
header: HifiStylesUit.RalewayRegular {
|
||||
id: rootHeader
|
||||
text: "Marketplace Item Tester"
|
||||
height: 80
|
||||
width: paintedWidth
|
||||
size: 22
|
||||
color: hifi.colors.black
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 12
|
||||
}
|
||||
|
||||
footerPositioning: ListView.OverlayFooter
|
||||
footer: Row {
|
||||
id: rootActions
|
||||
spacing: 20
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
property string currentAction
|
||||
property var actions: {
|
||||
"Load File": function(){
|
||||
rootActions.currentAction = "load file";
|
||||
Window.browseChanged.connect(onResourceSelected);
|
||||
Window.browseAsync("Please select a file (*.app.json *.json *.fst *.json.gz)", "", "Assets (*.app.json *.json *.fst *.json.gz)");
|
||||
},
|
||||
"Load URL": function(){
|
||||
rootActions.currentAction = "load url";
|
||||
Window.promptTextChanged.connect(onResourceSelected);
|
||||
Window.promptAsync("Please enter a URL", "");
|
||||
}
|
||||
}
|
||||
|
||||
function onResourceSelected(resource) {
|
||||
// It is possible that we received the present signal
|
||||
// from something other than our browserAsync window.
|
||||
// Alas, there is nothing we can do about that so charge
|
||||
// ahead as though we are sure the present signal is one
|
||||
// we expect.
|
||||
switch(currentAction) {
|
||||
case "load file":
|
||||
Window.browseChanged.disconnect(onResourceSelected);
|
||||
break
|
||||
case "load url":
|
||||
Window.promptTextChanged.disconnect(onResourceSelected);
|
||||
break;
|
||||
}
|
||||
if (resource) {
|
||||
var resourceObj = buildResourceObj(resource);
|
||||
installResourceObj(resourceObj);
|
||||
sendToScript({
|
||||
method: 'tester_newResourceObject',
|
||||
resourceObject: resourceObj });
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: [ "Load File", "Load URL" ]
|
||||
HifiControlsUit.Button {
|
||||
color: hifi.buttons.blue
|
||||
fontSize: 20
|
||||
text: modelData
|
||||
width: root.width / 3
|
||||
height: 40
|
||||
onClicked: actions[text]()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
signal sendToScript(var message)
|
||||
}
|
||||
|
|
Binary file not shown.
Before ![]() (image error) Size: 45 KiB After ![]() (image error) Size: 58 KiB ![]() ![]() |
|
@ -116,9 +116,14 @@ Rectangle {
|
|||
Column {
|
||||
id: column2
|
||||
width: 200
|
||||
height: 400
|
||||
height: 600
|
||||
spacing: 10
|
||||
|
||||
CheckBox {
|
||||
id: grabbable
|
||||
text: qsTr("Grabbable")
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
id: dynamic
|
||||
text: qsTr("Dynamic")
|
||||
|
@ -217,9 +222,10 @@ Rectangle {
|
|||
newModelDialog.sendToScript({
|
||||
method: "newModelDialogAdd",
|
||||
params: {
|
||||
textInput: modelURL.text,
|
||||
checkBox: dynamic.checked,
|
||||
comboBox: collisionType.currentIndex
|
||||
url: modelURL.text,
|
||||
dynamic: dynamic.checked,
|
||||
collisionShapeIndex: collisionType.currentIndex,
|
||||
grabbable: grabbable.checked
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -226,6 +226,7 @@
|
|||
#include "commerce/Ledger.h"
|
||||
#include "commerce/Wallet.h"
|
||||
#include "commerce/QmlCommerce.h"
|
||||
#include "ResourceRequestObserver.h"
|
||||
|
||||
#include "webbrowser/WebBrowserSuggestionsEngine.h"
|
||||
#include <DesktopPreviewProvider.h>
|
||||
|
@ -947,6 +948,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
|||
DependencyManager::set<WalletScriptingInterface>();
|
||||
|
||||
DependencyManager::set<FadeEffect>();
|
||||
DependencyManager::set<ResourceRequestObserver>();
|
||||
|
||||
return previousSessionCrashed;
|
||||
}
|
||||
|
@ -3129,6 +3131,7 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) {
|
|||
surfaceContext->setContextProperty("ContextOverlay", DependencyManager::get<ContextOverlayInterface>().data());
|
||||
surfaceContext->setContextProperty("Wallet", DependencyManager::get<WalletScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("HiFiAbout", AboutUtil::getInstance());
|
||||
surfaceContext->setContextProperty("ResourceRequestObserver", DependencyManager::get<ResourceRequestObserver>().data());
|
||||
|
||||
if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
|
||||
surfaceContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get()));
|
||||
|
@ -5022,12 +5025,12 @@ void Application::saveSettings() const {
|
|||
PluginManager::getInstance()->saveSettings();
|
||||
}
|
||||
|
||||
bool Application::importEntities(const QString& urlOrFilename) {
|
||||
bool Application::importEntities(const QString& urlOrFilename, const bool isObservable, const qint64 callerId) {
|
||||
bool success = false;
|
||||
_entityClipboard->withWriteLock([&] {
|
||||
_entityClipboard->eraseAllOctreeElements();
|
||||
|
||||
success = _entityClipboard->readFromURL(urlOrFilename);
|
||||
success = _entityClipboard->readFromURL(urlOrFilename, isObservable, callerId);
|
||||
if (success) {
|
||||
_entityClipboard->reaverageOctreeElements();
|
||||
}
|
||||
|
@ -6811,6 +6814,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe
|
|||
scriptEngine->registerGlobalObject("Wallet", DependencyManager::get<WalletScriptingInterface>().data());
|
||||
scriptEngine->registerGlobalObject("AddressManager", DependencyManager::get<AddressManager>().data());
|
||||
scriptEngine->registerGlobalObject("HifiAbout", AboutUtil::getInstance());
|
||||
scriptEngine->registerGlobalObject("ResourceRequestObserver", DependencyManager::get<ResourceRequestObserver>().data());
|
||||
|
||||
qScriptRegisterMetaType(scriptEngine.data(), OverlayIDtoScriptValue, OverlayIDfromScriptValue);
|
||||
|
||||
|
@ -7197,7 +7201,8 @@ void Application::addAssetToWorldFromURL(QString url) {
|
|||
|
||||
addAssetToWorldInfo(filename, "Downloading model file " + filename + ".");
|
||||
|
||||
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(nullptr, QUrl(url));
|
||||
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(
|
||||
nullptr, QUrl(url), true, -1, "Application::addAssetToWorldFromURL");
|
||||
connect(request, &ResourceRequest::finished, this, &Application::addAssetToWorldFromURLRequestFinished);
|
||||
request->send();
|
||||
}
|
||||
|
|
|
@ -52,7 +52,6 @@
|
|||
#include <RunningMarker.h>
|
||||
|
||||
#include "avatar/MyAvatar.h"
|
||||
#include "BandwidthRecorder.h"
|
||||
#include "FancyCamera.h"
|
||||
#include "ConnectionMonitor.h"
|
||||
#include "CursorManager.h"
|
||||
|
@ -343,7 +342,7 @@ public slots:
|
|||
QVector<EntityItemID> pasteEntities(float x, float y, float z);
|
||||
bool exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs, const glm::vec3* givenOffset = nullptr);
|
||||
bool exportEntities(const QString& filename, float x, float y, float z, float scale);
|
||||
bool importEntities(const QString& url);
|
||||
bool importEntities(const QString& url, const bool isObservable = true, const qint64 callerId = -1);
|
||||
void updateThreadPoolCount() const;
|
||||
void updateSystemTabletMode();
|
||||
void goToErrorDomainURL(QUrl errorDomainURL);
|
||||
|
|
|
@ -53,7 +53,8 @@ void ATPAssetMigrator::loadEntityServerFile() {
|
|||
|
||||
auto migrateResources = [=](QUrl migrationURL, QJsonValueRef jsonValue, bool isModelURL) {
|
||||
auto request =
|
||||
DependencyManager::get<ResourceManager>()->createResourceRequest(this, migrationURL);
|
||||
DependencyManager::get<ResourceManager>()->createResourceRequest(
|
||||
this, migrationURL, true, -1, "ATPAssetMigrator::loadEntityServerFile");
|
||||
|
||||
if (request) {
|
||||
qCDebug(asset_migrator) << "Requesting" << migrationURL << "for ATP asset migration";
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <AccountManager.h>
|
||||
#include <AddressManager.h>
|
||||
#include <AudioClient.h>
|
||||
#include <ClientTraitsHandler.h>
|
||||
#include <display-plugins/DisplayPlugin.h>
|
||||
#include <FSTReader.h>
|
||||
#include <GeometryUtil.h>
|
||||
|
@ -463,10 +464,74 @@ void MyAvatar::reset(bool andRecenter, bool andReload, bool andHead) {
|
|||
}
|
||||
}
|
||||
|
||||
void MyAvatar::updateSitStandState(float newHeightReading, float dt) {
|
||||
const float STANDING_HEIGHT_MULTIPLE = 1.2f;
|
||||
const float SITTING_HEIGHT_MULTIPLE = 0.833f;
|
||||
const float SITTING_TIMEOUT = 4.0f; // 4 seconds
|
||||
const float STANDING_TIMEOUT = 0.3333f; // 1/3 second
|
||||
const float SITTING_UPPER_BOUND = 1.52f;
|
||||
if (!getIsSitStandStateLocked()) {
|
||||
if (!getIsAway() && qApp->isHMDMode()) {
|
||||
if (getIsInSittingState()) {
|
||||
if (newHeightReading > (STANDING_HEIGHT_MULTIPLE * _tippingPoint)) {
|
||||
// if we recenter upwards then no longer in sitting state
|
||||
_sitStandStateTimer += dt;
|
||||
if (_sitStandStateTimer > STANDING_TIMEOUT) {
|
||||
_averageUserHeightSensorSpace = newHeightReading;
|
||||
_tippingPoint = newHeightReading;
|
||||
setIsInSittingState(false);
|
||||
}
|
||||
} else if (newHeightReading < (SITTING_HEIGHT_MULTIPLE * _tippingPoint)) {
|
||||
// if we are mis labelled as sitting but we are standing in the real world this will
|
||||
// make sure that a real sit is still recognized so we won't be stuck in sitting unable to change state
|
||||
_sitStandStateTimer += dt;
|
||||
if (_sitStandStateTimer > SITTING_TIMEOUT) {
|
||||
_averageUserHeightSensorSpace = newHeightReading;
|
||||
_tippingPoint = newHeightReading;
|
||||
// here we stay in sit state but reset the average height
|
||||
setIsInSittingState(true);
|
||||
}
|
||||
} else {
|
||||
// sanity check if average height greater than 5ft they are not sitting(or get off your dangerous barstool please)
|
||||
if (_averageUserHeightSensorSpace > SITTING_UPPER_BOUND) {
|
||||
setIsInSittingState(false);
|
||||
} else {
|
||||
// tipping point is average height when sitting.
|
||||
_tippingPoint = _averageUserHeightSensorSpace;
|
||||
_sitStandStateTimer = 0.0f;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// in the standing state
|
||||
if (newHeightReading < (SITTING_HEIGHT_MULTIPLE * _tippingPoint)) {
|
||||
_sitStandStateTimer += dt;
|
||||
if (_sitStandStateTimer > SITTING_TIMEOUT) {
|
||||
_averageUserHeightSensorSpace = newHeightReading;
|
||||
_tippingPoint = newHeightReading;
|
||||
setIsInSittingState(true);
|
||||
}
|
||||
} else {
|
||||
// use the mode height for the tipping point when we are standing.
|
||||
_tippingPoint = getCurrentStandingHeight();
|
||||
_sitStandStateTimer = 0.0f;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//if you are away then reset the average and set state to standing.
|
||||
_averageUserHeightSensorSpace = _userHeight.get();
|
||||
_tippingPoint = _userHeight.get();
|
||||
setIsInSittingState(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MyAvatar::update(float deltaTime) {
|
||||
// update moving average of HMD facing in xz plane.
|
||||
const float HMD_FACING_TIMESCALE = getRotationRecenterFilterLength();
|
||||
const float PERCENTAGE_WEIGHT_HEAD_VS_SHOULDERS_AZIMUTH = 0.0f; // 100 percent shoulders
|
||||
const float COSINE_THIRTY_DEGREES = 0.866f;
|
||||
const float SQUATTY_TIMEOUT = 30.0f; // 30 seconds
|
||||
const float HEIGHT_FILTER_COEFFICIENT = 0.01f;
|
||||
|
||||
float tau = deltaTime / HMD_FACING_TIMESCALE;
|
||||
setHipToHandController(computeHandAzimuth());
|
||||
|
@ -493,11 +558,36 @@ void MyAvatar::update(float deltaTime) {
|
|||
_smoothOrientationTimer += deltaTime;
|
||||
}
|
||||
|
||||
float newHeightReading = getControllerPoseInAvatarFrame(controller::Action::HEAD).getTranslation().y;
|
||||
int newHeightReadingInCentimeters = glm::floor(newHeightReading * CENTIMETERS_PER_METER);
|
||||
_recentModeReadings.insert(newHeightReadingInCentimeters);
|
||||
setCurrentStandingHeight(computeStandingHeightMode(getControllerPoseInAvatarFrame(controller::Action::HEAD)));
|
||||
setAverageHeadRotation(computeAverageHeadRotation(getControllerPoseInAvatarFrame(controller::Action::HEAD)));
|
||||
controller::Pose newHeightReading = getControllerPoseInSensorFrame(controller::Action::HEAD);
|
||||
if (newHeightReading.isValid()) {
|
||||
int newHeightReadingInCentimeters = glm::floor(newHeightReading.getTranslation().y * CENTIMETERS_PER_METER);
|
||||
_averageUserHeightSensorSpace = lerp(_averageUserHeightSensorSpace, newHeightReading.getTranslation().y, HEIGHT_FILTER_COEFFICIENT);
|
||||
_recentModeReadings.insert(newHeightReadingInCentimeters);
|
||||
setCurrentStandingHeight(computeStandingHeightMode(newHeightReading));
|
||||
setAverageHeadRotation(computeAverageHeadRotation(getControllerPoseInAvatarFrame(controller::Action::HEAD)));
|
||||
}
|
||||
|
||||
// if the spine is straight and the head is below the default position by 5 cm then increment squatty count.
|
||||
const float SQUAT_THRESHOLD = 0.05f;
|
||||
glm::vec3 headDefaultPositionAvatarSpace = getAbsoluteDefaultJointTranslationInObjectFrame(getJointIndex("Head"));
|
||||
glm::quat spine2OrientationAvatarSpace = getAbsoluteJointRotationInObjectFrame(getJointIndex("Spine2"));
|
||||
glm::vec3 upSpine2 = spine2OrientationAvatarSpace * glm::vec3(0.0f, 1.0f, 0.0f);
|
||||
if (glm::length(upSpine2) > 0.0f) {
|
||||
upSpine2 = glm::normalize(upSpine2);
|
||||
}
|
||||
float angleSpine2 = glm::dot(upSpine2, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
if (getControllerPoseInAvatarFrame(controller::Action::HEAD).getTranslation().y < (headDefaultPositionAvatarSpace.y - SQUAT_THRESHOLD) && (angleSpine2 > COSINE_THIRTY_DEGREES)) {
|
||||
_squatTimer += deltaTime;
|
||||
if (_squatTimer > SQUATTY_TIMEOUT) {
|
||||
_squatTimer = 0.0f;
|
||||
_follow._squatDetected = true;
|
||||
}
|
||||
} else {
|
||||
_squatTimer = 0.0f;
|
||||
}
|
||||
|
||||
// put update sit stand state counts here
|
||||
updateSitStandState(newHeightReading.getTranslation().y, deltaTime);
|
||||
|
||||
if (_drawAverageFacingEnabled) {
|
||||
auto sensorHeadPose = getControllerPoseInSensorFrame(controller::Action::HEAD);
|
||||
|
@ -3557,12 +3647,9 @@ glm::vec3 MyAvatar::computeCounterBalance() {
|
|||
glm::vec3 counterBalancedCg = (1.0f / DEFAULT_AVATAR_HIPS_MASS) * counterBalancedForHead;
|
||||
|
||||
// find the height of the hips
|
||||
const float UPPER_LEG_FRACTION = 0.3333f;
|
||||
glm::vec3 xzDiff((cgHeadMass.position.x - counterBalancedCg.x), 0.0f, (cgHeadMass.position.z - counterBalancedCg.z));
|
||||
float headMinusHipXz = glm::length(xzDiff);
|
||||
float headHipDefault = glm::length(tposeHead - tposeHips);
|
||||
float hipFootDefault = tposeHips.y - tposeRightFoot.y;
|
||||
float sitSquatThreshold = tposeHips.y - (UPPER_LEG_FRACTION * hipFootDefault);
|
||||
float hipHeight = 0.0f;
|
||||
if (headHipDefault > headMinusHipXz) {
|
||||
hipHeight = sqrtf((headHipDefault * headHipDefault) - (headMinusHipXz * headMinusHipXz));
|
||||
|
@ -3574,10 +3661,6 @@ glm::vec3 MyAvatar::computeCounterBalance() {
|
|||
if (counterBalancedCg.y > (tposeHips.y + 0.05f)) {
|
||||
// if the height is higher than default hips, clamp to default hips
|
||||
counterBalancedCg.y = tposeHips.y + 0.05f;
|
||||
} else if (counterBalancedCg.y < sitSquatThreshold) {
|
||||
//do a height reset
|
||||
setResetMode(true);
|
||||
_follow.activate(FollowHelper::Vertical);
|
||||
}
|
||||
return counterBalancedCg;
|
||||
}
|
||||
|
@ -3818,6 +3901,18 @@ bool MyAvatar::getIsInWalkingState() const {
|
|||
return _isInWalkingState;
|
||||
}
|
||||
|
||||
bool MyAvatar::getIsInSittingState() const {
|
||||
return _isInSittingState.get();
|
||||
}
|
||||
|
||||
MyAvatar::SitStandModelType MyAvatar::getUserRecenterModel() const {
|
||||
return _userRecenterModel.get();
|
||||
}
|
||||
|
||||
bool MyAvatar::getIsSitStandStateLocked() const {
|
||||
return _lockSitStandState.get();
|
||||
}
|
||||
|
||||
float MyAvatar::getWalkSpeed() const {
|
||||
return _walkSpeed.get() * _walkSpeedScalar;
|
||||
}
|
||||
|
@ -3838,6 +3933,61 @@ void MyAvatar::setIsInWalkingState(bool isWalking) {
|
|||
_isInWalkingState = isWalking;
|
||||
}
|
||||
|
||||
void MyAvatar::setIsInSittingState(bool isSitting) {
|
||||
_sitStandStateTimer = 0.0f;
|
||||
_squatTimer = 0.0f;
|
||||
// on reset height we need the count to be more than one in case the user sits and stands up quickly.
|
||||
_isInSittingState.set(isSitting);
|
||||
setResetMode(true);
|
||||
if (isSitting) {
|
||||
setCenterOfGravityModelEnabled(false);
|
||||
} else {
|
||||
setCenterOfGravityModelEnabled(true);
|
||||
}
|
||||
setSitStandStateChange(true);
|
||||
}
|
||||
|
||||
void MyAvatar::setUserRecenterModel(MyAvatar::SitStandModelType modelName) {
|
||||
|
||||
_userRecenterModel.set(modelName);
|
||||
|
||||
switch (modelName) {
|
||||
case MyAvatar::SitStandModelType::ForceSit:
|
||||
setHMDLeanRecenterEnabled(true);
|
||||
setIsInSittingState(true);
|
||||
setIsSitStandStateLocked(true);
|
||||
break;
|
||||
case MyAvatar::SitStandModelType::ForceStand:
|
||||
setHMDLeanRecenterEnabled(true);
|
||||
setIsInSittingState(false);
|
||||
setIsSitStandStateLocked(true);
|
||||
break;
|
||||
case MyAvatar::SitStandModelType::Auto:
|
||||
default:
|
||||
setHMDLeanRecenterEnabled(true);
|
||||
setIsInSittingState(false);
|
||||
setIsSitStandStateLocked(false);
|
||||
break;
|
||||
case MyAvatar::SitStandModelType::DisableHMDLean:
|
||||
setHMDLeanRecenterEnabled(false);
|
||||
setIsInSittingState(false);
|
||||
setIsSitStandStateLocked(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MyAvatar::setIsSitStandStateLocked(bool isLocked) {
|
||||
_lockSitStandState.set(isLocked);
|
||||
_sitStandStateTimer = 0.0f;
|
||||
_squatTimer = 0.0f;
|
||||
_averageUserHeightSensorSpace = _userHeight.get();
|
||||
_tippingPoint = _userHeight.get();
|
||||
if (!isLocked) {
|
||||
// always start the auto transition mode in standing state.
|
||||
setIsInSittingState(false);
|
||||
}
|
||||
}
|
||||
|
||||
void MyAvatar::setWalkSpeed(float value) {
|
||||
_walkSpeed.set(value);
|
||||
}
|
||||
|
@ -3854,6 +4004,14 @@ float MyAvatar::getSprintSpeed() const {
|
|||
return _sprintSpeed.get();
|
||||
}
|
||||
|
||||
void MyAvatar::setSitStandStateChange(bool stateChanged) {
|
||||
_sitStandStateChange = stateChanged;
|
||||
}
|
||||
|
||||
float MyAvatar::getSitStandStateChange() const {
|
||||
return _sitStandStateChange;
|
||||
}
|
||||
|
||||
QVector<QString> MyAvatar::getScriptUrls() {
|
||||
QVector<QString> scripts = _skeletonModel->isLoaded() ? _skeletonModel->getFBXGeometry().scripts : QVector<QString>();
|
||||
return scripts;
|
||||
|
@ -3997,6 +4155,7 @@ bool MyAvatar::FollowHelper::shouldActivateHorizontal(const MyAvatar& myAvatar,
|
|||
// x axis of currentBodyMatrix in world space.
|
||||
glm::vec3 right = glm::normalize(glm::vec3(currentBodyMatrix[0][0], currentBodyMatrix[1][0], currentBodyMatrix[2][0]));
|
||||
glm::vec3 offset = extractTranslation(desiredBodyMatrix) - extractTranslation(currentBodyMatrix);
|
||||
controller::Pose currentHeadPose = myAvatar.getControllerPoseInAvatarFrame(controller::Action::HEAD);
|
||||
|
||||
float forwardLeanAmount = glm::dot(forward, offset);
|
||||
float lateralLeanAmount = glm::dot(right, offset);
|
||||
|
@ -4005,14 +4164,19 @@ bool MyAvatar::FollowHelper::shouldActivateHorizontal(const MyAvatar& myAvatar,
|
|||
const float MAX_FORWARD_LEAN = 0.15f;
|
||||
const float MAX_BACKWARD_LEAN = 0.1f;
|
||||
|
||||
|
||||
if (forwardLeanAmount > 0 && forwardLeanAmount > MAX_FORWARD_LEAN) {
|
||||
return true;
|
||||
bool stepDetected = false;
|
||||
if (myAvatar.getIsInSittingState()) {
|
||||
if (!withinBaseOfSupport(currentHeadPose)) {
|
||||
stepDetected = true;
|
||||
}
|
||||
} else if (forwardLeanAmount > 0 && forwardLeanAmount > MAX_FORWARD_LEAN) {
|
||||
stepDetected = true;
|
||||
} else if (forwardLeanAmount < 0 && forwardLeanAmount < -MAX_BACKWARD_LEAN) {
|
||||
return true;
|
||||
stepDetected = true;
|
||||
} else {
|
||||
stepDetected = fabs(lateralLeanAmount) > MAX_LATERAL_LEAN;
|
||||
}
|
||||
|
||||
return fabs(lateralLeanAmount) > MAX_LATERAL_LEAN;
|
||||
return stepDetected;
|
||||
}
|
||||
|
||||
bool MyAvatar::FollowHelper::shouldActivateHorizontalCG(MyAvatar& myAvatar) const {
|
||||
|
@ -4021,6 +4185,7 @@ bool MyAvatar::FollowHelper::shouldActivateHorizontalCG(MyAvatar& myAvatar) cons
|
|||
controller::Pose currentHeadPose = myAvatar.getControllerPoseInAvatarFrame(controller::Action::HEAD);
|
||||
controller::Pose currentLeftHandPose = myAvatar.getControllerPoseInAvatarFrame(controller::Action::LEFT_HAND);
|
||||
controller::Pose currentRightHandPose = myAvatar.getControllerPoseInAvatarFrame(controller::Action::RIGHT_HAND);
|
||||
controller::Pose currentHeadSensorPose = myAvatar.getControllerPoseInSensorFrame(controller::Action::HEAD);
|
||||
|
||||
bool stepDetected = false;
|
||||
float myScale = myAvatar.getAvatarScale();
|
||||
|
@ -4030,7 +4195,7 @@ bool MyAvatar::FollowHelper::shouldActivateHorizontalCG(MyAvatar& myAvatar) cons
|
|||
} else {
|
||||
if (!withinBaseOfSupport(currentHeadPose) &&
|
||||
headAngularVelocityBelowThreshold(currentHeadPose) &&
|
||||
isWithinThresholdHeightMode(currentHeadPose, myAvatar.getCurrentStandingHeight(), myScale) &&
|
||||
isWithinThresholdHeightMode(currentHeadSensorPose, myAvatar.getCurrentStandingHeight(), myScale) &&
|
||||
handDirectionMatchesHeadDirection(currentLeftHandPose, currentRightHandPose, currentHeadPose) &&
|
||||
handAngularVelocityBelowThreshold(currentLeftHandPose, currentRightHandPose) &&
|
||||
headVelocityGreaterThanThreshold(currentHeadPose) &&
|
||||
|
@ -4046,6 +4211,7 @@ bool MyAvatar::FollowHelper::shouldActivateHorizontalCG(MyAvatar& myAvatar) cons
|
|||
glm::vec3 currentHeadPosition = currentHeadPose.getTranslation();
|
||||
float anatomicalHeadToHipsDistance = glm::length(defaultHeadPosition - defaultHipsPosition);
|
||||
if (!isActive(Horizontal) &&
|
||||
(!isActive(Vertical)) &&
|
||||
(glm::length(currentHeadPosition - defaultHipsPosition) > (anatomicalHeadToHipsDistance + (DEFAULT_AVATAR_SPINE_STRETCH_LIMIT * anatomicalHeadToHipsDistance)))) {
|
||||
myAvatar.setResetMode(true);
|
||||
stepDetected = true;
|
||||
|
@ -4061,10 +4227,32 @@ bool MyAvatar::FollowHelper::shouldActivateHorizontalCG(MyAvatar& myAvatar) cons
|
|||
bool MyAvatar::FollowHelper::shouldActivateVertical(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const {
|
||||
const float CYLINDER_TOP = 0.1f;
|
||||
const float CYLINDER_BOTTOM = -1.5f;
|
||||
const float SITTING_BOTTOM = -0.02f;
|
||||
|
||||
glm::vec3 offset = extractTranslation(desiredBodyMatrix) - extractTranslation(currentBodyMatrix);
|
||||
bool returnValue = false;
|
||||
|
||||
return (offset.y > CYLINDER_TOP) || (offset.y < CYLINDER_BOTTOM);
|
||||
if (myAvatar.getSitStandStateChange()) {
|
||||
returnValue = true;
|
||||
} else {
|
||||
if (myAvatar.getIsInSittingState()) {
|
||||
if (myAvatar.getIsSitStandStateLocked()) {
|
||||
returnValue = (offset.y > CYLINDER_TOP);
|
||||
}
|
||||
if (offset.y < SITTING_BOTTOM) {
|
||||
// we recenter more easily when in sitting state.
|
||||
returnValue = true;
|
||||
}
|
||||
} else {
|
||||
// in the standing state
|
||||
returnValue = (offset.y > CYLINDER_TOP) || (offset.y < CYLINDER_BOTTOM);
|
||||
// finally check for squats in standing
|
||||
if (_squatDetected) {
|
||||
returnValue = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix,
|
||||
|
@ -4085,9 +4273,10 @@ void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat
|
|||
}
|
||||
}
|
||||
} else {
|
||||
// center of gravity model is not enabled
|
||||
if (!isActive(Horizontal) && (shouldActivateHorizontal(myAvatar, desiredBodyMatrix, currentBodyMatrix) || hasDriveInput)) {
|
||||
activate(Horizontal);
|
||||
if (myAvatar.getEnableStepResetRotation()) {
|
||||
if (myAvatar.getEnableStepResetRotation() && !myAvatar.getIsInSittingState()) {
|
||||
activate(Rotation);
|
||||
myAvatar.setHeadControllerFacingMovingAverage(myAvatar.getHeadControllerFacing());
|
||||
}
|
||||
|
@ -4095,6 +4284,9 @@ void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat
|
|||
}
|
||||
if (!isActive(Vertical) && (shouldActivateVertical(myAvatar, desiredBodyMatrix, currentBodyMatrix) || hasDriveInput)) {
|
||||
activate(Vertical);
|
||||
if (_squatDetected) {
|
||||
_squatDetected = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!isActive(Rotation) && getForceActivateRotation()) {
|
||||
|
@ -4144,7 +4336,7 @@ void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat
|
|||
myAvatar.getCharacterController()->setFollowParameters(followWorldPose, getMaxTimeRemaining());
|
||||
}
|
||||
|
||||
glm::mat4 MyAvatar::FollowHelper::postPhysicsUpdate(const MyAvatar& myAvatar, const glm::mat4& currentBodyMatrix) {
|
||||
glm::mat4 MyAvatar::FollowHelper::postPhysicsUpdate(MyAvatar& myAvatar, const glm::mat4& currentBodyMatrix) {
|
||||
if (isActive()) {
|
||||
float dt = myAvatar.getCharacterController()->getFollowTime();
|
||||
decrementTimeRemaining(dt);
|
||||
|
@ -4161,6 +4353,11 @@ glm::mat4 MyAvatar::FollowHelper::postPhysicsUpdate(const MyAvatar& myAvatar, co
|
|||
|
||||
glm::mat4 newBodyMat = createMatFromQuatAndPos(sensorAngularDisplacement * glmExtractRotation(currentBodyMatrix),
|
||||
sensorLinearDisplacement + extractTranslation(currentBodyMatrix));
|
||||
if (myAvatar.getSitStandStateChange()) {
|
||||
myAvatar.setSitStandStateChange(false);
|
||||
deactivate(Vertical);
|
||||
setTranslation(newBodyMat, extractTranslation(myAvatar.deriveBodyFromHMDSensor()));
|
||||
}
|
||||
return newBodyMat;
|
||||
} else {
|
||||
return currentBodyMatrix;
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include <AvatarConstants.h>
|
||||
#include <avatars-renderer/Avatar.h>
|
||||
#include <avatars-renderer/ScriptAvatar.h>
|
||||
#include <ClientTraitsHandler.h>
|
||||
#include <controllers/Pose.h>
|
||||
#include <controllers/Actions.h>
|
||||
#include <EntityItem.h>
|
||||
|
@ -142,6 +141,8 @@ class MyAvatar : public Avatar {
|
|||
* @property {number} walkSpeed
|
||||
* @property {number} walkBackwardSpeed
|
||||
* @property {number} sprintSpeed
|
||||
* @property {number} isInSittingState
|
||||
* @property {number} userRecenterModel
|
||||
*
|
||||
* @property {Vec3} skeletonOffset - Can be used to apply a translation offset between the avatar's position and the
|
||||
* registration point of the 3D model.
|
||||
|
@ -242,6 +243,9 @@ class MyAvatar : public Avatar {
|
|||
Q_PROPERTY(float walkSpeed READ getWalkSpeed WRITE setWalkSpeed);
|
||||
Q_PROPERTY(float walkBackwardSpeed READ getWalkBackwardSpeed WRITE setWalkBackwardSpeed);
|
||||
Q_PROPERTY(float sprintSpeed READ getSprintSpeed WRITE setSprintSpeed);
|
||||
Q_PROPERTY(bool isInSittingState READ getIsInSittingState WRITE setIsInSittingState);
|
||||
Q_PROPERTY(MyAvatar::SitStandModelType userRecenterModel READ getUserRecenterModel WRITE setUserRecenterModel);
|
||||
Q_PROPERTY(bool isSitStandStateLocked READ getIsSitStandStateLocked WRITE setIsSitStandStateLocked);
|
||||
|
||||
const QString DOMINANT_LEFT_HAND = "left";
|
||||
const QString DOMINANT_RIGHT_HAND = "right";
|
||||
|
@ -262,6 +266,15 @@ public:
|
|||
};
|
||||
Q_ENUM(DriveKeys)
|
||||
|
||||
enum SitStandModelType {
|
||||
ForceSit = 0,
|
||||
ForceStand,
|
||||
Auto,
|
||||
DisableHMDLean,
|
||||
NumSitStandTypes
|
||||
};
|
||||
Q_ENUM(SitStandModelType)
|
||||
|
||||
explicit MyAvatar(QThread* thread);
|
||||
virtual ~MyAvatar();
|
||||
|
||||
|
@ -1121,12 +1134,21 @@ public:
|
|||
|
||||
void setIsInWalkingState(bool isWalking);
|
||||
bool getIsInWalkingState() const;
|
||||
void setIsInSittingState(bool isSitting);
|
||||
bool getIsInSittingState() const;
|
||||
void setUserRecenterModel(MyAvatar::SitStandModelType modelName);
|
||||
MyAvatar::SitStandModelType getUserRecenterModel() const;
|
||||
void setIsSitStandStateLocked(bool isLocked);
|
||||
bool getIsSitStandStateLocked() const;
|
||||
void setWalkSpeed(float value);
|
||||
float getWalkSpeed() const;
|
||||
void setWalkBackwardSpeed(float value);
|
||||
float getWalkBackwardSpeed() const;
|
||||
void setSprintSpeed(float value);
|
||||
float getSprintSpeed() const;
|
||||
void setSitStandStateChange(bool stateChanged);
|
||||
float getSitStandStateChange() const;
|
||||
void updateSitStandState(float newHeightReading, float dt);
|
||||
|
||||
QVector<QString> getScriptUrls();
|
||||
|
||||
|
@ -1532,6 +1554,7 @@ signals:
|
|||
*/
|
||||
void disableHandTouchForIDChanged(const QUuid& entityID, bool disable);
|
||||
|
||||
|
||||
private slots:
|
||||
void leaveDomain();
|
||||
void updateCollisionCapsuleCache();
|
||||
|
@ -1742,7 +1765,7 @@ private:
|
|||
bool shouldActivateHorizontal(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const;
|
||||
bool shouldActivateHorizontalCG(MyAvatar& myAvatar) const;
|
||||
void prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat4& bodySensorMatrix, const glm::mat4& currentBodyMatrix, bool hasDriveInput);
|
||||
glm::mat4 postPhysicsUpdate(const MyAvatar& myAvatar, const glm::mat4& currentBodyMatrix);
|
||||
glm::mat4 postPhysicsUpdate(MyAvatar& myAvatar, const glm::mat4& currentBodyMatrix);
|
||||
bool getForceActivateRotation() const;
|
||||
void setForceActivateRotation(bool val);
|
||||
bool getForceActivateVertical() const;
|
||||
|
@ -1751,6 +1774,7 @@ private:
|
|||
void setForceActivateHorizontal(bool val);
|
||||
bool getToggleHipsFollowing() const;
|
||||
void setToggleHipsFollowing(bool followHead);
|
||||
bool _squatDetected { false };
|
||||
std::atomic<bool> _forceActivateRotation { false };
|
||||
std::atomic<bool> _forceActivateVertical { false };
|
||||
std::atomic<bool> _forceActivateHorizontal { false };
|
||||
|
@ -1820,10 +1844,13 @@ private:
|
|||
std::mutex _pinnedJointsMutex;
|
||||
std::vector<int> _pinnedJoints;
|
||||
|
||||
void updateChildCauterization(SpatiallyNestablePointer object, bool cauterize);
|
||||
|
||||
// height of user in sensor space, when standing erect.
|
||||
ThreadSafeValueCache<float> _userHeight { DEFAULT_AVATAR_HEIGHT };
|
||||
|
||||
void updateChildCauterization(SpatiallyNestablePointer object, bool cauterize);
|
||||
float _averageUserHeightSensorSpace { _userHeight.get() };
|
||||
bool _sitStandStateChange { false };
|
||||
ThreadSafeValueCache<bool> _lockSitStandState { false };
|
||||
|
||||
// max unscaled forward movement speed
|
||||
ThreadSafeValueCache<float> _walkSpeed { DEFAULT_AVATAR_MAX_WALKING_SPEED };
|
||||
|
@ -1831,6 +1858,11 @@ private:
|
|||
ThreadSafeValueCache<float> _sprintSpeed { AVATAR_SPRINT_SPEED_SCALAR };
|
||||
float _walkSpeedScalar { AVATAR_WALK_SPEED_SCALAR };
|
||||
bool _isInWalkingState { false };
|
||||
ThreadSafeValueCache<bool> _isInSittingState { false };
|
||||
ThreadSafeValueCache<MyAvatar::SitStandModelType> _userRecenterModel { MyAvatar::SitStandModelType::Auto };
|
||||
float _sitStandStateTimer { 0.0f };
|
||||
float _squatTimer { 0.0f };
|
||||
float _tippingPoint { _userHeight.get() };
|
||||
|
||||
// load avatar scripts once when rig is ready
|
||||
bool _shouldLoadScripts { false };
|
||||
|
|
|
@ -46,7 +46,7 @@ static AnimPose computeHipsInSensorFrame(MyAvatar* myAvatar, bool isFlying) {
|
|||
}
|
||||
|
||||
glm::mat4 hipsMat;
|
||||
if (myAvatar->getCenterOfGravityModelEnabled() && !isFlying && !(myAvatar->getIsInWalkingState()) && myAvatar->getHMDLeanRecenterEnabled()) {
|
||||
if (myAvatar->getCenterOfGravityModelEnabled() && !isFlying && !(myAvatar->getIsInWalkingState()) && !(myAvatar->getIsInSittingState()) && myAvatar->getHMDLeanRecenterEnabled()) {
|
||||
// then we use center of gravity model
|
||||
hipsMat = myAvatar->deriveBodyUsingCgModel();
|
||||
} else {
|
||||
|
@ -250,6 +250,7 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
bool headExists = _rig.getAbsoluteJointPoseInRigFrame(_rig.indexOfJoint("Head"), currentHeadPose);
|
||||
bool hipsExists = _rig.getAbsoluteJointPoseInRigFrame(_rig.indexOfJoint("Hips"), currentHipsPose);
|
||||
if (spine2Exists && headExists && hipsExists) {
|
||||
|
||||
AnimPose rigSpaceYaw(myAvatar->getSpine2RotationRigSpace());
|
||||
glm::vec3 u, v, w;
|
||||
glm::vec3 fwd = rigSpaceYaw.rot() * glm::vec3(0.0f, 0.0f, 1.0f);
|
||||
|
|
|
@ -315,7 +315,7 @@ QString QmlCommerce::getInstalledApps(const QString& justInstalledAppID) {
|
|||
return installedAppsFromMarketplace;
|
||||
}
|
||||
|
||||
bool QmlCommerce::installApp(const QString& itemHref) {
|
||||
bool QmlCommerce::installApp(const QString& itemHref, const bool& alsoOpenImmediately) {
|
||||
if (!QDir(_appsPath).exists()) {
|
||||
if (!QDir().mkdir(_appsPath)) {
|
||||
qCDebug(commerce) << "Couldn't make _appsPath directory.";
|
||||
|
@ -325,7 +325,8 @@ bool QmlCommerce::installApp(const QString& itemHref) {
|
|||
|
||||
QUrl appHref(itemHref);
|
||||
|
||||
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(this, appHref);
|
||||
auto request =
|
||||
DependencyManager::get<ResourceManager>()->createResourceRequest(this, appHref, true, -1, "QmlCommerce::installApp");
|
||||
|
||||
if (!request) {
|
||||
qCDebug(commerce) << "Couldn't create resource request for app.";
|
||||
|
@ -357,13 +358,22 @@ bool QmlCommerce::installApp(const QString& itemHref) {
|
|||
QJsonObject appFileJsonObject = appFileJsonDocument.object();
|
||||
QString scriptUrl = appFileJsonObject["scriptURL"].toString();
|
||||
|
||||
if ((DependencyManager::get<ScriptEngines>()->loadScript(scriptUrl.trimmed())).isNull()) {
|
||||
qCDebug(commerce) << "Couldn't load script.";
|
||||
return false;
|
||||
// Don't try to re-load (install) a script if it's already running
|
||||
QStringList runningScripts = DependencyManager::get<ScriptEngines>()->getRunningScripts();
|
||||
if (!runningScripts.contains(scriptUrl)) {
|
||||
if ((DependencyManager::get<ScriptEngines>()->loadScript(scriptUrl.trimmed())).isNull()) {
|
||||
qCDebug(commerce) << "Couldn't load script.";
|
||||
return false;
|
||||
}
|
||||
|
||||
QFileInfo appFileInfo(appFile);
|
||||
emit appInstalled(appFileInfo.baseName());
|
||||
}
|
||||
|
||||
if (alsoOpenImmediately) {
|
||||
QmlCommerce::openApp(itemHref);
|
||||
}
|
||||
|
||||
QFileInfo appFileInfo(appFile);
|
||||
emit appInstalled(appFileInfo.baseName());
|
||||
return true;
|
||||
});
|
||||
request->send();
|
||||
|
|
|
@ -88,7 +88,7 @@ protected:
|
|||
Q_INVOKABLE void replaceContentSet(const QString& itemHref, const QString& certificateID);
|
||||
|
||||
Q_INVOKABLE QString getInstalledApps(const QString& justInstalledAppID = "");
|
||||
Q_INVOKABLE bool installApp(const QString& appHref);
|
||||
Q_INVOKABLE bool installApp(const QString& appHref, const bool& alsoOpenImmediately = false);
|
||||
Q_INVOKABLE bool uninstallApp(const QString& appHref);
|
||||
Q_INVOKABLE bool openApp(const QString& appHref);
|
||||
|
||||
|
|
|
@ -91,7 +91,9 @@ void OctreePacketProcessor::processPacket(QSharedPointer<ReceivedMessage> messag
|
|||
return; // bail since piggyback version doesn't match
|
||||
}
|
||||
|
||||
qApp->trackIncomingOctreePacket(*message, sendingNode, wasStatsPacket);
|
||||
if (packetType != PacketType::EntityQueryInitialResultsComplete) {
|
||||
qApp->trackIncomingOctreePacket(*message, sendingNode, wasStatsPacket);
|
||||
}
|
||||
|
||||
// seek back to beginning of packet after tracking
|
||||
message->seek(0);
|
||||
|
|
|
@ -46,11 +46,17 @@ bool ClipboardScriptingInterface::exportEntities(const QString& filename, float
|
|||
return retVal;
|
||||
}
|
||||
|
||||
bool ClipboardScriptingInterface::importEntities(const QString& filename) {
|
||||
bool ClipboardScriptingInterface::importEntities(
|
||||
const QString& filename,
|
||||
const bool isObservable,
|
||||
const qint64 callerId
|
||||
) {
|
||||
bool retVal;
|
||||
BLOCKING_INVOKE_METHOD(qApp, "importEntities",
|
||||
Q_RETURN_ARG(bool, retVal),
|
||||
Q_ARG(const QString&, filename));
|
||||
Q_ARG(const QString&, filename),
|
||||
Q_ARG(const bool, isObservable),
|
||||
Q_ARG(const qint64, callerId));
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,9 +50,11 @@ public:
|
|||
* You can generate a JSON file using {@link Clipboard.exportEntities}.
|
||||
* @function Clipboard.importEntities
|
||||
* @param {string} filename Path and name of file to import.
|
||||
* @param {boolean} does the ResourceRequestObserver observe this request?
|
||||
* @param {number} optional internal id of object causing this import.
|
||||
* @returns {boolean} <code>true</code> if the import was successful, otherwise <code>false</code>.
|
||||
*/
|
||||
Q_INVOKABLE bool importEntities(const QString& filename);
|
||||
Q_INVOKABLE bool importEntities(const QString& filename, const bool isObservable = true, const qint64 callerId = -1);
|
||||
|
||||
/**jsdoc
|
||||
* Export the entities specified to a JSON file.
|
||||
|
|
|
@ -259,6 +259,39 @@ void setupPreferences() {
|
|||
auto preference = new CheckPreference(VR_MOVEMENT, "Show room boundaries while teleporting", getter, setter);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
auto getter = [myAvatar]()->int {
|
||||
switch (myAvatar->getUserRecenterModel()) {
|
||||
case MyAvatar::SitStandModelType::Auto:
|
||||
default:
|
||||
return 0;
|
||||
case MyAvatar::SitStandModelType::ForceSit:
|
||||
return 1;
|
||||
case MyAvatar::SitStandModelType::DisableHMDLean:
|
||||
return 2;
|
||||
}
|
||||
};
|
||||
auto setter = [myAvatar](int value) {
|
||||
switch (value) {
|
||||
case 0:
|
||||
default:
|
||||
myAvatar->setUserRecenterModel(MyAvatar::SitStandModelType::Auto);
|
||||
break;
|
||||
case 1:
|
||||
myAvatar->setUserRecenterModel(MyAvatar::SitStandModelType::ForceSit);
|
||||
break;
|
||||
case 2:
|
||||
myAvatar->setUserRecenterModel(MyAvatar::SitStandModelType::DisableHMDLean);
|
||||
break;
|
||||
}
|
||||
};
|
||||
auto preference = new RadioButtonsPreference(VR_MOVEMENT, "Auto / Force Sit / Disable Recenter", getter, setter);
|
||||
QStringList items;
|
||||
items << "Auto - turns on avatar leaning when standing in real world" << "Seated - disables all avatar leaning while sitting in real world" << "Disabled - allows avatar sitting on the floor [Experimental]";
|
||||
preference->setHeading("Avatar leaning behavior");
|
||||
preference->setItems(items);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
auto getter = [=]()->float { return myAvatar->getUserHeight(); };
|
||||
auto setter = [=](float value) { myAvatar->setUserHeight(value); };
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#include "raypick/PointerScriptingInterface.h"
|
||||
#include <display-plugins/CompositorHelper.h>
|
||||
#include "AboutUtil.h"
|
||||
#include "ResourceRequestObserver.h"
|
||||
|
||||
static int MAX_WINDOW_SIZE = 4096;
|
||||
static const float METERS_TO_INCHES = 39.3701f;
|
||||
|
@ -269,6 +270,7 @@ void Web3DOverlay::setupQmlSurface(bool isTablet) {
|
|||
_webSurface->getSurfaceContext()->setContextProperty("Window", DependencyManager::get<WindowScriptingInterface>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("Reticle", qApp->getApplicationCompositor().getReticleInterface());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("HiFiAbout", AboutUtil::getInstance());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("ResourceRequestObserver", DependencyManager::get<ResourceRequestObserver>().data());
|
||||
|
||||
// Override min fps for tablet UI, for silky smooth scrolling
|
||||
setMaxFPS(90);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
set(TARGET_NAME avatars-renderer)
|
||||
setup_hifi_library(Network Script)
|
||||
link_hifi_libraries(shared gpu graphics animation model-networking script-engine render render-utils image trackers entities-renderer)
|
||||
link_hifi_libraries(shared shaders gpu graphics animation model-networking script-engine render render-utils image trackers entities-renderer)
|
||||
include_hifi_library_headers(avatars)
|
||||
include_hifi_library_headers(networking)
|
||||
include_hifi_library_headers(fbx)
|
||||
|
|
|
@ -1731,6 +1731,7 @@ void Avatar::getCapsule(glm::vec3& start, glm::vec3& end, float& radius) {
|
|||
|
||||
glm::vec3 Avatar::getWorldFeetPosition() {
|
||||
ShapeInfo shapeInfo;
|
||||
|
||||
computeShapeInfo(shapeInfo);
|
||||
glm::vec3 halfExtents = shapeInfo.getHalfExtents(); // x = radius, y = halfHeight
|
||||
glm::vec3 localFeet(0.0f, shapeInfo.getOffset().y - halfExtents.y - halfExtents.x, 0.0f);
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "AvatarLogging.h"
|
||||
#include "AvatarTraits.h"
|
||||
#include "ClientTraitsHandler.h"
|
||||
#include "ResourceRequestObserver.h"
|
||||
|
||||
//#define WANT_DEBUG
|
||||
|
||||
|
@ -2161,11 +2162,21 @@ void AvatarData::updateJointMappings() {
|
|||
}
|
||||
|
||||
if (_skeletonModelURL.fileName().toLower().endsWith(".fst")) {
|
||||
////
|
||||
// TODO: Should we rely upon HTTPResourceRequest for ResourceRequestObserver instead?
|
||||
// HTTPResourceRequest::doSend() covers all of the following and
|
||||
// then some. It doesn't cover the connect() call, so we may
|
||||
// want to add a HTTPResourceRequest::doSend() method that does
|
||||
// connects.
|
||||
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
||||
QNetworkRequest networkRequest = QNetworkRequest(_skeletonModelURL);
|
||||
networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
|
||||
DependencyManager::get<ResourceRequestObserver>()->update(
|
||||
_skeletonModelURL, -1, "AvatarData::updateJointMappings");
|
||||
QNetworkReply* networkReply = networkAccessManager.get(networkRequest);
|
||||
//
|
||||
////
|
||||
connect(networkReply, &QNetworkReply::finished, this, &AvatarData::setJointMappingsFromNetworkReply);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,27 @@ ClientTraitsHandler::ClientTraitsHandler(AvatarData* owningAvatar) :
|
|||
nodeList->getPacketReceiver().registerListener(PacketType::SetAvatarTraits, this, "processTraitOverride");
|
||||
}
|
||||
|
||||
void ClientTraitsHandler::markTraitUpdated(AvatarTraits::TraitType updatedTrait) {
|
||||
Lock lock(_traitLock);
|
||||
_traitStatuses[updatedTrait] = Updated;
|
||||
_hasChangedTraits = true;
|
||||
}
|
||||
|
||||
void ClientTraitsHandler::markInstancedTraitUpdated(AvatarTraits::TraitType traitType, QUuid updatedInstanceID) {
|
||||
Lock lock(_traitLock);
|
||||
_traitStatuses.instanceInsert(traitType, updatedInstanceID, Updated);
|
||||
_hasChangedTraits = true;
|
||||
}
|
||||
|
||||
void ClientTraitsHandler::markInstancedTraitDeleted(AvatarTraits::TraitType traitType, QUuid deleteInstanceID) {
|
||||
Lock lock(_traitLock);
|
||||
_traitStatuses.instanceInsert(traitType, deleteInstanceID, Deleted);
|
||||
_hasChangedTraits = true;
|
||||
}
|
||||
|
||||
void ClientTraitsHandler::resetForNewMixer() {
|
||||
Lock lock(_traitLock);
|
||||
|
||||
// re-set the current version to 0
|
||||
_currentTraitVersion = AvatarTraits::DEFAULT_TRAIT_VERSION;
|
||||
|
||||
|
@ -46,6 +66,8 @@ void ClientTraitsHandler::resetForNewMixer() {
|
|||
}
|
||||
|
||||
void ClientTraitsHandler::sendChangedTraitsToMixer() {
|
||||
Lock lock(_traitLock);
|
||||
|
||||
if (hasChangedTraits() || _shouldPerformInitialSend) {
|
||||
// we have at least one changed trait to send
|
||||
|
||||
|
@ -113,6 +135,7 @@ void ClientTraitsHandler::sendChangedTraitsToMixer() {
|
|||
|
||||
void ClientTraitsHandler::processTraitOverride(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) {
|
||||
if (sendingNode->getType() == NodeType::AvatarMixer) {
|
||||
Lock lock(_traitLock);
|
||||
while (message->getBytesLeftToRead()) {
|
||||
AvatarTraits::TraitType traitType;
|
||||
message->readPrimitive(&traitType);
|
||||
|
|
|
@ -26,14 +26,11 @@ public:
|
|||
|
||||
void sendChangedTraitsToMixer();
|
||||
|
||||
bool hasChangedTraits() { return _hasChangedTraits; }
|
||||
bool hasChangedTraits() const { return _hasChangedTraits; }
|
||||
|
||||
void markTraitUpdated(AvatarTraits::TraitType updatedTrait)
|
||||
{ _traitStatuses[updatedTrait] = Updated; _hasChangedTraits = true; }
|
||||
void markInstancedTraitUpdated(AvatarTraits::TraitType traitType, QUuid updatedInstanceID)
|
||||
{ _traitStatuses.instanceInsert(traitType, updatedInstanceID, Updated); _hasChangedTraits = true; }
|
||||
void markInstancedTraitDeleted(AvatarTraits::TraitType traitType, QUuid deleteInstanceID)
|
||||
{ _traitStatuses.instanceInsert(traitType, deleteInstanceID, Deleted); _hasChangedTraits = true; }
|
||||
void markTraitUpdated(AvatarTraits::TraitType updatedTrait);
|
||||
void markInstancedTraitUpdated(AvatarTraits::TraitType traitType, QUuid updatedInstanceID);
|
||||
void markInstancedTraitDeleted(AvatarTraits::TraitType traitType, QUuid deleteInstanceID);
|
||||
|
||||
void resetForNewMixer();
|
||||
|
||||
|
@ -41,17 +38,21 @@ public slots:
|
|||
void processTraitOverride(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
|
||||
|
||||
private:
|
||||
using Mutex = std::recursive_mutex;
|
||||
using Lock = std::lock_guard<Mutex>;
|
||||
|
||||
enum ClientTraitStatus {
|
||||
Unchanged,
|
||||
Updated,
|
||||
Deleted
|
||||
};
|
||||
|
||||
AvatarData* _owningAvatar;
|
||||
AvatarData* const _owningAvatar;
|
||||
|
||||
Mutex _traitLock;
|
||||
AvatarTraits::AssociatedTraitValues<ClientTraitStatus, Unchanged> _traitStatuses;
|
||||
AvatarTraits::TraitVersion _currentTraitVersion { AvatarTraits::DEFAULT_TRAIT_VERSION };
|
||||
|
||||
AvatarTraits::TraitVersion _currentTraitVersion { AvatarTraits::DEFAULT_TRAIT_VERSION };
|
||||
AvatarTraits::TraitVersion _currentSkeletonVersion { AvatarTraits::NULL_TRAIT_VERSION };
|
||||
|
||||
bool _shouldPerformInitialSend { false };
|
||||
|
|
|
@ -2,11 +2,11 @@ struct TextureData {
|
|||
ivec2 textureSize;
|
||||
};
|
||||
|
||||
layout(std140, binding=0) uniform textureDataBuffer {
|
||||
LAYOUT_STD140(binding=0) uniform textureDataBuffer {
|
||||
TextureData textureData;
|
||||
};
|
||||
|
||||
layout(binding=0) uniform sampler2D colorMap;
|
||||
LAYOUT(binding=0) uniform sampler2D colorMap;
|
||||
layout(location=0) in vec2 varTexCoord0;
|
||||
layout(location=0) out vec4 outFragColor;
|
||||
|
||||
|
|
|
@ -363,56 +363,35 @@ void OpenGLDisplayPlugin::customizeContext() {
|
|||
}
|
||||
|
||||
if (!_presentPipeline) {
|
||||
gpu::StatePointer blendState = gpu::StatePointer(new gpu::State());
|
||||
blendState->setDepthTest(gpu::State::DepthTest(false));
|
||||
blendState->setBlendFunction(true,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
|
||||
gpu::StatePointer scissorState = gpu::StatePointer(new gpu::State());
|
||||
scissorState->setDepthTest(gpu::State::DepthTest(false));
|
||||
scissorState->setScissorEnable(true);
|
||||
|
||||
{
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::gpu::program::drawTexture);
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(gpu::State::DepthTest(false));
|
||||
state->setScissorEnable(true);
|
||||
_simplePipeline = gpu::Pipeline::create(program, state);
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::gpu::program::DrawTexture);
|
||||
_simplePipeline = gpu::Pipeline::create(program, scissorState);
|
||||
_hudPipeline = gpu::Pipeline::create(program, blendState);
|
||||
}
|
||||
|
||||
{
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::display_plugins::program::SrgbToLinear);
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(gpu::State::DepthTest(false));
|
||||
state->setScissorEnable(true);
|
||||
_presentPipeline = gpu::Pipeline::create(program, state);
|
||||
_presentPipeline = gpu::Pipeline::create(program, scissorState);
|
||||
}
|
||||
|
||||
{
|
||||
auto vs = gpu::Shader::createVertex(shader::gpu::vertex::DrawUnitQuadTexcoord);
|
||||
auto ps = gpu::Shader::createPixel(shader::gpu::fragment::DrawTexture);
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(gpu::State::DepthTest(false));
|
||||
state->setBlendFunction(true,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
_hudPipeline = gpu::Pipeline::create(program, state);
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::gpu::program::DrawTextureMirroredX);
|
||||
_mirrorHUDPipeline = gpu::Pipeline::create(program, blendState);
|
||||
}
|
||||
|
||||
{
|
||||
auto vs = gpu::Shader::createVertex(shader::gpu::vertex::DrawUnitQuadTexcoord);
|
||||
auto ps = gpu::Shader::createPixel(shader::gpu::fragment::DrawTextureMirroredX);
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(gpu::State::DepthTest(false));
|
||||
state->setBlendFunction(true,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
_mirrorHUDPipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
|
||||
{
|
||||
auto vs = gpu::Shader::createVertex(shader::gpu::vertex::DrawTransformUnitQuad);
|
||||
auto ps = gpu::Shader::createPixel(shader::gpu::fragment::DrawTexture);
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(gpu::State::DepthTest(false));
|
||||
state->setBlendFunction(true,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
_cursorPipeline = gpu::Pipeline::create(program, state);
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::gpu::program::DrawTransformedTexture);
|
||||
_cursorPipeline = gpu::Pipeline::create(program, blendState);
|
||||
}
|
||||
}
|
||||
updateCompositeFramebuffer();
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
// OpenGLDisplayPlugin_present.frag
|
||||
|
||||
layout(binding = 0) uniform sampler2D colorMap;
|
||||
LAYOUT(binding=0) uniform sampler2D colorMap;
|
||||
|
||||
layout(location = 0) in vec2 varTexCoord0;
|
||||
layout(location=0) in vec2 varTexCoord0;
|
||||
|
||||
layout(location = 0) out vec4 outFragColor;
|
||||
layout(location=0) out vec4 outFragColor;
|
||||
|
||||
float sRGBFloatToLinear(float value) {
|
||||
const float SRGB_ELBOW = 0.04045;
|
||||
|
|
|
@ -30,12 +30,14 @@ 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);
|
||||
// FIXME: Setup proper uniform slots and use correct pipelines for forward rendering
|
||||
_procedural._opaquefragmentSource = gpu::Shader::getFragmentShaderSource(shader::render_utils::fragment::simple);
|
||||
_procedural._transparentfragmentSource = gpu::Shader::getFragmentShaderSource(shader::render_utils::fragment::simple_transparent);
|
||||
_procedural._opaqueFragmentSource = gpu::Shader::Source::get(shader::render_utils::fragment::simple);
|
||||
_procedural._transparentFragmentSource = gpu::Shader::Source::get(shader::render_utils::fragment::simple_transparent);
|
||||
_procedural._opaqueState->setCullMode(gpu::State::CULL_NONE);
|
||||
_procedural._opaqueState->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
PrepareStencil::testMaskDrawShape(*_procedural._opaqueState);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<@include DeferredBufferWrite.slh@>
|
||||
|
||||
// the albedo texture
|
||||
layout(binding=0) uniform sampler2D originalTexture;
|
||||
LAYOUT(binding=0) uniform sampler2D originalTexture;
|
||||
|
||||
// the interpolated normal
|
||||
layout(location=0) in vec3 interpolatedNormal;
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<$declareFadeFragment()$>
|
||||
|
||||
// the albedo texture
|
||||
layout(binding=0) uniform sampler2D originalTexture;
|
||||
LAYOUT(binding=0) uniform sampler2D originalTexture;
|
||||
|
||||
// the interpolated normal
|
||||
layout(location=0) in vec3 interpolatedNormal;
|
||||
|
@ -30,7 +30,7 @@ struct PolyLineUniforms {
|
|||
vec3 color;
|
||||
};
|
||||
|
||||
layout(binding=0) uniform polyLineBuffer {
|
||||
LAYOUT(binding=0) uniform polyLineBuffer {
|
||||
PolyLineUniforms polyline;
|
||||
};
|
||||
|
||||
|
|
|
@ -20,15 +20,15 @@ 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(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;
|
||||
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 {
|
||||
LAYOUT(binding=0) uniform polyvoxParamsBuffer {
|
||||
PolyvoxParams params;
|
||||
};
|
||||
|
||||
|
|
|
@ -23,15 +23,15 @@ 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;
|
||||
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 {
|
||||
LAYOUT(binding=0) uniform polyvoxParamsBuffer {
|
||||
PolyvoxParams params;
|
||||
};
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
layout(binding=0) uniform sampler2D colorMap;
|
||||
LAYOUT(binding=0) uniform sampler2D colorMap;
|
||||
|
||||
layout(location=0) in vec4 varColor;
|
||||
layout(location=1) in vec2 varTexcoord;
|
||||
|
|
|
@ -43,7 +43,7 @@ struct ParticleUniforms {
|
|||
vec2 spare;
|
||||
};
|
||||
|
||||
layout(std140, binding=0) uniform particleBuffer {
|
||||
LAYOUT_STD140(binding=0) uniform particleBuffer {
|
||||
ParticleUniforms particle;
|
||||
};
|
||||
|
||||
|
|
|
@ -5,4 +5,4 @@ include_hifi_library_headers(fbx)
|
|||
include_hifi_library_headers(gpu)
|
||||
include_hifi_library_headers(image)
|
||||
include_hifi_library_headers(ktx)
|
||||
link_hifi_libraries(shared networking octree avatars graphics model-networking)
|
||||
link_hifi_libraries(shared shaders networking octree avatars graphics model-networking)
|
|
@ -200,7 +200,8 @@ void EntityEditFilters::addFilter(EntityItemID entityID, QString filterURL) {
|
|||
_filterDataMap.insert(entityID, filterData);
|
||||
_lock.unlock();
|
||||
|
||||
auto scriptRequest = DependencyManager::get<ResourceManager>()->createResourceRequest(this, scriptURL);
|
||||
auto scriptRequest = DependencyManager::get<ResourceManager>()->createResourceRequest(
|
||||
this, scriptURL, true, -1, "EntityEditFilters::addFilter");
|
||||
if (!scriptRequest) {
|
||||
qWarning() << "Could not create ResourceRequest for Entity Edit filter script at" << scriptURL.toString();
|
||||
scriptRequestFinished(entityID);
|
||||
|
|
|
@ -953,7 +953,8 @@ bool GLTFReader::doesResourceExist(const QString& url) {
|
|||
}
|
||||
|
||||
std::tuple<bool, QByteArray> GLTFReader::requestData(QUrl& url) {
|
||||
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(nullptr, url);
|
||||
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(
|
||||
nullptr, url, true, -1, "GLTFReader::requestData");
|
||||
|
||||
if (!request) {
|
||||
return std::make_tuple(false, QByteArray());
|
||||
|
|
|
@ -443,7 +443,8 @@ void OBJReader::parseTextureLine(const QByteArray& textureLine, QByteArray& file
|
|||
}
|
||||
|
||||
std::tuple<bool, QByteArray> requestData(QUrl& url) {
|
||||
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(nullptr, url);
|
||||
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(
|
||||
nullptr, url, true, -1, "(OBJReader) requestData");
|
||||
|
||||
if (!request) {
|
||||
return std::make_tuple(false, QByteArray());
|
||||
|
|
|
@ -14,14 +14,17 @@ using namespace gl;
|
|||
|
||||
void Uniform::load(GLuint glprogram, int index) {
|
||||
this->index = index;
|
||||
const GLint NAME_LENGTH = 256;
|
||||
GLchar glname[NAME_LENGTH];
|
||||
GLint length = 0;
|
||||
glGetActiveUniform(glprogram, index, NAME_LENGTH, &length, &size, &type, glname);
|
||||
// Length does NOT include the null terminator
|
||||
// https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetActiveUniform.xhtml
|
||||
name = std::string(glname, length);
|
||||
binding = glGetUniformLocation(glprogram, glname);
|
||||
if (index >= 0) {
|
||||
static const GLint NAME_LENGTH = 1024;
|
||||
GLchar glname[NAME_LENGTH];
|
||||
memset(glname, 0, NAME_LENGTH);
|
||||
GLint length = 0;
|
||||
glGetActiveUniform(glprogram, index, NAME_LENGTH, &length, &size, &type, glname);
|
||||
// Length does NOT include the null terminator
|
||||
// https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetActiveUniform.xhtml
|
||||
name = std::string(glname, length);
|
||||
binding = glGetUniformLocation(glprogram, name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
bool isTextureType(GLenum type) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
set(TARGET_NAME gpu-gl-common)
|
||||
setup_hifi_library(Concurrent)
|
||||
link_hifi_libraries(shared gl gpu)
|
||||
link_hifi_libraries(shared gl gpu shaders)
|
||||
GroupSources("src")
|
||||
target_opengl()
|
||||
|
||||
|
|
|
@ -643,18 +643,21 @@ protected:
|
|||
}
|
||||
} _pipeline;
|
||||
|
||||
// Backend dependant compilation of the shader
|
||||
// Backend dependent compilation of the shader
|
||||
virtual void postLinkProgram(ShaderObject& programObject, const Shader& program) const;
|
||||
virtual GLShader* compileBackendProgram(const Shader& program, const Shader::CompilationHandler& handler);
|
||||
virtual GLShader* compileBackendShader(const Shader& shader, const Shader::CompilationHandler& handler);
|
||||
virtual std::string getBackendShaderHeader() const = 0;
|
||||
// For a program, this will return a string containing all the source files (without any
|
||||
// backend headers or defines). For a vertex, fragment or geometry shader, this will
|
||||
// return the fully customized shader with all the version and backend specific
|
||||
|
||||
// For a program, this will return a string containing all the source files (without any
|
||||
// backend headers or defines). For a vertex, fragment or geometry shader, this will
|
||||
// return the fully customized shader with all the version and backend specific
|
||||
// preprocessor directives
|
||||
// The program string returned can be used as a key for a cache of shader binaries
|
||||
// The shader strings can be reliably sent to the low level `compileShader` functions
|
||||
virtual std::string getShaderSource(const Shader& shader, int version) final;
|
||||
virtual std::string getShaderSource(const Shader& shader, shader::Variant version) final;
|
||||
shader::Variant getShaderVariant() const { return isStereo() ? shader::Variant::Stereo : shader::Variant::Mono; }
|
||||
virtual shader::Dialect getShaderDialect() const = 0;
|
||||
|
||||
class ElementResource {
|
||||
public:
|
||||
gpu::Element _element;
|
||||
|
|
|
@ -54,7 +54,7 @@ void GLBackend::do_setPipeline(const Batch& batch, size_t paramOffset) {
|
|||
// check the program cache
|
||||
// pick the program version
|
||||
#ifdef GPU_STEREO_CAMERA_BUFFER
|
||||
GLuint glprogram = pipelineObject->_program->getProgram((GLShader::Version)isStereo());
|
||||
GLuint glprogram = pipelineObject->_program->getProgram(getShaderVariant());
|
||||
#else
|
||||
GLuint glprogram = pipelineObject->_program->getProgram();
|
||||
#endif
|
||||
|
|
|
@ -25,120 +25,53 @@ static const std::array<GLenum, NUM_SHADER_DOMAINS> SHADER_DOMAINS{ {
|
|||
GL_GEOMETRY_SHADER,
|
||||
} };
|
||||
|
||||
// Domain specific defines
|
||||
// Must match the order of type specified in gpu::Shader::Type
|
||||
static const std::array<std::string, NUM_SHADER_DOMAINS> DOMAIN_DEFINES{ {
|
||||
"#define GPU_VERTEX_SHADER",
|
||||
"#define GPU_PIXEL_SHADER",
|
||||
"#define GPU_GEOMETRY_SHADER",
|
||||
} };
|
||||
|
||||
// Stereo specific defines
|
||||
static const std::string stereoVersion{
|
||||
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||
R"SHADER(
|
||||
#define GPU_TRANSFORM_IS_STEREO
|
||||
#define GPU_TRANSFORM_STEREO_CAMERA
|
||||
#define GPU_TRANSFORM_STEREO_CAMERA_INSTANCED
|
||||
#define GPU_TRANSFORM_STEREO_SPLIT_SCREEN
|
||||
)SHADER"
|
||||
#endif
|
||||
#ifdef GPU_STEREO_DRAWCALL_DOUBLED
|
||||
#ifdef GPU_STEREO_CAMERA_BUFFER
|
||||
R"SHADER(
|
||||
#define GPU_TRANSFORM_IS_STEREO
|
||||
#define GPU_TRANSFORM_STEREO_CAMERA
|
||||
#define GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED
|
||||
)SHADER"
|
||||
#else
|
||||
R"SHADER(
|
||||
#define GPU_TRANSFORM_IS_STEREO
|
||||
)SHADER"
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
// TextureTable specific defines
|
||||
static const std::string textureTableVersion {
|
||||
"#extension GL_ARB_bindless_texture : require\n#define GPU_TEXTURE_TABLE_BINDLESS\n"
|
||||
};
|
||||
|
||||
// Versions specific of the shader
|
||||
static const std::array<std::string, GLShader::NumVersions> VERSION_DEFINES { {
|
||||
"",
|
||||
stereoVersion
|
||||
} };
|
||||
|
||||
static std::string getShaderTypeString(Shader::Type type) {
|
||||
switch (type) {
|
||||
case Shader::Type::VERTEX:
|
||||
return "vertex";
|
||||
case Shader::Type::PIXEL:
|
||||
return "pixel";
|
||||
case Shader::Type::GEOMETRY:
|
||||
return "geometry";
|
||||
case Shader::Type::PROGRAM:
|
||||
return "program";
|
||||
default:
|
||||
qFatal("Unexpected shader type %d", type);
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
std::string GLBackend::getShaderSource(const Shader& shader, int version) {
|
||||
std::string GLBackend::getShaderSource(const Shader& shader, shader::Variant variant) {
|
||||
if (shader.isProgram()) {
|
||||
std::string result;
|
||||
result.append("// VERSION " + std::to_string(version));
|
||||
for (const auto& subShader : shader.getShaders()) {
|
||||
result.append("//-------- ");
|
||||
result.append(getShaderTypeString(subShader->getType()));
|
||||
result.append("\n");
|
||||
result.append(subShader->getSource().getCode());
|
||||
if (subShader) {
|
||||
result += subShader->getSource().getSource(getShaderDialect(), variant);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string shaderDefines = getBackendShaderHeader() + "\n"
|
||||
+ (supportsBindless() ? textureTableVersion : "\n")
|
||||
+ DOMAIN_DEFINES[shader.getType()] + "\n"
|
||||
+ VERSION_DEFINES[version];
|
||||
|
||||
return shaderDefines + "\n" + shader.getSource().getCode();
|
||||
}
|
||||
return shader.getSource().getSource(getShaderDialect(), variant);
|
||||
}
|
||||
|
||||
GLShader* GLBackend::compileBackendShader(const Shader& shader, const Shader::CompilationHandler& handler) {
|
||||
// Any GLSLprogram ? normally yes...
|
||||
GLenum shaderDomain = SHADER_DOMAINS[shader.getType()];
|
||||
GLShader::ShaderObjects shaderObjects;
|
||||
Shader::CompilationLogs compilationLogs(GLShader::NumVersions);
|
||||
const auto& variants = shader::allVariants();
|
||||
Shader::CompilationLogs compilationLogs(variants.size());
|
||||
shader.incrementCompilationAttempt();
|
||||
|
||||
for (int version = 0; version < GLShader::NumVersions; version++) {
|
||||
auto& shaderObject = shaderObjects[version];
|
||||
auto shaderSource = getShaderSource(shader, version);
|
||||
for (const auto& variant : variants) {
|
||||
auto index = static_cast<uint32_t>(variant);
|
||||
auto shaderSource = getShaderSource(shader, variant);
|
||||
auto& shaderObject = shaderObjects[index];
|
||||
if (handler) {
|
||||
bool retest = true;
|
||||
std::string currentSrc = shaderSource;
|
||||
// When a Handler is specified, we can try multiple times to build the shader and let the handler change the source if the compilation fails.
|
||||
// The retest bool is set to false as soon as the compilation succeed to wexit the while loop.
|
||||
// The retest bool is set to false as soon as the compilation succeed to exit the while loop.
|
||||
// The handler tells us if we should retry or not while returning a modified version of the source.
|
||||
while (retest) {
|
||||
bool result = ::gl::compileShader(shaderDomain, currentSrc, shaderObject.glshader, compilationLogs[version].message);
|
||||
compilationLogs[version].compiled = result;
|
||||
bool result = ::gl::compileShader(shaderDomain, currentSrc, shaderObject.glshader, compilationLogs[index].message);
|
||||
compilationLogs[index].compiled = result;
|
||||
if (!result) {
|
||||
std::string newSrc;
|
||||
retest = handler(shader, currentSrc, compilationLogs[version], newSrc);
|
||||
retest = handler(shader, currentSrc, compilationLogs[index], newSrc);
|
||||
currentSrc = newSrc;
|
||||
} else {
|
||||
retest = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
compilationLogs[version].compiled = ::gl::compileShader(shaderDomain, shaderSource, shaderObject.glshader, compilationLogs[version].message);
|
||||
compilationLogs[index].compiled = ::gl::compileShader(shaderDomain, shaderSource, shaderObject.glshader, compilationLogs[index].message);
|
||||
}
|
||||
|
||||
if (!compilationLogs[version].compiled) {
|
||||
qCWarning(gpugllogging) << "GLBackend::compileBackendProgram - Shader didn't compile:\n" << compilationLogs[version].message.c_str();
|
||||
if (!compilationLogs[index].compiled) {
|
||||
qCWarning(gpugllogging) << "GLBackend::compileBackendProgram - Shader didn't compile:\n" << compilationLogs[index].message.c_str();
|
||||
shader.setCompilationLogs(compilationLogs);
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -162,11 +95,13 @@ GLShader* GLBackend::compileBackendProgram(const Shader& program, const Shader::
|
|||
|
||||
GLShader::ShaderObjects programObjects;
|
||||
program.incrementCompilationAttempt();
|
||||
Shader::CompilationLogs compilationLogs(GLShader::NumVersions);
|
||||
const auto& variants = shader::allVariants();
|
||||
Shader::CompilationLogs compilationLogs(variants.size());
|
||||
|
||||
for (int version = 0; version < GLShader::NumVersions; version++) {
|
||||
auto& programObject = programObjects[version];
|
||||
auto programSource = getShaderSource(program, version);
|
||||
for (const auto& variant : variants) {
|
||||
auto index = static_cast<uint32_t>(variant);
|
||||
auto& programObject = programObjects[index];
|
||||
auto programSource = getShaderSource(program, variant);
|
||||
auto hash = ::gl::getShaderHash(programSource);
|
||||
|
||||
CachedShader cachedBinary;
|
||||
|
@ -199,11 +134,11 @@ GLShader* GLBackend::compileBackendProgram(const Shader& program, const Shader::
|
|||
for (auto subShader : program.getShaders()) {
|
||||
auto object = GLShader::sync((*this), *subShader, handler);
|
||||
if (object) {
|
||||
shaderGLObjects.push_back(object->_shaderObjects[version].glshader);
|
||||
shaderGLObjects.push_back(object->_shaderObjects[index].glshader);
|
||||
} else {
|
||||
qCWarning(gpugllogging) << "GLBackend::compileBackendProgram - One of the shaders of the program is not compiled?";
|
||||
compilationLogs[version].compiled = false;
|
||||
compilationLogs[version].message = std::string("Failed to compile, one of the shaders of the program is not compiled ?");
|
||||
compilationLogs[index].compiled = false;
|
||||
compilationLogs[index].message = std::string("Failed to compile, one of the shaders of the program is not compiled ?");
|
||||
program.setCompilationLogs(compilationLogs);
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -211,9 +146,9 @@ GLShader* GLBackend::compileBackendProgram(const Shader& program, const Shader::
|
|||
|
||||
glprogram = ::gl::buildProgram(shaderGLObjects);
|
||||
|
||||
if (!::gl::linkProgram(glprogram, compilationLogs[version].message)) {
|
||||
qCWarning(gpugllogging) << "GLBackend::compileBackendProgram - Program didn't link:\n" << compilationLogs[version].message.c_str();
|
||||
compilationLogs[version].compiled = false;
|
||||
if (!::gl::linkProgram(glprogram, compilationLogs[index].message)) {
|
||||
qCWarning(gpugllogging) << "GLBackend::compileBackendProgram - Program didn't link:\n" << compilationLogs[index].message.c_str();
|
||||
compilationLogs[index].compiled = false;
|
||||
glDeleteProgram(glprogram);
|
||||
glprogram = 0;
|
||||
return nullptr;
|
||||
|
@ -228,12 +163,12 @@ GLShader* GLBackend::compileBackendProgram(const Shader& program, const Shader::
|
|||
}
|
||||
|
||||
if (glprogram == 0) {
|
||||
qCWarning(gpugllogging) << "GLBackend::compileBackendProgram - Program didn't link:\n" << compilationLogs[version].message.c_str();
|
||||
qCWarning(gpugllogging) << "GLBackend::compileBackendProgram - Program didn't link:\n" << compilationLogs[index].message.c_str();
|
||||
program.setCompilationLogs(compilationLogs);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
compilationLogs[version].compiled = true;
|
||||
compilationLogs[index].compiled = true;
|
||||
programObject.glprogram = glprogram;
|
||||
postLinkProgram(programObject, program);
|
||||
}
|
||||
|
@ -249,7 +184,10 @@ GLShader* GLBackend::compileBackendProgram(const Shader& program, const Shader::
|
|||
static const GLint INVALID_UNIFORM_INDEX = -1;
|
||||
|
||||
GLint GLBackend::getRealUniformLocation(GLint location) const {
|
||||
auto& shader = _pipeline._programShader->_shaderObjects[(GLShader::Version)isStereo()];
|
||||
auto variant = isStereo() ? shader::Variant::Stereo : shader::Variant::Mono;
|
||||
auto index = static_cast<uint32_t>(variant);
|
||||
|
||||
auto& shader = _pipeline._programShader->_shaderObjects[index];
|
||||
auto itr = shader.uniformRemap.find(location);
|
||||
if (itr == shader.uniformRemap.end()) {
|
||||
// This shouldn't happen, because we use reflection to determine all the possible
|
||||
|
@ -264,20 +202,23 @@ GLint GLBackend::getRealUniformLocation(GLint location) const {
|
|||
|
||||
void GLBackend::postLinkProgram(ShaderObject& shaderObject, const Shader& program) const {
|
||||
const auto& glprogram = shaderObject.glprogram;
|
||||
const auto& expectedUniforms = program.getUniforms();
|
||||
const auto expectedLocationsByName = expectedUniforms.getLocationsByName();
|
||||
const auto uniforms = ::gl::Uniform::load(glprogram, expectedUniforms.getNames());
|
||||
auto& uniformRemap = shaderObject.uniformRemap;
|
||||
const auto& expectedUniforms = program.getReflection().uniforms;
|
||||
|
||||
// Pre-initialize all the uniforms with an invalid location
|
||||
for (const auto& entry : expectedLocationsByName) {
|
||||
auto& uniformRemap = shaderObject.uniformRemap;
|
||||
// initialize all the uniforms with an invalid location
|
||||
for (const auto& entry : expectedUniforms) {
|
||||
uniformRemap[entry.second] = INVALID_UNIFORM_INDEX;
|
||||
}
|
||||
|
||||
// Now load up all the actual found uniform location
|
||||
|
||||
// Get the actual uniform locations from the shader
|
||||
const auto names = Shader::Reflection::getNames(expectedUniforms);
|
||||
const auto uniforms = ::gl::Uniform::load(glprogram, names);
|
||||
|
||||
// Now populate the remapping with the found locations
|
||||
for (const auto& uniform : uniforms) {
|
||||
const auto& name = uniform.name;
|
||||
const auto& expectedLocation = expectedLocationsByName.at(name);
|
||||
const auto& expectedLocation = expectedUniforms.at(name);
|
||||
const auto& location = uniform.binding;
|
||||
uniformRemap[expectedLocation] = location;
|
||||
}
|
||||
|
@ -462,3 +403,4 @@ void GLBackend::initShaderBinaryCache() {
|
|||
void GLBackend::killShaderBinaryCache() {
|
||||
::gl::saveShaderCache(_shaderBinaryCache._binaries);
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ GLPipeline* GLPipeline::sync(GLBackend& backend, const Pipeline& pipeline) {
|
|||
// Special case for view correction matrices, any pipeline that declares the correction buffer
|
||||
// uniform will automatically have it provided without any client code necessary.
|
||||
// Required for stable lighting in the HMD.
|
||||
object->_cameraCorrection = shader->getUniformBuffers().isValid(gpu::slot::buffer::CameraCorrection);
|
||||
object->_cameraCorrection = shader->getReflection().validUniformBuffer(gpu::slot::buffer::CameraCorrection);
|
||||
object->_program = programObject;
|
||||
object->_state = stateObject;
|
||||
|
||||
|
|
|
@ -14,43 +14,45 @@
|
|||
namespace gpu { namespace gl {
|
||||
|
||||
struct ShaderObject {
|
||||
GLuint glshader { 0 };
|
||||
GLuint glprogram { 0 };
|
||||
enum class BindingType
|
||||
{
|
||||
INPUT,
|
||||
OUTPUT,
|
||||
TEXTURE,
|
||||
SAMPLER,
|
||||
UNIFORM_BUFFER,
|
||||
RESOURCE_BUFFER,
|
||||
UNIFORM,
|
||||
};
|
||||
|
||||
using LocationMap = std::unordered_map <GLuint, GLuint>;
|
||||
LocationMap uniformRemap;
|
||||
using LocationMap = std::unordered_map<std::string, int32_t>;
|
||||
using ReflectionMap = std::map<BindingType, LocationMap>;
|
||||
using UniformMap = std::unordered_map<GLuint, GLuint>;
|
||||
|
||||
GLuint glshader{ 0 };
|
||||
GLuint glprogram{ 0 };
|
||||
|
||||
UniformMap uniformRemap;
|
||||
};
|
||||
|
||||
class GLShader : public GPUObject {
|
||||
public:
|
||||
static GLShader* sync(GLBackend& backend, const Shader& shader, const Shader::CompilationHandler& handler = nullptr);
|
||||
|
||||
enum Version {
|
||||
Mono = 0,
|
||||
Stereo,
|
||||
|
||||
NumVersions
|
||||
};
|
||||
|
||||
using ShaderObject = gpu::gl::ShaderObject;
|
||||
using ShaderObjects = std::array< ShaderObject, NumVersions >;
|
||||
|
||||
using UniformMapping = std::map<GLint, GLint>;
|
||||
using UniformMappingVersions = std::vector<UniformMapping>;
|
||||
using ShaderObjects = std::array<ShaderObject, shader::NUM_VARIANTS>;
|
||||
|
||||
GLShader(const std::weak_ptr<GLBackend>& backend);
|
||||
~GLShader();
|
||||
|
||||
ShaderObjects _shaderObjects;
|
||||
|
||||
GLuint getProgram(Version version = Mono) const {
|
||||
return _shaderObjects[version].glprogram;
|
||||
GLuint getProgram(shader::Variant version = shader::Variant::Mono) const {
|
||||
return _shaderObjects[static_cast<uint32_t>(version)].glprogram;
|
||||
}
|
||||
|
||||
const std::weak_ptr<GLBackend> _backend;
|
||||
};
|
||||
|
||||
} }
|
||||
|
||||
}} // namespace gpu::gl
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
set(TARGET_NAME gpu-gl)
|
||||
setup_hifi_library(Concurrent)
|
||||
link_hifi_libraries(shared gl gpu gpu-gl-common)
|
||||
link_hifi_libraries(shared gl gpu gpu-gl-common shaders)
|
||||
if (UNIX)
|
||||
target_link_libraries(${TARGET_NAME} pthread)
|
||||
endif(UNIX)
|
||||
|
|
|
@ -170,8 +170,7 @@ protected:
|
|||
// Output stage
|
||||
void do_blit(const Batch& batch, size_t paramOffset) override;
|
||||
|
||||
std::string getBackendShaderHeader() const override;
|
||||
|
||||
shader::Dialect getShaderDialect() const override { return shader::Dialect::glsl410; }
|
||||
void postLinkProgram(ShaderObject& programObject, const Shader& program) const override;
|
||||
};
|
||||
|
||||
|
|
|
@ -12,22 +12,13 @@ using namespace gpu;
|
|||
using namespace gpu::gl;
|
||||
using namespace gpu::gl41;
|
||||
|
||||
// GLSL version
|
||||
std::string GL41Backend::getBackendShaderHeader() const {
|
||||
static const std::string header(
|
||||
R"SHADER(#version 410 core
|
||||
#define GPU_GL410
|
||||
#define BITFIELD int
|
||||
)SHADER");
|
||||
return header;
|
||||
}
|
||||
|
||||
void GL41Backend::postLinkProgram(ShaderObject& programObject, const Shader& program) const {
|
||||
Parent::postLinkProgram(programObject, program);
|
||||
const auto& glprogram = programObject.glprogram;
|
||||
const auto& reflection = program.getReflection();
|
||||
// For the UBOs, use glUniformBlockBinding to fixup the locations based on the reflection
|
||||
{
|
||||
const auto expectedUbos = program.getUniformBuffers().getLocationsByName();
|
||||
const auto& expectedUbos = reflection.uniformBuffers;
|
||||
auto ubos = ::gl::UniformBlock::load(glprogram);
|
||||
for (const auto& ubo : ubos) {
|
||||
const auto& name = ubo.name;
|
||||
|
@ -41,7 +32,7 @@ void GL41Backend::postLinkProgram(ShaderObject& programObject, const Shader& pro
|
|||
|
||||
// For the Textures, use glUniform1i to fixup the active texture slots based on the reflection
|
||||
{
|
||||
const auto expectedTextures = program.getTextures().getLocationsByName();
|
||||
const auto& expectedTextures = reflection.textures;
|
||||
for (const auto& expectedTexture : expectedTextures) {
|
||||
auto location = glGetUniformLocation(glprogram, expectedTexture.first.c_str());
|
||||
if (location < 0) {
|
||||
|
@ -53,8 +44,9 @@ void GL41Backend::postLinkProgram(ShaderObject& programObject, const Shader& pro
|
|||
|
||||
// For the resource buffers, do the same as for the textures, since in GL 4.1 that's how they're implemented
|
||||
{
|
||||
const auto expectedResourceBuffers = program.getResourceBuffers().getLocationsByName();
|
||||
const auto resourceBufferUniforms = ::gl::Uniform::loadByName(glprogram, program.getResourceBuffers().getNames());
|
||||
const auto& expectedResourceBuffers = reflection.resourceBuffers;
|
||||
const auto names = Shader::Reflection::getNames(expectedResourceBuffers);
|
||||
const auto resourceBufferUniforms = ::gl::Uniform::loadByName(glprogram, names);
|
||||
for (const auto& resourceBuffer : resourceBufferUniforms) {
|
||||
const auto& targetBinding = expectedResourceBuffers.at(resourceBuffer.name);
|
||||
glProgramUniform1i(glprogram, resourceBuffer.binding, targetBinding + GL41Backend::RESOURCE_BUFFER_SLOT0_TEX_UNIT);
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#define GPU_BINDLESS_TEXTURES 0
|
||||
|
||||
namespace gpu { namespace gl45 {
|
||||
|
||||
|
||||
using namespace gpu::gl;
|
||||
using TextureWeakPointer = std::weak_ptr<Texture>;
|
||||
|
||||
|
@ -56,6 +56,7 @@ public:
|
|||
using Parent = GLTexture;
|
||||
friend class GL45Backend;
|
||||
static GLuint allocate(const Texture& texture);
|
||||
|
||||
protected:
|
||||
GL45Texture(const std::weak_ptr<GLBackend>& backend, const Texture& texture);
|
||||
void generateMips() const override;
|
||||
|
@ -88,6 +89,7 @@ public:
|
|||
virtual const Bindless& getBindless() const;
|
||||
void releaseBindless() const;
|
||||
void recreateBindless() const;
|
||||
|
||||
private:
|
||||
mutable Bindless _bindless;
|
||||
#endif
|
||||
|
@ -98,10 +100,11 @@ public:
|
|||
mutable Sampler _cachedSampler{ getInvalidSampler() };
|
||||
};
|
||||
|
||||
#if GPU_BINDLESS_TEXTURES
|
||||
#if GPU_BINDLESS_TEXTURES
|
||||
class GL45TextureTable : public GLObject<TextureTable> {
|
||||
static GLuint allocate();
|
||||
using Parent = GLObject<TextureTable>;
|
||||
|
||||
public:
|
||||
using BindlessArray = std::array<GL45Texture::Bindless, TextureTable::COUNT>;
|
||||
|
||||
|
@ -116,7 +119,6 @@ public:
|
|||
};
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// Textures that have fixed allocation sizes and cannot be managed at runtime
|
||||
//
|
||||
|
@ -134,12 +136,13 @@ public:
|
|||
|
||||
void allocateStorage() const;
|
||||
void syncSampler() const override;
|
||||
const Size _size { 0 };
|
||||
const Size _size{ 0 };
|
||||
};
|
||||
|
||||
class GL45AttachmentTexture : public GL45FixedAllocationTexture {
|
||||
using Parent = GL45FixedAllocationTexture;
|
||||
friend class GL45Backend;
|
||||
|
||||
protected:
|
||||
GL45AttachmentTexture(const std::weak_ptr<GLBackend>& backend, const Texture& texture);
|
||||
~GL45AttachmentTexture();
|
||||
|
@ -148,6 +151,7 @@ public:
|
|||
class GL45StrictResourceTexture : public GL45FixedAllocationTexture {
|
||||
using Parent = GL45FixedAllocationTexture;
|
||||
friend class GL45Backend;
|
||||
|
||||
protected:
|
||||
GL45StrictResourceTexture(const std::weak_ptr<GLBackend>& backend, const Texture& texture);
|
||||
~GL45StrictResourceTexture();
|
||||
|
@ -179,6 +183,7 @@ public:
|
|||
class GL45ResourceTexture : public GL45VariableAllocationTexture {
|
||||
using Parent = GL45VariableAllocationTexture;
|
||||
friend class GL45Backend;
|
||||
|
||||
protected:
|
||||
GL45ResourceTexture(const std::weak_ptr<GLBackend>& backend, const Texture& texture);
|
||||
|
||||
|
@ -186,7 +191,6 @@ public:
|
|||
size_t promote() override;
|
||||
size_t demote() override;
|
||||
void populateTransferQueue(TransferQueue& pendingTransfers) override;
|
||||
|
||||
|
||||
void allocateStorage(uint16 mip);
|
||||
Size copyMipsFromTexture();
|
||||
|
@ -226,7 +230,6 @@ public:
|
|||
};
|
||||
#endif
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
void draw(GLenum mode, uint32 numVertices, uint32 startVertex) override;
|
||||
|
@ -244,7 +247,6 @@ protected:
|
|||
GLuint getQueryID(const QueryPointer& query) override;
|
||||
GLQuery* syncGPUObject(const Query& query) override;
|
||||
|
||||
|
||||
// Draw Stage
|
||||
void do_draw(const Batch& batch, size_t paramOffset) override;
|
||||
void do_drawIndexed(const Batch& batch, size_t paramOffset) override;
|
||||
|
@ -270,7 +272,7 @@ protected:
|
|||
void do_blit(const Batch& batch, size_t paramOffset) override;
|
||||
|
||||
// Shader Stage
|
||||
std::string getBackendShaderHeader() const override;
|
||||
shader::Dialect getShaderDialect() const override;
|
||||
|
||||
// Texture Management Stage
|
||||
void initTextureManagementStage() override;
|
||||
|
@ -282,9 +284,8 @@ protected:
|
|||
#endif
|
||||
};
|
||||
|
||||
} }
|
||||
}} // namespace gpu::gl45
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(gpugl45logging)
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -7,22 +7,16 @@
|
|||
//
|
||||
#include "GL45Backend.h"
|
||||
#include <gpu/gl/GLShader.h>
|
||||
//#include <gl/GLShaders.h>
|
||||
|
||||
using namespace gpu;
|
||||
using namespace gpu::gl;
|
||||
using namespace gpu::gl45;
|
||||
|
||||
// GLSL version
|
||||
std::string GL45Backend::getBackendShaderHeader() const {
|
||||
static const std::string header(
|
||||
R"SHADER(#version 450 core
|
||||
#define GPU_GL450
|
||||
#define BITFIELD int
|
||||
)SHADER"
|
||||
#ifdef GPU_SSBO_TRANSFORM_OBJECT
|
||||
R"SHADER(#define GPU_SSBO_TRANSFORM_OBJECT)SHADER"
|
||||
shader::Dialect GL45Backend::getShaderDialect() const {
|
||||
#if defined(Q_OS_MAC)
|
||||
// We build, but don't actually use GL 4.5 on OSX
|
||||
throw std::runtime_error("GL 4.5 unavailable on OSX");
|
||||
#else
|
||||
return shader::Dialect::glsl450;
|
||||
#endif
|
||||
);
|
||||
return header;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
set(TARGET_NAME gpu-gles)
|
||||
setup_hifi_library(Gui Concurrent)
|
||||
link_hifi_libraries(shared gl gpu gpu-gl-common)
|
||||
link_hifi_libraries(shared shaders gl gpu gpu-gl-common)
|
||||
GroupSources("src")
|
||||
target_opengl()
|
||||
|
|
|
@ -27,11 +27,7 @@ class GLESBackend : public GLBackend {
|
|||
friend class Context;
|
||||
|
||||
public:
|
||||
static const GLint TRANSFORM_OBJECT_SLOT { 31 };
|
||||
static const GLint RESOURCE_TRANSFER_TEX_UNIT { 32 };
|
||||
static const GLint RESOURCE_TRANSFER_EXTRA_TEX_UNIT { 33 };
|
||||
static const GLint RESOURCE_BUFFER_TEXBUF_TEX_UNIT { 34 };
|
||||
static const GLint RESOURCE_BUFFER_SLOT0_TEX_UNIT { 35 };
|
||||
explicit GLESBackend(bool syncCache) : Parent(syncCache) {}
|
||||
GLESBackend() : Parent() {}
|
||||
virtual ~GLESBackend() {
|
||||
|
@ -166,7 +162,7 @@ protected:
|
|||
// Output stage
|
||||
void do_blit(const Batch& batch, size_t paramOffset) override;
|
||||
|
||||
std::string getBackendShaderHeader() const override;
|
||||
shader::Dialect getShaderDialect() const override { return shader::Dialect::glsl310es; }
|
||||
};
|
||||
|
||||
} }
|
||||
|
|
|
@ -12,15 +12,3 @@ using namespace gpu;
|
|||
using namespace gpu::gl;
|
||||
using namespace gpu::gles;
|
||||
|
||||
// GLSL version
|
||||
std::string GLESBackend::getBackendShaderHeader() const {
|
||||
static const std::string header(
|
||||
R"SHADER(#version 310 es
|
||||
#extension GL_EXT_texture_buffer : enable
|
||||
precision highp float;
|
||||
precision highp samplerBuffer;
|
||||
precision highp sampler2DShadow;
|
||||
#define BITFIELD highp int
|
||||
)SHADER");
|
||||
return header;
|
||||
}
|
||||
|
|
|
@ -60,12 +60,11 @@ void GLESBackend::transferTransformState(const Batch& batch) const {
|
|||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + GLESBackend::TRANSFORM_OBJECT_SLOT);
|
||||
glActiveTexture(GL_TEXTURE0 + slot::texture::ObjectTransforms);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, _transform._objectBufferTexture);
|
||||
if (!batch._objects.empty()) {
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, _transform._objectBuffer);
|
||||
}
|
||||
|
||||
CHECK_GL_ERROR();
|
||||
|
||||
// Make sure the current Camera offset is unknown before render Draw
|
||||
|
|
|
@ -17,7 +17,7 @@ struct DrawColorParams {
|
|||
vec4 color;
|
||||
};
|
||||
|
||||
layout(binding=0) uniform drawColorParamsBuffer {
|
||||
LAYOUT(binding=0) uniform drawColorParamsBuffer {
|
||||
DrawColorParams params;
|
||||
};
|
||||
|
||||
|
|
|
@ -13,13 +13,13 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
layout(binding=0) uniform sampler2D colorMap;
|
||||
LAYOUT(binding=0) uniform sampler2D colorMap;
|
||||
|
||||
struct DrawColorParams {
|
||||
vec4 color;
|
||||
};
|
||||
|
||||
layout(binding=0) uniform drawColorParams {
|
||||
LAYOUT(binding=0) uniform drawColorParams {
|
||||
DrawColorParams params;
|
||||
};
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ struct TexCoordRectParams {
|
|||
vec4 texcoordRect;
|
||||
};
|
||||
|
||||
layout(binding=0) uniform texcoordRectBuffer {
|
||||
LAYOUT(binding=0) uniform texcoordRectBuffer {
|
||||
TexCoordRectParams params;
|
||||
};
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
//
|
||||
|
||||
|
||||
layout(binding=0) uniform sampler2D colorMap;
|
||||
LAYOUT(binding=0) uniform sampler2D colorMap;
|
||||
|
||||
layout(location=0) in vec2 varTexCoord0;
|
||||
layout(location=0) out vec4 outFragColor;
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
VERTEX DrawUnitQuadTexcoord
|
||||
FRAGMENT DrawTexture
|
|
@ -14,7 +14,7 @@
|
|||
//
|
||||
|
||||
|
||||
layout(binding=0) uniform sampler2D colorMap;
|
||||
LAYOUT(binding=0) uniform sampler2D colorMap;
|
||||
|
||||
layout(location=0) in vec2 varTexCoord0;
|
||||
layout(location=0) out vec4 outFragColor;
|
||||
|
|
1
libraries/gpu/src/gpu/DrawTextureMirroredX.slp
Normal file
1
libraries/gpu/src/gpu/DrawTextureMirroredX.slp
Normal file
|
@ -0,0 +1 @@
|
|||
VERTEX DrawUnitQuadTexcoord
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
<@include gpu/ShaderConstants.h@>
|
||||
|
||||
layout(binding=0) uniform sampler2D colorMap;
|
||||
LAYOUT(binding=0) uniform sampler2D colorMap;
|
||||
|
||||
layout(location=0) in vec2 varTexCoord0;
|
||||
|
||||
|
|
2
libraries/gpu/src/gpu/DrawTransformedTexture.slp
Normal file
2
libraries/gpu/src/gpu/DrawTransformedTexture.slp
Normal file
|
@ -0,0 +1,2 @@
|
|||
VERTEX DrawTransformUnitQuad
|
||||
FRAGMENT DrawTexture
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
<@include gpu/ShaderConstants.h@>
|
||||
|
||||
layout(binding=GPU_TEXTURE_MIP_CREATION_INPUT) uniform sampler2D texMap;
|
||||
LAYOUT(binding=GPU_TEXTURE_MIP_CREATION_INPUT) uniform sampler2D texMap;
|
||||
|
||||
in vec2 varTexCoord0;
|
||||
|
||||
|
|
|
@ -10,44 +10,49 @@
|
|||
//
|
||||
|
||||
#include "Shader.h"
|
||||
#include <math.h>
|
||||
#include <QDebug>
|
||||
#include <set>
|
||||
|
||||
#include <QtCore/QJsonDocument>
|
||||
#include <QtCore/QJsonObject>
|
||||
|
||||
#include <shaders/Shaders.h>
|
||||
|
||||
#include "Context.h"
|
||||
|
||||
using namespace gpu;
|
||||
|
||||
std::atomic<uint32_t> Shader::_nextShaderID( 1 );
|
||||
Shader::DomainShaderMaps Shader::_domainShaderMaps;
|
||||
Shader::ProgramMap Shader::_programMap;
|
||||
|
||||
|
||||
Shader::Shader(Type type, const Source& source) :
|
||||
_source(source),
|
||||
_type(type),
|
||||
_ID(_nextShaderID++)
|
||||
Shader::Shader(Type type, const Source& source, bool dynamic) :
|
||||
_type(type)
|
||||
{
|
||||
auto& thisSource = const_cast<Source&>(_source);
|
||||
thisSource = source;
|
||||
if (!dynamic) {
|
||||
thisSource.id = source.id;
|
||||
}
|
||||
}
|
||||
|
||||
Shader::Shader(Type type, const Pointer& vertex, const Pointer& geometry, const Pointer& pixel):
|
||||
_type(type),
|
||||
_ID(_nextShaderID++)
|
||||
Shader::Shader(Type type, const Pointer& vertex, const Pointer& geometry, const Pointer& pixel) :
|
||||
_type(type)
|
||||
{
|
||||
|
||||
auto& shaders = const_cast<Shaders&>(_shaders);
|
||||
if (geometry) {
|
||||
_shaders.resize(3);
|
||||
_shaders[VERTEX] = vertex;
|
||||
_shaders[GEOMETRY] = geometry;
|
||||
_shaders[PIXEL] = pixel;
|
||||
shaders.resize(3);
|
||||
shaders[VERTEX] = vertex;
|
||||
shaders[GEOMETRY] = geometry;
|
||||
shaders[PIXEL] = pixel;
|
||||
} else {
|
||||
_shaders.resize(2);
|
||||
_shaders[VERTEX] = vertex;
|
||||
_shaders[PIXEL] = pixel;
|
||||
shaders.resize(2);
|
||||
shaders[VERTEX] = vertex;
|
||||
shaders[PIXEL] = pixel;
|
||||
}
|
||||
|
||||
auto& reflection = const_cast<Reflection&>(getReflection());
|
||||
for (const auto& subShader : _shaders) {
|
||||
reflection.merge(subShader->getReflection());
|
||||
}
|
||||
if (_shaders[VERTEX]) {
|
||||
reflection.inputs = _shaders[VERTEX]->getReflection().inputs;
|
||||
}
|
||||
if (_shaders[PIXEL]) {
|
||||
reflection.outputs = _shaders[PIXEL]->getReflection().outputs;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,46 +60,27 @@ Shader::~Shader()
|
|||
{
|
||||
}
|
||||
|
||||
void populateSlotSet(Shader::SlotSet& slotSet, const Shader::LocationMap& map) {
|
||||
for (const auto& entry : map) {
|
||||
const auto& name = entry.first;
|
||||
const auto& location = entry.second;
|
||||
slotSet.insert({ name, location, Element() });
|
||||
}
|
||||
static std::unordered_map<uint32_t, std::weak_ptr<Shader>> _shaderCache;
|
||||
|
||||
Shader::ID Shader::getID() const {
|
||||
if (isProgram()) {
|
||||
return (_shaders[VERTEX]->getID() << 16) | (_shaders[PIXEL]->getID());
|
||||
}
|
||||
|
||||
return _source.id;
|
||||
}
|
||||
|
||||
Shader::Pointer Shader::createOrReuseDomainShader(Type type, const Source& source) {
|
||||
auto found = _domainShaderMaps[type].find(source);
|
||||
if (found != _domainShaderMaps[type].end()) {
|
||||
Shader::Pointer Shader::createOrReuseDomainShader(Type type, uint32_t sourceId) {
|
||||
// Don't attempt to cache non-static shaders
|
||||
auto found = _shaderCache.find(sourceId);
|
||||
if (found != _shaderCache.end()) {
|
||||
auto sharedShader = (*found).second.lock();
|
||||
if (sharedShader) {
|
||||
return sharedShader;
|
||||
}
|
||||
}
|
||||
auto shader = Pointer(new Shader(type, source));
|
||||
const auto& reflection = source.getReflection();
|
||||
if (0 != reflection.count(BindingType::INPUT)) {
|
||||
populateSlotSet(shader->_inputs, reflection.find(BindingType::INPUT)->second);
|
||||
}
|
||||
if (0 != reflection.count(BindingType::OUTPUT)) {
|
||||
populateSlotSet(shader->_outputs, reflection.find(BindingType::OUTPUT)->second);
|
||||
}
|
||||
if (0 != reflection.count(BindingType::UNIFORM_BUFFER)) {
|
||||
populateSlotSet(shader->_uniformBuffers, reflection.find(BindingType::UNIFORM_BUFFER)->second);
|
||||
}
|
||||
if (0 != reflection.count(BindingType::RESOURCE_BUFFER)) {
|
||||
populateSlotSet(shader->_resourceBuffers, reflection.find(BindingType::RESOURCE_BUFFER)->second);
|
||||
}
|
||||
if (0 != reflection.count(BindingType::TEXTURE)) {
|
||||
populateSlotSet(shader->_textures, reflection.find(BindingType::TEXTURE)->second);
|
||||
}
|
||||
if (0 != reflection.count(BindingType::SAMPLER)) {
|
||||
populateSlotSet(shader->_samplers, reflection.find(BindingType::SAMPLER)->second);
|
||||
}
|
||||
if (0 != reflection.count(BindingType::UNIFORM)) {
|
||||
populateSlotSet(shader->_uniforms, reflection.find(BindingType::UNIFORM)->second);
|
||||
}
|
||||
_domainShaderMaps[type].emplace(source, std::weak_ptr<Shader>(shader));
|
||||
auto shader = Pointer(new Shader(type, getShaderSource(sourceId), false));
|
||||
_shaderCache.insert({ sourceId, shader });
|
||||
return shader;
|
||||
}
|
||||
|
||||
|
@ -137,28 +123,6 @@ ShaderPointer Shader::createOrReuseProgramShader(Type type, const Pointer& verte
|
|||
|
||||
// Program is a new one, let's create it
|
||||
auto program = Pointer(new Shader(type, vertexShader, geometryShader, pixelShader));
|
||||
|
||||
// Combine the slots from the sub-shaders
|
||||
for (const auto& shader : program->_shaders) {
|
||||
const auto& reflection = shader->_source.getReflection();
|
||||
if (0 != reflection.count(BindingType::UNIFORM_BUFFER)) {
|
||||
populateSlotSet(program->_uniformBuffers, reflection.find(BindingType::UNIFORM_BUFFER)->second);
|
||||
}
|
||||
if (0 != reflection.count(BindingType::RESOURCE_BUFFER)) {
|
||||
populateSlotSet(program->_resourceBuffers, reflection.find(BindingType::RESOURCE_BUFFER)->second);
|
||||
}
|
||||
if (0 != reflection.count(BindingType::TEXTURE)) {
|
||||
populateSlotSet(program->_textures, reflection.find(BindingType::TEXTURE)->second);
|
||||
}
|
||||
if (0 != reflection.count(BindingType::SAMPLER)) {
|
||||
populateSlotSet(program->_samplers, reflection.find(BindingType::SAMPLER)->second);
|
||||
}
|
||||
if (0 != reflection.count(BindingType::UNIFORM)) {
|
||||
populateSlotSet(program->_uniforms, reflection.find(BindingType::UNIFORM)->second);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_programMap.emplace(key, std::weak_ptr<Shader>(program));
|
||||
return program;
|
||||
}
|
||||
|
@ -175,24 +139,21 @@ void Shader::incrementCompilationAttempt() const {
|
|||
}
|
||||
|
||||
Shader::Pointer Shader::createVertex(const Source& source) {
|
||||
return createOrReuseDomainShader(VERTEX, source);
|
||||
return Pointer(new Shader(VERTEX, source, true));
|
||||
}
|
||||
|
||||
Shader::Pointer Shader::createPixel(const Source& source) {
|
||||
return createOrReuseDomainShader(FRAGMENT, source);
|
||||
return Pointer(new Shader(FRAGMENT, source, true));
|
||||
}
|
||||
|
||||
Shader::Pointer Shader::createVertex(uint32_t id) {
|
||||
return createVertex(getShaderSource(id));
|
||||
return createOrReuseDomainShader(VERTEX, id);
|
||||
}
|
||||
|
||||
Shader::Pointer Shader::createPixel(uint32_t id) {
|
||||
return createPixel(getShaderSource(id));
|
||||
return createOrReuseDomainShader(FRAGMENT, id);
|
||||
}
|
||||
|
||||
Shader::Pointer Shader::createProgram(const Pointer& vertexShader, const Pointer& pixelShader) {
|
||||
return createOrReuseProgramShader(PROGRAM, vertexShader, nullptr, pixelShader);
|
||||
}
|
||||
|
||||
Shader::Pointer Shader::createProgram(uint32_t programId) {
|
||||
auto vertexShader = createVertex(shader::getVertexId(programId));
|
||||
|
@ -200,98 +161,15 @@ Shader::Pointer Shader::createProgram(uint32_t programId) {
|
|||
return createOrReuseProgramShader(PROGRAM, vertexShader, nullptr, fragmentShader);
|
||||
}
|
||||
|
||||
Shader::Pointer Shader::createProgram(const Pointer& vertexShader, const Pointer& pixelShader) {
|
||||
return Pointer(new Shader(PROGRAM, vertexShader, nullptr, pixelShader));
|
||||
}
|
||||
|
||||
// Dynamic program, bypass caching
|
||||
Shader::Pointer Shader::createProgram(const Pointer& vertexShader, const Pointer& geometryShader, const Pointer& pixelShader) {
|
||||
return createOrReuseProgramShader(PROGRAM, vertexShader, geometryShader, pixelShader);
|
||||
return Pointer(new Shader(PROGRAM, vertexShader, geometryShader, pixelShader));
|
||||
}
|
||||
|
||||
static const std::string IGNORED_BINDING = "transformObjectBuffer";
|
||||
|
||||
void updateBindingsFromJsonObject(Shader::LocationMap& inOutSet, const QJsonObject& json) {
|
||||
for (const auto& key : json.keys()) {
|
||||
auto keyStr = key.toStdString();
|
||||
if (IGNORED_BINDING == keyStr) {
|
||||
continue;
|
||||
}
|
||||
inOutSet[keyStr] = json[key].toInt();
|
||||
}
|
||||
}
|
||||
|
||||
void updateTextureAndResourceBuffersFromJsonObjects(Shader::LocationMap& inOutTextures, Shader::LocationMap& inOutResourceBuffers,
|
||||
const QJsonObject& json, const QJsonObject& types) {
|
||||
static const std::string RESOURCE_BUFFER_TEXTURE_TYPE = "samplerBuffer";
|
||||
for (const auto& key : json.keys()) {
|
||||
auto keyStr = key.toStdString();
|
||||
if (keyStr == IGNORED_BINDING) {
|
||||
continue;
|
||||
}
|
||||
auto location = json[key].toInt();
|
||||
auto type = types[key].toString().toStdString();
|
||||
if (type == RESOURCE_BUFFER_TEXTURE_TYPE) {
|
||||
inOutResourceBuffers[keyStr] = location;
|
||||
} else {
|
||||
inOutTextures[key.toStdString()] = location;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Shader::ReflectionMap getShaderReflection(const std::string& reflectionJson) {
|
||||
if (reflectionJson.empty() && reflectionJson != std::string("null")) {
|
||||
return {};
|
||||
}
|
||||
|
||||
#define REFLECT_KEY_INPUTS "inputs"
|
||||
#define REFLECT_KEY_OUTPUTS "outputs"
|
||||
#define REFLECT_KEY_UBOS "uniformBuffers"
|
||||
#define REFLECT_KEY_SSBOS "storageBuffers"
|
||||
#define REFLECT_KEY_UNIFORMS "uniforms"
|
||||
#define REFLECT_KEY_TEXTURES "textures"
|
||||
#define REFLECT_KEY_TEXTURE_TYPES "textureTypes"
|
||||
|
||||
auto doc = QJsonDocument::fromJson(reflectionJson.c_str());
|
||||
if (doc.isNull()) {
|
||||
qWarning() << "Invalid shader reflection JSON" << reflectionJson.c_str();
|
||||
return {};
|
||||
}
|
||||
|
||||
Shader::ReflectionMap result;
|
||||
auto json = doc.object();
|
||||
if (json.contains(REFLECT_KEY_INPUTS)) {
|
||||
updateBindingsFromJsonObject(result[Shader::BindingType::INPUT], json[REFLECT_KEY_INPUTS].toObject());
|
||||
}
|
||||
if (json.contains(REFLECT_KEY_OUTPUTS)) {
|
||||
updateBindingsFromJsonObject(result[Shader::BindingType::OUTPUT], json[REFLECT_KEY_OUTPUTS].toObject());
|
||||
}
|
||||
// FIXME eliminate the last of the uniforms
|
||||
if (json.contains(REFLECT_KEY_UNIFORMS)) {
|
||||
updateBindingsFromJsonObject(result[Shader::BindingType::UNIFORM], json[REFLECT_KEY_UNIFORMS].toObject());
|
||||
}
|
||||
if (json.contains(REFLECT_KEY_UBOS)) {
|
||||
updateBindingsFromJsonObject(result[Shader::BindingType::UNIFORM_BUFFER], json[REFLECT_KEY_UBOS].toObject());
|
||||
}
|
||||
|
||||
// SSBOs need to come BEFORE the textures. In GL 4.5 the reflection slots aren't really used, but in 4.1 the slots
|
||||
// are used to explicitly setup bindings after shader linkage, so we want the resource buffer slots to contain the
|
||||
// texture locations, not the SSBO locations
|
||||
if (json.contains(REFLECT_KEY_SSBOS)) {
|
||||
updateBindingsFromJsonObject(result[Shader::BindingType::RESOURCE_BUFFER], json[REFLECT_KEY_SSBOS].toObject());
|
||||
}
|
||||
|
||||
// samplerBuffer textures map to gpu ResourceBuffer, while all other textures map to regular gpu Texture
|
||||
if (json.contains(REFLECT_KEY_TEXTURES)) {
|
||||
updateTextureAndResourceBuffersFromJsonObjects(
|
||||
result[Shader::BindingType::TEXTURE],
|
||||
result[Shader::BindingType::RESOURCE_BUFFER],
|
||||
json[REFLECT_KEY_TEXTURES].toObject(),
|
||||
json[REFLECT_KEY_TEXTURE_TYPES].toObject());
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Shader::Source Shader::getShaderSource(uint32_t id) {
|
||||
auto source = shader::loadShaderSource(id);
|
||||
auto reflectionJson = shader::loadShaderReflection(id);
|
||||
auto reflection = getShaderReflection(reflectionJson);
|
||||
return { source, reflection };
|
||||
const Shader::Source& Shader::getShaderSource(uint32_t id) {
|
||||
return shader::Source::get(id);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <unordered_map>
|
||||
#include <map>
|
||||
#include <functional>
|
||||
#include <shaders/Shaders.h>
|
||||
#include <QUrl>
|
||||
|
||||
namespace gpu {
|
||||
|
@ -42,58 +43,10 @@ public:
|
|||
typedef std::shared_ptr<Shader> Pointer;
|
||||
typedef std::vector<Pointer> Shaders;
|
||||
|
||||
// Needs to match values in shaders/Shaders.h
|
||||
enum class BindingType
|
||||
{
|
||||
INVALID = -1,
|
||||
INPUT = 0,
|
||||
OUTPUT,
|
||||
TEXTURE,
|
||||
SAMPLER,
|
||||
UNIFORM_BUFFER,
|
||||
RESOURCE_BUFFER,
|
||||
UNIFORM,
|
||||
};
|
||||
|
||||
using LocationMap = std::unordered_map<std::string, int32_t>;
|
||||
using ReflectionMap = std::map<BindingType, LocationMap>;
|
||||
|
||||
class Source {
|
||||
public:
|
||||
enum Language
|
||||
{
|
||||
INVALID = -1,
|
||||
GLSL = 0,
|
||||
SPIRV = 1,
|
||||
MSL = 2,
|
||||
HLSL = 3,
|
||||
};
|
||||
|
||||
Source() {}
|
||||
Source(const std::string& code, const ReflectionMap& reflection, Language lang = GLSL) :
|
||||
_code(code), _reflection(reflection), _lang(lang) {}
|
||||
Source(const Source& source) : _code(source._code), _reflection(source._reflection), _lang(source._lang) {}
|
||||
virtual ~Source() {}
|
||||
|
||||
virtual const std::string& getCode() const { return _code; }
|
||||
virtual const ReflectionMap& getReflection() const { return _reflection; }
|
||||
|
||||
class Less {
|
||||
public:
|
||||
bool operator()(const Source& x, const Source& y) const {
|
||||
if (x._lang == y._lang) {
|
||||
return x._code < y._code;
|
||||
} else {
|
||||
return (x._lang < y._lang);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
protected:
|
||||
std::string _code;
|
||||
ReflectionMap _reflection;
|
||||
Language _lang;
|
||||
};
|
||||
using Source = shader::Source;
|
||||
using Reflection = shader::Reflection;
|
||||
using Dialect = shader::Dialect;
|
||||
using Variant = shader::Variant;
|
||||
|
||||
struct CompilationLog {
|
||||
std::string message;
|
||||
|
@ -112,85 +65,13 @@ public:
|
|||
bool operator()(const T& x, const T& y) const { return x._name < y._name; }
|
||||
};
|
||||
|
||||
class Slot {
|
||||
public:
|
||||
std::string _name;
|
||||
int32 _location{ INVALID_LOCATION };
|
||||
Element _element;
|
||||
uint16 _resourceType{ Resource::BUFFER };
|
||||
uint32 _size{ 0 };
|
||||
|
||||
Slot(const Slot& s) :
|
||||
_name(s._name), _location(s._location), _element(s._element), _resourceType(s._resourceType), _size(s._size) {}
|
||||
Slot(Slot&& s) :
|
||||
_name(s._name), _location(s._location), _element(s._element), _resourceType(s._resourceType), _size(s._size) {}
|
||||
Slot(const std::string& name,
|
||||
int32 location,
|
||||
const Element& element,
|
||||
uint16 resourceType = Resource::BUFFER,
|
||||
uint32 size = 0) :
|
||||
_name(name),
|
||||
_location(location), _element(element), _resourceType(resourceType), _size(size) {}
|
||||
Slot(const std::string& name) : _name(name) {}
|
||||
|
||||
Slot& operator=(const Slot& s) {
|
||||
_name = s._name;
|
||||
_location = s._location;
|
||||
_element = s._element;
|
||||
_resourceType = s._resourceType;
|
||||
_size = s._size;
|
||||
return (*this);
|
||||
}
|
||||
};
|
||||
|
||||
class SlotSet : protected std::set<Slot, Less<Slot>> {
|
||||
using Parent = std::set<Slot, Less<Slot>>;
|
||||
|
||||
public:
|
||||
void insert(const Parent::value_type& value) {
|
||||
Parent::insert(value);
|
||||
if (value._location != INVALID_LOCATION) {
|
||||
_validSlots.insert(value._location);
|
||||
}
|
||||
}
|
||||
|
||||
using Parent::begin;
|
||||
using Parent::empty;
|
||||
using Parent::end;
|
||||
using Parent::size;
|
||||
|
||||
using LocationMap = std::unordered_map<std::string, int32>;
|
||||
using NameVector = std::vector<std::string>;
|
||||
|
||||
NameVector getNames() const {
|
||||
NameVector result;
|
||||
for (const auto& entry : *this) {
|
||||
result.push_back(entry._name);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
LocationMap getLocationsByName() const {
|
||||
LocationMap result;
|
||||
for (const auto& entry : *this) {
|
||||
result.insert({ entry._name, entry._location });
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool isValid(int32 slot) const { return 0 != _validSlots.count(slot); }
|
||||
|
||||
protected:
|
||||
std::unordered_set<int> _validSlots;
|
||||
};
|
||||
|
||||
static Source getShaderSource(uint32_t id);
|
||||
static Source getVertexShaderSource(uint32_t id) { return getShaderSource(id); }
|
||||
static Source getFragmentShaderSource(uint32_t id) { return getShaderSource(id); }
|
||||
|
||||
static const Source& getShaderSource(uint32_t id);
|
||||
static const Source& getVertexShaderSource(uint32_t id) { return getShaderSource(id); }
|
||||
static const Source& getFragmentShaderSource(uint32_t id) { return getShaderSource(id); }
|
||||
static Pointer createVertex(const Source& source);
|
||||
static Pointer createPixel(const Source& source);
|
||||
static Pointer createGeometry(const Source& source);
|
||||
|
||||
static Pointer createVertex(uint32_t shaderId);
|
||||
static Pointer createPixel(uint32_t shaderId);
|
||||
static Pointer createGeometry(uint32_t shaderId);
|
||||
|
@ -201,8 +82,7 @@ public:
|
|||
|
||||
~Shader();
|
||||
|
||||
ID getID() const { return _ID; }
|
||||
|
||||
ID getID() const;
|
||||
Type getType() const { return _type; }
|
||||
bool isProgram() const { return getType() > NUM_DOMAINS; }
|
||||
bool isDomain() const { return getType() < NUM_DOMAINS; }
|
||||
|
@ -211,17 +91,12 @@ public:
|
|||
|
||||
const Shaders& getShaders() const { return _shaders; }
|
||||
|
||||
// Access the exposed uniform, input and output slot
|
||||
const SlotSet& getUniforms() const { return _uniforms; }
|
||||
const SlotSet& getUniformBuffers() const { return _uniformBuffers; }
|
||||
const SlotSet& getResourceBuffers() const { return _resourceBuffers; }
|
||||
const SlotSet& getTextures() const { return _textures; }
|
||||
const SlotSet& getSamplers() const { return _samplers; }
|
||||
const Reflection& getReflection() const { return _source.reflection; }
|
||||
|
||||
// Compilation Handler can be passed while compiling a shader (in the makeProgram call) to be able to give the hand to
|
||||
// the caller thread if the comilation fails and to prvide a different version of the source for it
|
||||
// the caller thread if the compilation fails and to provide a different version of the source for it
|
||||
// @param0 the Shader object that just failed to compile
|
||||
// @param1 the original source code as submited to the compiler
|
||||
// @param1 the original source code as submitted to the compiler
|
||||
// @param2 the compilation log containing the error message
|
||||
// @param3 a new string ready to be filled with the new version of the source that could be proposed from the handler functor
|
||||
// @return boolean true if the backend should keep trying to compile the shader with the new source returned or false to stop and fail that shader compilation
|
||||
|
@ -240,32 +115,21 @@ public:
|
|||
const GPUObjectPointer gpuObject{};
|
||||
|
||||
protected:
|
||||
Shader(Type type, const Source& source);
|
||||
Shader(Type type, const Source& source, bool dynamic);
|
||||
Shader(Type type, const Pointer& vertex, const Pointer& geometry, const Pointer& pixel);
|
||||
|
||||
Shader(const Shader& shader); // deep copy of the sysmem shader
|
||||
Shader& operator=(const Shader& shader); // deep copy of the sysmem texture
|
||||
|
||||
// Source contains the actual source code or nothing if the shader is a program
|
||||
Source _source;
|
||||
const Source _source;
|
||||
|
||||
// if shader is composed of sub shaders, here they are
|
||||
Shaders _shaders;
|
||||
|
||||
// List of exposed uniform, input and output slots
|
||||
SlotSet _uniforms;
|
||||
SlotSet _uniformBuffers;
|
||||
SlotSet _resourceBuffers;
|
||||
SlotSet _textures;
|
||||
SlotSet _samplers;
|
||||
SlotSet _inputs;
|
||||
SlotSet _outputs;
|
||||
const Shaders _shaders;
|
||||
|
||||
|
||||
// The type of the shader, the master key
|
||||
Type _type;
|
||||
|
||||
// The unique identifier of a shader in the GPU lib
|
||||
uint32_t _ID{ 0 };
|
||||
const Type _type;
|
||||
|
||||
// Number of attempts to compile the shader
|
||||
mutable uint32_t _numCompilationAttempts{ 0 };
|
||||
|
@ -277,13 +141,9 @@ protected:
|
|||
|
||||
// Global maps of the shaders
|
||||
// Unique shader ID
|
||||
static std::atomic<ID> _nextShaderID;
|
||||
//static std::atomic<ID> _nextShaderID;
|
||||
|
||||
using ShaderMap = std::map<Source, std::weak_ptr<Shader>, Source::Less>;
|
||||
using DomainShaderMaps = std::array<ShaderMap, NUM_DOMAINS>;
|
||||
static DomainShaderMaps _domainShaderMaps;
|
||||
|
||||
static ShaderPointer createOrReuseDomainShader(Type type, const Source& source);
|
||||
static ShaderPointer createOrReuseDomainShader(Type type, uint32_t sourceId);
|
||||
|
||||
using ProgramMapKey = glm::uvec3; // The IDs of the shaders in a program make its key
|
||||
class ProgramKeyLess {
|
||||
|
|
|
@ -98,21 +98,6 @@ enum Attribute {
|
|||
};
|
||||
} // namespace attr
|
||||
|
||||
namespace uniform {
|
||||
enum Uniform {
|
||||
Extra0 = GPU_UNIFORM_EXTRA0,
|
||||
Extra1 = GPU_UNIFORM_EXTRA1,
|
||||
Extra2 = GPU_UNIFORM_EXTRA2,
|
||||
Extra3 = GPU_UNIFORM_EXTRA3,
|
||||
Extra4 = GPU_UNIFORM_EXTRA4,
|
||||
Extra5 = GPU_UNIFORM_EXTRA5,
|
||||
Extra6 = GPU_UNIFORM_EXTRA6,
|
||||
Extra7 = GPU_UNIFORM_EXTRA7,
|
||||
Extra8 = GPU_UNIFORM_EXTRA8,
|
||||
Extra9 = GPU_UNIFORM_EXTRA9,
|
||||
};
|
||||
} // namespace uniform
|
||||
|
||||
} } // namespace gpu::slot
|
||||
|
||||
// !>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#define TransformCamera _TransformCamera
|
||||
|
||||
layout(std140, binding=GPU_BUFFER_TRANSFORM_CAMERA) uniform transformCameraBuffer {
|
||||
LAYOUT_STD140(binding=GPU_BUFFER_TRANSFORM_CAMERA) uniform transformCameraBuffer {
|
||||
#ifdef GPU_TRANSFORM_IS_STEREO
|
||||
#ifdef GPU_TRANSFORM_STEREO_CAMERA
|
||||
TransformCamera _camera[2];
|
||||
|
@ -26,7 +26,7 @@ layout(std140, binding=GPU_BUFFER_TRANSFORM_CAMERA) uniform transformCameraBuffe
|
|||
#else
|
||||
TransformCamera _camera;
|
||||
#endif
|
||||
};
|
||||
} _cameraBlock;
|
||||
|
||||
#ifdef GPU_VERTEX_SHADER
|
||||
#ifdef GPU_TRANSFORM_IS_STEREO
|
||||
|
@ -76,12 +76,12 @@ TransformCamera getTransformCamera() {
|
|||
_stereoSide = gl_InstanceID % 2;
|
||||
#endif
|
||||
#endif
|
||||
return _camera[_stereoSide];
|
||||
return _cameraBlock._camera[_stereoSide];
|
||||
#else
|
||||
return _camera;
|
||||
return _cameraBlock._camera;
|
||||
#endif
|
||||
#else
|
||||
return _camera;
|
||||
return _cameraBlock._camera;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ bool cam_isStereo() {
|
|||
#ifdef GPU_TRANSFORM_IS_STEREO
|
||||
return getTransformCamera()._stereoInfo.x > 0.0;
|
||||
#else
|
||||
return _camera._stereoInfo.x > 0.0;
|
||||
return _cameraBlock._camera._stereoInfo.x > 0.0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -102,10 +102,10 @@ float cam_getStereoSide() {
|
|||
#ifdef GPU_TRANSFORM_STEREO_CAMERA
|
||||
return getTransformCamera()._stereoInfo.y;
|
||||
#else
|
||||
return _camera._stereoInfo.y;
|
||||
return _cameraBlock._camera._stereoInfo.y;
|
||||
#endif
|
||||
#else
|
||||
return _camera._stereoInfo.y;
|
||||
return _cameraBlock._camera._stereoInfo.y;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -120,7 +120,7 @@ struct TransformObject {
|
|||
layout(location=GPU_ATTR_DRAW_CALL_INFO) in ivec2 _drawCallInfo;
|
||||
|
||||
#if defined(GPU_SSBO_TRANSFORM_OBJECT)
|
||||
layout(std140, binding=GPU_STORAGE_TRANSFORM_OBJECT) buffer transformObjectBuffer {
|
||||
LAYOUT_STD140(binding=GPU_STORAGE_TRANSFORM_OBJECT) buffer transformObjectBuffer {
|
||||
TransformObject _object[];
|
||||
};
|
||||
TransformObject getTransformObject() {
|
||||
|
@ -128,7 +128,7 @@ TransformObject getTransformObject() {
|
|||
return transformObject;
|
||||
}
|
||||
#else
|
||||
layout(binding=GPU_TEXTURE_TRANSFORM_OBJECT) uniform samplerBuffer transformObjectBuffer;
|
||||
LAYOUT(binding=GPU_TEXTURE_TRANSFORM_OBJECT) uniform samplerBuffer transformObjectBuffer;
|
||||
|
||||
TransformObject getTransformObject() {
|
||||
int offset = 8 * _drawCallInfo.x;
|
||||
|
@ -167,7 +167,9 @@ TransformObject getTransformObject() {
|
|||
vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));
|
||||
vec2 eyeOffsetScale = vec2(-0.5, +0.5);
|
||||
uint eyeIndex = uint(_stereoSide);
|
||||
#ifndef GPU_GLES
|
||||
gl_ClipDistance[0] = dot(<$clipPos$>, eyeClipEdge[eyeIndex]);
|
||||
#endif
|
||||
float newClipPosX = <$clipPos$>.x * 0.5 + eyeOffsetScale[eyeIndex] * <$clipPos$>.w;
|
||||
<$clipPos$>.x = newClipPosX;
|
||||
#endif
|
||||
|
|
|
@ -51,7 +51,7 @@ float getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }
|
|||
|
||||
|
||||
<@if N@>
|
||||
layout(binding=GRAPHICS_BUFFER_LIGHT) uniform lightBuffer {
|
||||
LAYOUT(binding=GRAPHICS_BUFFER_LIGHT) uniform lightBuffer {
|
||||
Light lightArray[<$N$>];
|
||||
};
|
||||
Light getLight(int index) {
|
||||
|
@ -59,7 +59,7 @@ Light getLight(int index) {
|
|||
}
|
||||
|
||||
<@else@>
|
||||
layout(binding=GRAPHICS_BUFFER_KEY_LIGHT) uniform keyLightBuffer {
|
||||
LAYOUT(binding=GRAPHICS_BUFFER_KEY_LIGHT) uniform keyLightBuffer {
|
||||
Light light;
|
||||
};
|
||||
Light getKeyLight() {
|
||||
|
@ -79,7 +79,7 @@ Light getKeyLight() {
|
|||
|
||||
<@if N@>
|
||||
|
||||
layout(binding=GRAPHICS_BUFFER_AMBIENT_LIGHT) uniform lightAmbientBuffer {
|
||||
LAYOUT(binding=GRAPHICS_BUFFER_AMBIENT_LIGHT) uniform lightAmbientBuffer {
|
||||
LightAmbient lightAmbientArray[<$N$>];
|
||||
};
|
||||
|
||||
|
@ -88,7 +88,7 @@ LightAmbient getLightAmbient(int index) {
|
|||
}
|
||||
|
||||
<@else@>
|
||||
layout(binding=GRAPHICS_BUFFER_AMBIENT_LIGHT) uniform lightAmbientBuffer {
|
||||
LAYOUT(binding=GRAPHICS_BUFFER_AMBIENT_LIGHT) uniform lightAmbientBuffer {
|
||||
LightAmbient lightAmbient;
|
||||
};
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ struct Material {
|
|||
vec4 _scatteringSpare2Key;
|
||||
};
|
||||
|
||||
layout(binding=GRAPHICS_BUFFER_MATERIAL) uniform materialBuffer {
|
||||
LAYOUT(binding=GRAPHICS_BUFFER_MATERIAL) uniform materialBuffer {
|
||||
Material _mat;
|
||||
TexMapArray _texMapArray;
|
||||
};
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
<@if not MODEL_MATERIAL_TEXTURES_SLH@>
|
||||
<@def MODEL_MATERIAL_TEXTURES_SLH@>
|
||||
|
||||
<@include graphics/ShaderConstants.h@>
|
||||
<@include graphics/Material.slh@>
|
||||
|
||||
<@func declareMaterialTextures(withAlbedo, withRoughness, withNormal, withMetallic, withEmissive, withOcclusion, withScattering)@>
|
||||
|
@ -91,21 +92,21 @@ float fetchScatteringMap(vec2 uv) {
|
|||
#else
|
||||
|
||||
<@if withAlbedo@>
|
||||
layout(binding=GRAPHICS_TEXTURE_MATERIAL_ALBEDO) uniform sampler2D albedoMap;
|
||||
LAYOUT(binding=GRAPHICS_TEXTURE_MATERIAL_ALBEDO) uniform sampler2D albedoMap;
|
||||
vec4 fetchAlbedoMap(vec2 uv) {
|
||||
return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);
|
||||
}
|
||||
<@endif@>
|
||||
|
||||
<@if withRoughness@>
|
||||
layout(binding=GRAPHICS_TEXTURE_MATERIAL_ROUGHNESS) uniform sampler2D roughnessMap;
|
||||
LAYOUT(binding=GRAPHICS_TEXTURE_MATERIAL_ROUGHNESS) uniform sampler2D roughnessMap;
|
||||
float fetchRoughnessMap(vec2 uv) {
|
||||
return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);
|
||||
}
|
||||
<@endif@>
|
||||
|
||||
<@if withNormal@>
|
||||
layout(binding=GRAPHICS_TEXTURE_MATERIAL_NORMAL) uniform sampler2D normalMap;
|
||||
LAYOUT(binding=GRAPHICS_TEXTURE_MATERIAL_NORMAL) uniform sampler2D normalMap;
|
||||
vec3 fetchNormalMap(vec2 uv) {
|
||||
// unpack normal, swizzle to get into hifi tangent space with Y axis pointing out
|
||||
vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));
|
||||
|
@ -115,28 +116,28 @@ vec3 fetchNormalMap(vec2 uv) {
|
|||
<@endif@>
|
||||
|
||||
<@if withMetallic@>
|
||||
layout(binding=GRAPHICS_TEXTURE_MATERIAL_METALLIC) uniform sampler2D metallicMap;
|
||||
LAYOUT(binding=GRAPHICS_TEXTURE_MATERIAL_METALLIC) uniform sampler2D metallicMap;
|
||||
float fetchMetallicMap(vec2 uv) {
|
||||
return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);
|
||||
}
|
||||
<@endif@>
|
||||
|
||||
<@if withEmissive@>
|
||||
layout(binding=GRAPHICS_TEXTURE_MATERIAL_EMISSIVE_LIGHTMAP) uniform sampler2D emissiveMap;
|
||||
LAYOUT(binding=GRAPHICS_TEXTURE_MATERIAL_EMISSIVE_LIGHTMAP) uniform sampler2D emissiveMap;
|
||||
vec3 fetchEmissiveMap(vec2 uv) {
|
||||
return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;
|
||||
}
|
||||
<@endif@>
|
||||
|
||||
<@if withOcclusion@>
|
||||
layout(binding=GRAPHICS_TEXTURE_MATERIAL_OCCLUSION) uniform sampler2D occlusionMap;
|
||||
LAYOUT(binding=GRAPHICS_TEXTURE_MATERIAL_OCCLUSION) uniform sampler2D occlusionMap;
|
||||
float fetchOcclusionMap(vec2 uv) {
|
||||
return texture(occlusionMap, uv).r;
|
||||
}
|
||||
<@endif@>
|
||||
|
||||
<@if withScattering@>
|
||||
layout(binding=GRAPHICS_TEXTURE_MATERIAL_SCATTERING) uniform sampler2D scatteringMap;
|
||||
LAYOUT(binding=GRAPHICS_TEXTURE_MATERIAL_SCATTERING) uniform sampler2D scatteringMap;
|
||||
float fetchScatteringMap(vec2 uv) {
|
||||
float scattering = texture(scatteringMap, uv, TAA_TEXTURE_LOD_BIAS).r; // boolean scattering for now
|
||||
return max(((scattering - 0.1) / 0.9), 0.0);
|
||||
|
@ -185,7 +186,7 @@ float fetchScatteringMap(vec2 uv) {
|
|||
|
||||
<$declareMaterialTexMapArrayBuffer()$>
|
||||
|
||||
layout(binding=GRAPHICS_TEXTURE_MATERIAL_EMISSIVE_LIGHTMAP) uniform sampler2D emissiveMap;
|
||||
LAYOUT(binding=GRAPHICS_TEXTURE_MATERIAL_EMISSIVE_LIGHTMAP) uniform sampler2D emissiveMap;
|
||||
vec3 fetchLightmapMap(vec2 uv) {
|
||||
vec2 lightmapParams = getTexMapArray()._lightmapParams.xy;
|
||||
return (vec3(lightmapParams.x) + lightmapParams.y * texture(emissiveMap, uv).rgb);
|
||||
|
|
|
@ -12,13 +12,13 @@
|
|||
//
|
||||
<@include graphics/ShaderConstants.h@>
|
||||
|
||||
layout(binding=GRAPHICS_TEXTURE_SKYBOX) uniform samplerCube cubeMap;
|
||||
LAYOUT(binding=GRAPHICS_TEXTURE_SKYBOX) uniform samplerCube cubeMap;
|
||||
|
||||
struct Skybox {
|
||||
vec4 color;
|
||||
};
|
||||
|
||||
layout(binding=GRAPHICS_BUFFER_SKYBOX_PARAMS) uniform skyboxBuffer {
|
||||
LAYOUT(binding=GRAPHICS_BUFFER_SKYBOX_PARAMS) uniform skyboxBuffer {
|
||||
Skybox skybox;
|
||||
};
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue