mirror of
https://github.com/lubosz/overte.git
synced 2025-04-17 20:50:27 +02:00
Merge branch 'master' into feature/ant-man
This commit is contained in:
commit
b81f85e1ae
47 changed files with 1684 additions and 490 deletions
309
CMakeLists.txt
309
CMakeLists.txt
|
@ -4,254 +4,81 @@ else()
|
|||
cmake_minimum_required(VERSION 3.2)
|
||||
endif()
|
||||
|
||||
if (USE_ANDROID_TOOLCHAIN)
|
||||
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/android/android.toolchain.cmake")
|
||||
set(ANDROID_NATIVE_API_LEVEL 19)
|
||||
set(ANDROID_TOOLCHAIN_NAME arm-linux-androideabi-clang3.5)
|
||||
set(ANDROID_STL c++_shared)
|
||||
endif ()
|
||||
|
||||
if (WIN32)
|
||||
cmake_policy(SET CMP0020 NEW)
|
||||
endif (WIN32)
|
||||
|
||||
if (POLICY CMP0043)
|
||||
cmake_policy(SET CMP0043 OLD)
|
||||
endif ()
|
||||
|
||||
if (POLICY CMP0042)
|
||||
cmake_policy(SET CMP0042 OLD)
|
||||
endif ()
|
||||
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMakeTargets")
|
||||
include("cmake/init.cmake")
|
||||
|
||||
project(hifi)
|
||||
add_definitions(-DGLM_FORCE_RADIANS)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
|
||||
|
||||
find_package( Threads )
|
||||
include("cmake/compiler.cmake")
|
||||
|
||||
if (WIN32)
|
||||
if (NOT "${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
|
||||
message( FATAL_ERROR "Only 64 bit builds supported." )
|
||||
endif()
|
||||
|
||||
add_definitions(-DNOMINMAX -D_CRT_SECURE_NO_WARNINGS)
|
||||
|
||||
if (NOT WINDOW_SDK_PATH)
|
||||
set(DEBUG_DISCOVERED_SDK_PATH TRUE)
|
||||
endif()
|
||||
|
||||
# sets path for Microsoft SDKs
|
||||
# if you get build error about missing 'glu32' this path is likely wrong
|
||||
if (MSVC_VERSION GREATER_EQUAL 1910) # VS 2017
|
||||
set(WINDOW_SDK_PATH "C:/Program Files (x86)/Windows Kits/10/Lib/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}/x64" CACHE PATH "Windows SDK PATH")
|
||||
elseif (MSVC_VERSION GREATER_EQUAL 1800) # VS 2013
|
||||
set(WINDOW_SDK_PATH "C:\\Program Files (x86)\\Windows Kits\\8.1\\Lib\\winv6.3\\um\\${WINDOW_SDK_FOLDER}" CACHE PATH "Windows SDK PATH")
|
||||
else()
|
||||
message( FATAL_ERROR "Visual Studio 2013 or higher required." )
|
||||
endif()
|
||||
|
||||
if (DEBUG_DISCOVERED_SDK_PATH)
|
||||
message(STATUS "The discovered Windows SDK path is ${WINDOW_SDK_PATH}")
|
||||
endif ()
|
||||
|
||||
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${WINDOW_SDK_PATH})
|
||||
# /wd4351 disables warning C4351: new behavior: elements of array will be default initialized
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /wd4351")
|
||||
# /LARGEADDRESSAWARE enables 32-bit apps to use more than 2GB of memory.
|
||||
# Caveats: http://stackoverflow.com/questions/2288728/drawbacks-of-using-largeaddressaware-for-32-bit-windows-executables
|
||||
# TODO: Remove when building 64-bit.
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LARGEADDRESSAWARE")
|
||||
# always produce symbols as PDB files
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zi")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUG /OPT:REF /OPT:ICF")
|
||||
else ()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -fno-strict-aliasing -Wno-unused-parameter")
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ggdb -Woverloaded-virtual -Wdouble-promotion")
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "5.1") # gcc 5.1 and on have suggest-override
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-override")
|
||||
endif ()
|
||||
endif ()
|
||||
endif(WIN32)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.3")
|
||||
# GLM 0.9.8 on Ubuntu 14 (gcc 4.4) has issues with the simd declarations
|
||||
add_definitions(-DGLM_FORCE_PURE)
|
||||
endif()
|
||||
if (NOT DEFINED SERVER_ONLY)
|
||||
set(SERVER_ONLY 0)
|
||||
endif()
|
||||
|
||||
if (NOT ANDROID)
|
||||
if ((NOT MSVC12) AND (NOT MSVC14))
|
||||
include(CheckCXXCompilerFlag)
|
||||
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
|
||||
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
|
||||
|
||||
if (COMPILER_SUPPORTS_CXX11)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
elseif(COMPILER_SUPPORTS_CXX0X)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
|
||||
else()
|
||||
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
|
||||
endif()
|
||||
endif ()
|
||||
else ()
|
||||
# assume that the toolchain selected for android has C++11 support
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
endif ()
|
||||
|
||||
if (APPLE)
|
||||
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++11")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --stdlib=libc++")
|
||||
endif ()
|
||||
|
||||
if (NOT ANDROID_LIB_DIR)
|
||||
set(ANDROID_LIB_DIR $ENV{ANDROID_LIB_DIR})
|
||||
endif ()
|
||||
|
||||
if (ANDROID)
|
||||
if (NOT ANDROID_QT_CMAKE_PREFIX_PATH)
|
||||
set(QT_CMAKE_PREFIX_PATH ${ANDROID_LIB_DIR}/Qt/5.5/android_armv7/lib/cmake)
|
||||
else ()
|
||||
set(QT_CMAKE_PREFIX_PATH ${ANDROID_QT_CMAKE_PREFIX_PATH})
|
||||
endif ()
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib)
|
||||
|
||||
if (ANDROID_LIB_DIR)
|
||||
list(APPEND CMAKE_FIND_ROOT_PATH ${ANDROID_LIB_DIR})
|
||||
endif ()
|
||||
else ()
|
||||
if (NOT QT_CMAKE_PREFIX_PATH)
|
||||
set(QT_CMAKE_PREFIX_PATH $ENV{QT_CMAKE_PREFIX_PATH})
|
||||
endif ()
|
||||
if (NOT QT_CMAKE_PREFIX_PATH)
|
||||
get_filename_component(QT_CMAKE_PREFIX_PATH "${Qt5_DIR}/.." REALPATH)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
set(QT_DIR $ENV{QT_DIR})
|
||||
|
||||
if (WIN32)
|
||||
if (NOT EXISTS ${QT_CMAKE_PREFIX_PATH})
|
||||
message(FATAL_ERROR "Could not determine QT_CMAKE_PREFIX_PATH.")
|
||||
endif ()
|
||||
if (ANDROID OR UWP)
|
||||
set(MOBILE 1)
|
||||
else()
|
||||
set(MOBILE 0)
|
||||
endif()
|
||||
|
||||
# figure out where the qt dir is
|
||||
get_filename_component(QT_DIR "${QT_CMAKE_PREFIX_PATH}/../../" ABSOLUTE)
|
||||
if (ANDROID OR UWP)
|
||||
option(BUILD_SERVER "Build server components" OFF)
|
||||
option(BUILD_TOOLS "Build tools" OFF)
|
||||
else()
|
||||
option(BUILD_SERVER "Build server components" ON)
|
||||
option(BUILD_TOOLS "Build tools" ON)
|
||||
endif()
|
||||
|
||||
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${QT_CMAKE_PREFIX_PATH})
|
||||
if (SERVER_ONLY)
|
||||
option(BUILD_CLIENT "Build client components" OFF)
|
||||
option(BUILD_TESTS "Build tests" OFF)
|
||||
else()
|
||||
option(BUILD_CLIENT "Build client components" ON)
|
||||
option(BUILD_TESTS "Build tests" ON)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
option(BUILD_INSTALLER "Build installer" ON)
|
||||
|
||||
exec_program(sw_vers ARGS -productVersion OUTPUT_VARIABLE OSX_VERSION)
|
||||
string(REGEX MATCH "^[0-9]+\\.[0-9]+" OSX_VERSION ${OSX_VERSION})
|
||||
message(STATUS "Detected OS X version = ${OSX_VERSION}")
|
||||
MESSAGE(STATUS "Build server: " ${BUILD_SERVER})
|
||||
MESSAGE(STATUS "Build client: " ${BUILD_CLIENT})
|
||||
MESSAGE(STATUS "Build tests: " ${BUILD_TESTS})
|
||||
MESSAGE(STATUS "Build tools: " ${BUILD_TOOLS})
|
||||
MESSAGE(STATUS "Build installer: " ${BUILD_INSTALLER})
|
||||
|
||||
set(OSX_SDK "${OSX_VERSION}" CACHE String "OS X SDK version to look for inside Xcode bundle or at OSX_SDK_PATH")
|
||||
if (UNIX AND DEFINED ENV{HIFI_MEMORY_DEBUGGING})
|
||||
MESSAGE(STATUS "Memory debugging is enabled")
|
||||
endif()
|
||||
|
||||
# set our OS X deployment target
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.8)
|
||||
|
||||
# find the SDK path for the desired SDK
|
||||
find_path(
|
||||
_OSX_DESIRED_SDK_PATH
|
||||
NAME MacOSX${OSX_SDK}.sdk
|
||||
HINTS ${OSX_SDK_PATH}
|
||||
PATHS /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/
|
||||
/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/
|
||||
)
|
||||
|
||||
if (NOT _OSX_DESIRED_SDK_PATH)
|
||||
message(STATUS "Could not find OS X ${OSX_SDK} SDK. Will fall back to default. If you want a specific SDK, please pass OSX_SDK and optionally OSX_SDK_PATH to CMake.")
|
||||
else ()
|
||||
message(STATUS "Found OS X ${OSX_SDK} SDK at ${_OSX_DESIRED_SDK_PATH}/MacOSX${OSX_SDK}.sdk")
|
||||
|
||||
# set that as the SDK to use
|
||||
set(CMAKE_OSX_SYSROOT ${_OSX_DESIRED_SDK_PATH}/MacOSX${OSX_SDK}.sdk)
|
||||
endif ()
|
||||
|
||||
endif ()
|
||||
|
||||
# Hide automoc folders (for IDEs)
|
||||
set(AUTOGEN_TARGETS_FOLDER "hidden/generated")
|
||||
|
||||
# Find includes in corresponding build directories
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
# Instruct CMake to run moc automatically when needed.
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
# Instruct CMake to run rcc automatically when needed
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
set(HIFI_LIBRARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libraries")
|
||||
|
||||
# setup for find modules
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/")
|
||||
|
||||
if (CMAKE_BUILD_TYPE)
|
||||
string(TOUPPER ${CMAKE_BUILD_TYPE} UPPER_CMAKE_BUILD_TYPE)
|
||||
else ()
|
||||
set(UPPER_CMAKE_BUILD_TYPE DEBUG)
|
||||
endif ()
|
||||
|
||||
set(HF_CMAKE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
set(MACRO_DIR "${HF_CMAKE_DIR}/macros")
|
||||
set(EXTERNAL_PROJECT_DIR "${HF_CMAKE_DIR}/externals")
|
||||
|
||||
file(GLOB HIFI_CUSTOM_MACROS "cmake/macros/*.cmake")
|
||||
foreach(CUSTOM_MACRO ${HIFI_CUSTOM_MACROS})
|
||||
include(${CUSTOM_MACRO})
|
||||
endforeach()
|
||||
#
|
||||
# Helper projects
|
||||
#
|
||||
file(GLOB_RECURSE CMAKE_SRC cmake/*.cmake cmake/CMakeLists.txt)
|
||||
add_custom_target(cmake SOURCES ${CMAKE_SRC})
|
||||
GroupSources("cmake")
|
||||
|
||||
file(GLOB_RECURSE JS_SRC scripts/*.js unpublishedScripts/*.js)
|
||||
add_custom_target(js SOURCES ${JS_SRC})
|
||||
GroupSources("scripts")
|
||||
GroupSources("unpublishedScripts")
|
||||
|
||||
if (UNIX)
|
||||
install(
|
||||
DIRECTORY "${CMAKE_SOURCE_DIR}/scripts"
|
||||
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/interface
|
||||
COMPONENT ${CLIENT_COMPONENT}
|
||||
)
|
||||
endif()
|
||||
# Locate the required Qt build on the filesystem
|
||||
setup_qt()
|
||||
list(APPEND CMAKE_PREFIX_PATH "${QT_CMAKE_PREFIX_PATH}")
|
||||
|
||||
if (ANDROID)
|
||||
file(GLOB ANDROID_CUSTOM_MACROS "cmake/android/*.cmake")
|
||||
foreach(CUSTOM_MACRO ${ANDROID_CUSTOM_MACROS})
|
||||
include(${CUSTOM_MACRO})
|
||||
endforeach()
|
||||
endif ()
|
||||
find_package( Threads )
|
||||
|
||||
add_definitions(-DGLM_FORCE_RADIANS)
|
||||
set(HIFI_LIBRARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libraries")
|
||||
|
||||
set(EXTERNAL_PROJECT_PREFIX "project")
|
||||
set_property(DIRECTORY PROPERTY EP_PREFIX ${EXTERNAL_PROJECT_PREFIX})
|
||||
setup_externals_binary_dir()
|
||||
|
||||
option(USE_NSIGHT "Attempt to find the nSight libraries" 1)
|
||||
option(GET_QUAZIP "Get QuaZip library automatically as external project" 1)
|
||||
|
||||
|
||||
if (WIN32)
|
||||
add_paths_to_fixup_libs("${QT_DIR}/bin")
|
||||
endif ()
|
||||
|
||||
if (NOT DEFINED SERVER_ONLY)
|
||||
set(SERVER_ONLY 0)
|
||||
endif()
|
||||
|
||||
set_packaging_parameters()
|
||||
|
||||
option(BUILD_TESTS "Build tests" ON)
|
||||
MESSAGE(STATUS "Build tests: " ${BUILD_TESTS})
|
||||
|
||||
# add subdirectories for all targets
|
||||
if (NOT ANDROID)
|
||||
if (BUILD_SERVER)
|
||||
add_subdirectory(assignment-client)
|
||||
set_target_properties(assignment-client PROPERTIES FOLDER "Apps")
|
||||
add_subdirectory(domain-server)
|
||||
|
@ -259,30 +86,36 @@ if (NOT ANDROID)
|
|||
add_subdirectory(ice-server)
|
||||
set_target_properties(ice-server PROPERTIES FOLDER "Apps")
|
||||
add_subdirectory(server-console)
|
||||
if (NOT SERVER_ONLY)
|
||||
endif()
|
||||
|
||||
if (BUILD_CLIENT)
|
||||
add_subdirectory(interface)
|
||||
set_target_properties(interface PROPERTIES FOLDER "Apps")
|
||||
if (BUILD_TESTS)
|
||||
add_subdirectory(tests)
|
||||
if (ANDROID)
|
||||
add_subdirectory(gvr-interface)
|
||||
set_target_properties(gvr-interface PROPERTIES FOLDER "Apps")
|
||||
endif()
|
||||
endif()
|
||||
add_subdirectory(plugins)
|
||||
endif()
|
||||
|
||||
if (BUILD_CLIENT OR BUILD_SERVER)
|
||||
add_subdirectory(plugins)
|
||||
endif()
|
||||
|
||||
if (BUILD_TOOLS)
|
||||
add_subdirectory(tools)
|
||||
endif()
|
||||
|
||||
if (ANDROID OR DESKTOP_GVR)
|
||||
add_subdirectory(interface)
|
||||
add_subdirectory(gvr-interface)
|
||||
add_subdirectory(plugins)
|
||||
endif ()
|
||||
if (BUILD_TESTS)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
if (DEFINED ENV{HIFI_MEMORY_DEBUGGING})
|
||||
SET( HIFI_MEMORY_DEBUGGING true )
|
||||
endif ()
|
||||
if (HIFI_MEMORY_DEBUGGING)
|
||||
if (UNIX)
|
||||
MESSAGE("-- Memory debugging is enabled")
|
||||
endif (UNIX)
|
||||
endif ()
|
||||
|
||||
generate_installers()
|
||||
if (BUILD_INSTALLER)
|
||||
if (UNIX)
|
||||
install(
|
||||
DIRECTORY "${CMAKE_SOURCE_DIR}/scripts"
|
||||
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/interface
|
||||
COMPONENT ${CLIENT_COMPONENT}
|
||||
)
|
||||
endif()
|
||||
generate_installers()
|
||||
endif()
|
||||
|
|
106
cmake/compiler.cmake
Normal file
106
cmake/compiler.cmake
Normal file
|
@ -0,0 +1,106 @@
|
|||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
|
||||
|
||||
if (WIN32)
|
||||
if (NOT "${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
|
||||
message( FATAL_ERROR "Only 64 bit builds supported." )
|
||||
endif()
|
||||
|
||||
add_definitions(-DNOMINMAX -D_CRT_SECURE_NO_WARNINGS)
|
||||
|
||||
if (NOT WINDOW_SDK_PATH)
|
||||
set(DEBUG_DISCOVERED_SDK_PATH TRUE)
|
||||
endif()
|
||||
|
||||
# sets path for Microsoft SDKs
|
||||
# if you get build error about missing 'glu32' this path is likely wrong
|
||||
if (MSVC_VERSION GREATER_EQUAL 1910) # VS 2017
|
||||
set(WINDOW_SDK_PATH "C:/Program Files (x86)/Windows Kits/10/Lib/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}/x64" CACHE PATH "Windows SDK PATH")
|
||||
elseif (MSVC_VERSION GREATER_EQUAL 1800) # VS 2013
|
||||
set(WINDOW_SDK_PATH "C:\\Program Files (x86)\\Windows Kits\\8.1\\Lib\\winv6.3\\um\\${WINDOW_SDK_FOLDER}" CACHE PATH "Windows SDK PATH")
|
||||
else()
|
||||
message( FATAL_ERROR "Visual Studio 2013 or higher required." )
|
||||
endif()
|
||||
|
||||
if (DEBUG_DISCOVERED_SDK_PATH)
|
||||
message(STATUS "The discovered Windows SDK path is ${WINDOW_SDK_PATH}")
|
||||
endif ()
|
||||
|
||||
list(APPEND CMAKE_PREFIX_PATH "${WINDOW_SDK_PATH}")
|
||||
|
||||
# /wd4351 disables warning C4351: new behavior: elements of array will be default initialized
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /wd4351")
|
||||
# /LARGEADDRESSAWARE enables 32-bit apps to use more than 2GB of memory.
|
||||
# Caveats: http://stackoverflow.com/questions/2288728/drawbacks-of-using-largeaddressaware-for-32-bit-windows-executables
|
||||
# TODO: Remove when building 64-bit.
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LARGEADDRESSAWARE")
|
||||
# always produce symbols as PDB files
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zi")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUG /OPT:REF /OPT:ICF")
|
||||
else ()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -fno-strict-aliasing -Wno-unused-parameter")
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ggdb -Woverloaded-virtual -Wdouble-promotion")
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "5.1") # gcc 5.1 and on have suggest-override
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-override")
|
||||
endif ()
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.3")
|
||||
# GLM 0.9.8 on Ubuntu 14 (gcc 4.4) has issues with the simd declarations
|
||||
add_definitions(-DGLM_FORCE_PURE)
|
||||
endif()
|
||||
endif ()
|
||||
endif()
|
||||
|
||||
if (ANDROID)
|
||||
# assume that the toolchain selected for android has C++11 support
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
elseif ((NOT MSVC12) AND (NOT MSVC14))
|
||||
include(CheckCXXCompilerFlag)
|
||||
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
|
||||
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
|
||||
if (COMPILER_SUPPORTS_CXX11)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
elseif(COMPILER_SUPPORTS_CXX0X)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
|
||||
else()
|
||||
message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
if (APPLE)
|
||||
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++11")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --stdlib=libc++")
|
||||
endif ()
|
||||
|
||||
if (NOT ANDROID_LIB_DIR)
|
||||
set(ANDROID_LIB_DIR $ENV{ANDROID_LIB_DIR})
|
||||
endif ()
|
||||
|
||||
if (APPLE)
|
||||
exec_program(sw_vers ARGS -productVersion OUTPUT_VARIABLE OSX_VERSION)
|
||||
string(REGEX MATCH "^[0-9]+\\.[0-9]+" OSX_VERSION ${OSX_VERSION})
|
||||
message(STATUS "Detected OS X version = ${OSX_VERSION}")
|
||||
|
||||
set(OSX_SDK "${OSX_VERSION}" CACHE String "OS X SDK version to look for inside Xcode bundle or at OSX_SDK_PATH")
|
||||
|
||||
# set our OS X deployment target
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.8)
|
||||
|
||||
# find the SDK path for the desired SDK
|
||||
find_path(
|
||||
_OSX_DESIRED_SDK_PATH
|
||||
NAME MacOSX${OSX_SDK}.sdk
|
||||
HINTS ${OSX_SDK_PATH}
|
||||
PATHS /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/
|
||||
/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/
|
||||
)
|
||||
|
||||
if (NOT _OSX_DESIRED_SDK_PATH)
|
||||
message(STATUS "Could not find OS X ${OSX_SDK} SDK. Will fall back to default. If you want a specific SDK, please pass OSX_SDK and optionally OSX_SDK_PATH to CMake.")
|
||||
else ()
|
||||
message(STATUS "Found OS X ${OSX_SDK} SDK at ${_OSX_DESIRED_SDK_PATH}/MacOSX${OSX_SDK}.sdk")
|
||||
|
||||
# set that as the SDK to use
|
||||
set(CMAKE_OSX_SYSROOT ${_OSX_DESIRED_SDK_PATH}/MacOSX${OSX_SDK}.sdk)
|
||||
endif ()
|
||||
endif ()
|
1
cmake/externals/LibOVR/CMakeLists.txt
vendored
1
cmake/externals/LibOVR/CMakeLists.txt
vendored
|
@ -33,7 +33,6 @@ if (WIN32)
|
|||
include(SelectLibraryConfigurations)
|
||||
select_library_configurations(LIBOVR)
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${${EXTERNAL_NAME_UPPER}_LIBRARIES} CACHE TYPE INTERNAL)
|
||||
message("Libs ${EXTERNAL_NAME_UPPER}_LIBRARIES ${${EXTERNAL_NAME_UPPER}_LIBRARIES}")
|
||||
|
||||
elseif(APPLE)
|
||||
|
||||
|
|
14
cmake/externals/quazip/CMakeLists.txt
vendored
14
cmake/externals/quazip/CMakeLists.txt
vendored
|
@ -4,14 +4,6 @@ cmake_policy(SET CMP0046 OLD)
|
|||
|
||||
include(ExternalProject)
|
||||
|
||||
if (WIN32)
|
||||
# windows shell does not like backslashes expanded on the command line,
|
||||
# so convert all backslashes in the QT path to forward slashes
|
||||
string(REPLACE \\ / QT_CMAKE_PREFIX_PATH $ENV{QT_CMAKE_PREFIX_PATH})
|
||||
elseif ($ENV{QT_CMAKE_PREFIX_PATH})
|
||||
set(QT_CMAKE_PREFIX_PATH $ENV{QT_CMAKE_PREFIX_PATH})
|
||||
endif ()
|
||||
|
||||
set(QUAZIP_CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -DCMAKE_PREFIX_PATH=${QT_CMAKE_PREFIX_PATH} -DCMAKE_INSTALL_NAME_DIR:PATH=<INSTALL_DIR>/lib -DZLIB_ROOT=${ZLIB_ROOT} -DCMAKE_POSITION_INDEPENDENT_CODE=ON)
|
||||
|
||||
if (APPLE)
|
||||
|
@ -34,9 +26,9 @@ add_dependencies(quazip zlib)
|
|||
|
||||
# Hide this external target (for ide users)
|
||||
set_target_properties(${EXTERNAL_NAME} PROPERTIES
|
||||
FOLDER "hidden/externals"
|
||||
INSTALL_NAME_DIR ${INSTALL_DIR}/lib
|
||||
BUILD_WITH_INSTALL_RPATH True)
|
||||
FOLDER "hidden/externals"
|
||||
INSTALL_NAME_DIR ${INSTALL_DIR}/lib
|
||||
BUILD_WITH_INSTALL_RPATH True)
|
||||
|
||||
ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR)
|
||||
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${INSTALL_DIR}/include CACHE PATH "List of QuaZip include directories")
|
||||
|
|
43
cmake/init.cmake
Normal file
43
cmake/init.cmake
Normal file
|
@ -0,0 +1,43 @@
|
|||
if (WIN32)
|
||||
cmake_policy(SET CMP0020 NEW)
|
||||
endif (WIN32)
|
||||
|
||||
if (POLICY CMP0043)
|
||||
cmake_policy(SET CMP0043 OLD)
|
||||
endif ()
|
||||
|
||||
if (POLICY CMP0042)
|
||||
cmake_policy(SET CMP0042 OLD)
|
||||
endif ()
|
||||
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMakeTargets")
|
||||
# Hide automoc folders (for IDEs)
|
||||
set(AUTOGEN_TARGETS_FOLDER "hidden/generated")
|
||||
# Find includes in corresponding build directories
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
if (CMAKE_BUILD_TYPE)
|
||||
string(TOUPPER ${CMAKE_BUILD_TYPE} UPPER_CMAKE_BUILD_TYPE)
|
||||
else ()
|
||||
set(UPPER_CMAKE_BUILD_TYPE DEBUG)
|
||||
endif ()
|
||||
|
||||
# CMAKE_CURRENT_SOURCE_DIR is the parent folder here
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/")
|
||||
|
||||
set(HF_CMAKE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
set(MACRO_DIR "${HF_CMAKE_DIR}/macros")
|
||||
set(EXTERNAL_PROJECT_DIR "${HF_CMAKE_DIR}/externals")
|
||||
|
||||
file(GLOB HIFI_CUSTOM_MACROS "cmake/macros/*.cmake")
|
||||
foreach(CUSTOM_MACRO ${HIFI_CUSTOM_MACROS})
|
||||
include(${CUSTOM_MACRO})
|
||||
endforeach()
|
||||
|
||||
if (ANDROID)
|
||||
file(GLOB ANDROID_CUSTOM_MACROS "cmake/android/*.cmake")
|
||||
foreach(CUSTOM_MACRO ${ANDROID_CUSTOM_MACROS})
|
||||
include(${CUSTOM_MACRO})
|
||||
endforeach()
|
||||
endif ()
|
|
@ -9,11 +9,13 @@ macro(SETUP_HIFI_CLIENT_SERVER_PLUGIN)
|
|||
set(${TARGET_NAME}_SHARED 1)
|
||||
setup_hifi_library(${ARGV})
|
||||
|
||||
if (NOT DEFINED SERVER_ONLY)
|
||||
if (BUILD_CLIENT)
|
||||
add_dependencies(interface ${TARGET_NAME})
|
||||
endif()
|
||||
|
||||
add_dependencies(assignment-client ${TARGET_NAME})
|
||||
if (BUILD_SERVER)
|
||||
add_dependencies(assignment-client ${TARGET_NAME})
|
||||
endif()
|
||||
|
||||
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Plugins")
|
||||
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
macro(SETUP_HIFI_PLUGIN)
|
||||
set(${TARGET_NAME}_SHARED 1)
|
||||
setup_hifi_library(${ARGV})
|
||||
add_dependencies(interface ${TARGET_NAME})
|
||||
if (BUILD_CLIENT)
|
||||
add_dependencies(interface ${TARGET_NAME})
|
||||
endif()
|
||||
target_link_libraries(${TARGET_NAME} ${CMAKE_THREAD_LIBS_INIT})
|
||||
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Plugins")
|
||||
|
||||
|
|
84
cmake/macros/SetupQt.cmake
Normal file
84
cmake/macros/SetupQt.cmake
Normal file
|
@ -0,0 +1,84 @@
|
|||
#
|
||||
# Copyright 2015 High Fidelity, Inc.
|
||||
# Created by Bradley Austin Davis on 2015/10/10
|
||||
#
|
||||
# Distributed under the Apache License, Version 2.0.
|
||||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
|
||||
function(set_from_env _RESULT_NAME _ENV_VAR_NAME _DEFAULT_VALUE)
|
||||
if ("$ENV{${_ENV_VAR_NAME}}" STREQUAL "")
|
||||
set (${_RESULT_NAME} ${_DEFAULT_VALUE} PARENT_SCOPE)
|
||||
else()
|
||||
set (${_RESULT_NAME} $ENV{${_ENV_VAR_NAME}} PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Construct a default QT location from a root path, a version and an architecture
|
||||
function(calculate_default_qt_dir _RESULT_NAME)
|
||||
if (ANDROID)
|
||||
set(QT_DEFAULT_ARCH "android_armv7")
|
||||
elseif(UWP)
|
||||
set(QT_DEFAULT_ARCH "winrt_x64_msvc2017")
|
||||
elseif(APPLE)
|
||||
set(QT_DEFAULT_ARCH "clang_64")
|
||||
elseif(WIN32)
|
||||
set(QT_DEFAULT_ARCH "msvc2017_64")
|
||||
else()
|
||||
set(QT_DEFAULT_ARCH "gcc_64")
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
set(QT_DEFAULT_ROOT "c:/Qt")
|
||||
else()
|
||||
set(QT_DEFAULT_ROOT "$ENV{HOME}/Qt")
|
||||
endif()
|
||||
|
||||
set_from_env(QT_ROOT QT_ROOT ${QT_DEFAULT_ROOT})
|
||||
set_from_env(QT_VERSION QT_VERSION "5.9.1")
|
||||
set_from_env(QT_ARCH QT_ARCH ${QT_DEFAULT_ARCH})
|
||||
|
||||
set(${_RESULT_NAME} "${QT_ROOT}/${QT_VERSION}/${QT_ARCH}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Sets the QT_CMAKE_PREFIX_PATH and QT_DIR variables
|
||||
# Also enables CMAKE_AUTOMOC and CMAKE_AUTORCC
|
||||
macro(setup_qt)
|
||||
set(QT_CMAKE_PREFIX_PATH "$ENV{QT_CMAKE_PREFIX_PATH}")
|
||||
if (("QT_CMAKE_PREFIX_PATH" STREQUAL "") OR (NOT EXISTS "${QT_CMAKE_PREFIX_PATH}"))
|
||||
calculate_default_qt_dir(QT_DIR)
|
||||
set(QT_CMAKE_PREFIX_PATH "${QT_DIR}/lib/cmake")
|
||||
else()
|
||||
# figure out where the qt dir is
|
||||
get_filename_component(QT_DIR "${QT_CMAKE_PREFIX_PATH}/../../" ABSOLUTE)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
# windows shell does not like backslashes expanded on the command line,
|
||||
# so convert all backslashes in the QT path to forward slashes
|
||||
string(REPLACE \\ / QT_CMAKE_PREFIX_PATH ${QT_CMAKE_PREFIX_PATH})
|
||||
string(REPLACE \\ / QT_DIR ${QT_DIR})
|
||||
endif()
|
||||
|
||||
# This check doesn't work on Mac
|
||||
#if (NOT EXISTS "${QT_DIR}/include/QtCore/QtGlobal")
|
||||
# message(FATAL_ERROR "Unable to locate Qt includes in ${QT_DIR}")
|
||||
#endif()
|
||||
|
||||
if (NOT EXISTS "${QT_CMAKE_PREFIX_PATH}/Qt5Core/Qt5CoreConfig.cmake")
|
||||
message(FATAL_ERROR "Unable to locate Qt cmake config in ${QT_CMAKE_PREFIX_PATH}")
|
||||
endif()
|
||||
|
||||
message(STATUS "The Qt build in use is: \"${QT_DIR}\"")
|
||||
|
||||
# Instruct CMake to run moc automatically when needed.
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
|
||||
# Instruct CMake to run rcc automatically when needed
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
if (WIN32)
|
||||
add_paths_to_fixup_libs("${QT_DIR}/bin")
|
||||
endif ()
|
||||
|
||||
endmacro()
|
|
@ -19,6 +19,7 @@ Flickable {
|
|||
|
||||
signal newViewRequestedCallback(var request)
|
||||
signal loadingChangedCallback(var loadRequest)
|
||||
pressDelay: 300
|
||||
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
|
||||
|
@ -167,4 +168,11 @@ Flickable {
|
|||
playing: visible
|
||||
z: 10000
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onWheel: {
|
||||
flick.flick(0, wheel.angleDelta.y*10)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,12 +40,20 @@ Rectangle {
|
|||
Hifi.QmlCommerce {
|
||||
id: commerce;
|
||||
|
||||
onAccountResult: {
|
||||
if (result.status === "success") {
|
||||
commerce.getKeyFilePathIfExists();
|
||||
} else {
|
||||
// unsure how to handle a failure here. We definitely cannot proceed.
|
||||
}
|
||||
}
|
||||
|
||||
onLoginStatusResult: {
|
||||
if (!isLoggedIn && root.activeView !== "needsLogIn") {
|
||||
root.activeView = "needsLogIn";
|
||||
} else if (isLoggedIn) {
|
||||
root.activeView = "initialize";
|
||||
commerce.getKeyFilePathIfExists();
|
||||
commerce.account();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,7 +211,7 @@ Rectangle {
|
|||
commerce.getLoginStatus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HifiWallet.NeedsLogIn {
|
||||
id: needsLogIn;
|
||||
visible: root.activeView === "needsLogIn";
|
||||
|
@ -239,7 +247,7 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// "WALLET NOT SET UP" START
|
||||
//
|
||||
|
@ -250,7 +258,7 @@ Rectangle {
|
|||
anchors.bottom: parent.bottom;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
|
||||
|
||||
RalewayRegular {
|
||||
id: notSetUpText;
|
||||
text: "<b>Your wallet isn't set up.</b><br><br>Set up your Wallet (no credit card necessary) to claim your <b>free HFC</b> " +
|
||||
|
@ -281,7 +289,7 @@ Rectangle {
|
|||
anchors.left: parent.left;
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.bottomMargin: 24;
|
||||
|
||||
|
||||
// "Cancel" button
|
||||
HifiControlsUit.Button {
|
||||
id: cancelButton;
|
||||
|
|
|
@ -35,12 +35,20 @@ Rectangle {
|
|||
Hifi.QmlCommerce {
|
||||
id: commerce;
|
||||
|
||||
onAccountResult: {
|
||||
if (result.status === "success") {
|
||||
commerce.getKeyFilePathIfExists();
|
||||
} else {
|
||||
// unsure how to handle a failure here. We definitely cannot proceed.
|
||||
}
|
||||
}
|
||||
|
||||
onLoginStatusResult: {
|
||||
if (!isLoggedIn && root.activeView !== "needsLogIn") {
|
||||
root.activeView = "needsLogIn";
|
||||
} else if (isLoggedIn) {
|
||||
root.activeView = "initialize";
|
||||
commerce.getKeyFilePathIfExists();
|
||||
commerce.account();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -174,7 +182,7 @@ Rectangle {
|
|||
commerce.getLoginStatus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HifiWallet.NeedsLogIn {
|
||||
id: needsLogIn;
|
||||
visible: root.activeView === "needsLogIn";
|
||||
|
@ -210,7 +218,7 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// "WALLET NOT SET UP" START
|
||||
//
|
||||
|
@ -221,7 +229,7 @@ Rectangle {
|
|||
anchors.bottom: parent.bottom;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
|
||||
|
||||
RalewayRegular {
|
||||
id: notSetUpText;
|
||||
text: "<b>Your wallet isn't set up.</b><br><br>Set up your Wallet (no credit card necessary) to claim your <b>free HFC</b> " +
|
||||
|
@ -252,7 +260,7 @@ Rectangle {
|
|||
anchors.left: parent.left;
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.bottomMargin: 24;
|
||||
|
||||
|
||||
// "Cancel" button
|
||||
HifiControlsUit.Button {
|
||||
id: cancelButton;
|
||||
|
@ -309,7 +317,7 @@ Rectangle {
|
|||
anchors.topMargin: 8;
|
||||
anchors.bottom: actionButtonsContainer.top;
|
||||
anchors.bottomMargin: 8;
|
||||
|
||||
|
||||
//
|
||||
// FILTER BAR START
|
||||
//
|
||||
|
@ -383,7 +391,7 @@ Rectangle {
|
|||
itemHref: root_file_url;
|
||||
anchors.topMargin: 12;
|
||||
anchors.bottomMargin: 12;
|
||||
|
||||
|
||||
Connections {
|
||||
onSendToPurchases: {
|
||||
if (msg.method === 'purchases_itemInfoClicked') {
|
||||
|
@ -402,7 +410,7 @@ Rectangle {
|
|||
anchors.left: parent.left;
|
||||
anchors.bottom: parent.bottom;
|
||||
width: parent.width;
|
||||
|
||||
|
||||
// Explanitory text
|
||||
RalewayRegular {
|
||||
id: haventPurchasedYet;
|
||||
|
|
|
@ -31,6 +31,13 @@
|
|||
#include <openssl/evp.h>
|
||||
#include <openssl/aes.h>
|
||||
|
||||
// I know, right? But per https://www.openssl.org/docs/faq.html
|
||||
// this avoids OPENSSL_Uplink(00007FF847238000,08): no OPENSSL_Applink
|
||||
// at runtime.
|
||||
#ifdef Q_OS_WIN
|
||||
#include <openssl/applink.c>
|
||||
#endif
|
||||
|
||||
static const char* KEY_FILE = "hifikey";
|
||||
static const char* IMAGE_FILE = "hifi_image"; // eventually this will live in keyfile
|
||||
|
||||
|
|
|
@ -144,25 +144,33 @@ int main(int argc, const char* argv[]) {
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
// FIXME this method of checking the OpenGL version screws up the `QOpenGLContext::globalShareContext()` value, which in turn
|
||||
// leads to crashes when creating the real OpenGL instance. Disabling for now until we come up with a better way of checking
|
||||
// the GL version on the system without resorting to creating a full Qt application
|
||||
#if 0
|
||||
// Check OpenGL version.
|
||||
// This is done separately from the main Application so that start-up and shut-down logic within the main Application is
|
||||
// not made more complicated than it already is.
|
||||
bool override = false;
|
||||
bool overrideGLCheck = false;
|
||||
|
||||
QJsonObject glData;
|
||||
{
|
||||
OpenGLVersionChecker openGLVersionChecker(argc, const_cast<char**>(argv));
|
||||
bool valid = true;
|
||||
glData = openGLVersionChecker.checkVersion(valid, override);
|
||||
glData = openGLVersionChecker.checkVersion(valid, overrideGLCheck);
|
||||
if (!valid) {
|
||||
if (override) {
|
||||
if (overrideGLCheck) {
|
||||
auto glVersion = glData["version"].toString();
|
||||
qCDebug(interfaceapp, "Running on insufficient OpenGL version: %s.", glVersion.toStdString().c_str());
|
||||
qCWarning(interfaceapp, "Running on insufficient OpenGL version: %s.", glVersion.toStdString().c_str());
|
||||
} else {
|
||||
qCDebug(interfaceapp, "Early exit due to OpenGL version.");
|
||||
qCWarning(interfaceapp, "Early exit due to OpenGL version.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Debug option to demonstrate that the client's local time does not
|
||||
// need to be in sync with any other network node. This forces clock
|
||||
|
@ -223,8 +231,9 @@ int main(int argc, const char* argv[]) {
|
|||
|
||||
Application app(argcExtended, const_cast<char**>(argvExtended.data()), startupTime, runningMarkerExisted);
|
||||
|
||||
#if 0
|
||||
// If we failed the OpenGLVersion check, log it.
|
||||
if (override) {
|
||||
if (overrideGLcheck) {
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
if (accountManager->isLoggedIn()) {
|
||||
UserActivityLogger::getInstance().insufficientGLVersion(glData);
|
||||
|
@ -238,6 +247,8 @@ int main(int argc, const char* argv[]) {
|
|||
});
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Setup local server
|
||||
QLocalServer server { &app };
|
||||
|
|
|
@ -649,7 +649,9 @@ void Avatar::render(RenderArgs* renderArgs) {
|
|||
return;
|
||||
}
|
||||
|
||||
fixupModelsInScene(renderArgs->_scene);
|
||||
if (!isMyAvatar()) {
|
||||
fixupModelsInScene(renderArgs->_scene);
|
||||
}
|
||||
|
||||
if (showCollisionShapes && shouldRenderHead(renderArgs) && _skeletonModel->isRenderable()) {
|
||||
PROFILE_RANGE_BATCH(batch, __FUNCTION__":skeletonBoundingCollisionShapes");
|
||||
|
|
|
@ -62,24 +62,9 @@ QRect HmdDisplayPlugin::getRecommendedOverlayRect() const {
|
|||
return CompositorHelper::VIRTUAL_SCREEN_RECOMMENDED_OVERLAY_RECT;
|
||||
}
|
||||
|
||||
bool HmdDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||
if (!_vsyncEnabled && !_disablePreviewItemAdded) {
|
||||
_container->addMenuItem(PluginType::DISPLAY_PLUGIN, MENU_PATH(), DISABLE_PREVIEW,
|
||||
[this](bool clicked) {
|
||||
_disablePreview = clicked;
|
||||
_container->setBoolSetting("disableHmdPreview", _disablePreview);
|
||||
if (_disablePreview) {
|
||||
_clearPreviewFlag = true;
|
||||
}
|
||||
}, true, _disablePreview);
|
||||
_disablePreviewItemAdded = true;
|
||||
}
|
||||
return Parent::beginFrameRender(frameIndex);
|
||||
}
|
||||
|
||||
#define DISABLE_PREVIEW_MENU_ITEM_DELAY_MS 500
|
||||
|
||||
bool HmdDisplayPlugin::internalActivate() {
|
||||
_disablePreviewItemAdded = false;
|
||||
_monoPreview = _container->getBoolSetting("monoPreview", DEFAULT_MONO_VIEW);
|
||||
_clearPreviewFlag = true;
|
||||
_container->addMenuItem(PluginType::DISPLAY_PLUGIN, MENU_PATH(), MONO_PREVIEW,
|
||||
|
@ -94,6 +79,19 @@ bool HmdDisplayPlugin::internalActivate() {
|
|||
_disablePreview = _container->getBoolSetting("disableHmdPreview", DEFAULT_DISABLE_PREVIEW || _vsyncEnabled);
|
||||
#endif
|
||||
|
||||
QTimer::singleShot(DISABLE_PREVIEW_MENU_ITEM_DELAY_MS, [this] {
|
||||
if (isActive() && !_vsyncEnabled) {
|
||||
_container->addMenuItem(PluginType::DISPLAY_PLUGIN, MENU_PATH(), DISABLE_PREVIEW,
|
||||
[this](bool clicked) {
|
||||
_disablePreview = clicked;
|
||||
_container->setBoolSetting("disableHmdPreview", _disablePreview);
|
||||
if (_disablePreview) {
|
||||
_clearPreviewFlag = true;
|
||||
}
|
||||
}, true, _disablePreview);
|
||||
}
|
||||
});
|
||||
|
||||
_container->removeMenu(FRAMERATE);
|
||||
for_each_eye([&](Eye eye) {
|
||||
_eyeInverseProjections[eye] = glm::inverse(_eyeProjections[eye]);
|
||||
|
|
|
@ -51,7 +51,6 @@ protected:
|
|||
virtual void postPreview() {};
|
||||
virtual void updatePresentPose();
|
||||
|
||||
bool beginFrameRender(uint32_t frameIndex) override;
|
||||
bool internalActivate() override;
|
||||
void internalDeactivate() override;
|
||||
void compositeOverlay() override;
|
||||
|
@ -87,7 +86,6 @@ private:
|
|||
ivec4 getViewportForSourceSize(const uvec2& size) const;
|
||||
float getLeftCenterPixel() const;
|
||||
|
||||
bool _disablePreviewItemAdded { false };
|
||||
bool _monoPreview { true };
|
||||
bool _clearPreviewFlag { false };
|
||||
gpu::TexturePointer _previewTexture;
|
||||
|
|
|
@ -91,7 +91,12 @@ void entitiesScriptEngineDeleter(ScriptEngine* engine) {
|
|||
};
|
||||
|
||||
// Wait for the scripting thread from the thread pool to avoid hanging the main thread
|
||||
QThreadPool::globalInstance()->start(new WaitRunnable(engine));
|
||||
auto threadPool = QThreadPool::globalInstance();
|
||||
if (threadPool) {
|
||||
threadPool->start(new WaitRunnable(engine));
|
||||
} else {
|
||||
delete engine;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::resetEntitiesScriptEngine() {
|
||||
|
|
|
@ -91,20 +91,27 @@ void ParticleEffectEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePoi
|
|||
qCWarning(entitiesrenderer) << "Bad particle properties";
|
||||
}
|
||||
}
|
||||
if (_particleProperties != newParticleProperties) {
|
||||
|
||||
if (resultWithReadLock<bool>([&]{ return _particleProperties != newParticleProperties; })) {
|
||||
_timeUntilNextEmit = 0;
|
||||
_particleProperties = newParticleProperties;
|
||||
withWriteLock([&]{
|
||||
_particleProperties = newParticleProperties;
|
||||
});
|
||||
}
|
||||
_emitting = entity->getIsEmitting();
|
||||
|
||||
if (_particleProperties.textures.isEmpty()) {
|
||||
bool hasTexture = resultWithReadLock<bool>([&]{ return _particleProperties.textures.isEmpty(); });
|
||||
if (hasTexture) {
|
||||
if (_networkTexture) {
|
||||
withWriteLock([&] {
|
||||
_networkTexture.reset();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (!_networkTexture || _networkTexture->getURL() != QUrl(_particleProperties.textures)) {
|
||||
bool textureNeedsUpdate = resultWithReadLock<bool>([&]{
|
||||
return !_networkTexture || _networkTexture->getURL() != QUrl(_particleProperties.textures);
|
||||
});
|
||||
if (textureNeedsUpdate) {
|
||||
withWriteLock([&] {
|
||||
_networkTexture = DependencyManager::get<TextureCache>()->getTexture(_particleProperties.textures);
|
||||
});
|
||||
|
@ -115,15 +122,17 @@ void ParticleEffectEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePoi
|
|||
void ParticleEffectEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||
// Fill in Uniforms structure
|
||||
ParticleUniforms particleUniforms;
|
||||
particleUniforms.radius.start = _particleProperties.radius.range.start;
|
||||
particleUniforms.radius.middle = _particleProperties.radius.gradient.target;
|
||||
particleUniforms.radius.finish = _particleProperties.radius.range.finish;
|
||||
particleUniforms.radius.spread = _particleProperties.radius.gradient.spread;
|
||||
particleUniforms.color.start = _particleProperties.getColorStart();
|
||||
particleUniforms.color.middle = _particleProperties.getColorMiddle();
|
||||
particleUniforms.color.finish = _particleProperties.getColorFinish();
|
||||
particleUniforms.color.spread = _particleProperties.getColorSpread();
|
||||
particleUniforms.lifespan = _particleProperties.lifespan;
|
||||
withReadLock([&]{
|
||||
particleUniforms.radius.start = _particleProperties.radius.range.start;
|
||||
particleUniforms.radius.middle = _particleProperties.radius.gradient.target;
|
||||
particleUniforms.radius.finish = _particleProperties.radius.range.finish;
|
||||
particleUniforms.radius.spread = _particleProperties.radius.gradient.spread;
|
||||
particleUniforms.color.start = _particleProperties.getColorStart();
|
||||
particleUniforms.color.middle = _particleProperties.getColorMiddle();
|
||||
particleUniforms.color.finish = _particleProperties.getColorFinish();
|
||||
particleUniforms.color.spread = _particleProperties.getColorSpread();
|
||||
particleUniforms.lifespan = _particleProperties.lifespan;
|
||||
});
|
||||
// Update particle uniforms
|
||||
memcpy(&_uniformBuffer.edit<ParticleUniforms>(), &particleUniforms, sizeof(ParticleUniforms));
|
||||
}
|
||||
|
@ -146,35 +155,26 @@ Item::Bound ParticleEffectEntityRenderer::getBound() {
|
|||
|
||||
static const size_t VERTEX_PER_PARTICLE = 4;
|
||||
|
||||
bool ParticleEffectEntityRenderer::emitting() const {
|
||||
return (
|
||||
_emitting &&
|
||||
_particleProperties.emission.rate > 0.0f &&
|
||||
_particleProperties.lifespan > 0.0f &&
|
||||
_particleProperties.polar.start <= _particleProperties.polar.finish
|
||||
);
|
||||
}
|
||||
|
||||
void ParticleEffectEntityRenderer::createParticle(uint64_t now) {
|
||||
ParticleEffectEntityRenderer::CpuParticle ParticleEffectEntityRenderer::createParticle(uint64_t now, const Transform& baseTransform, const particle::Properties& particleProperties) {
|
||||
CpuParticle particle;
|
||||
|
||||
const auto& accelerationSpread = _particleProperties.emission.acceleration.spread;
|
||||
const auto& azimuthStart = _particleProperties.azimuth.start;
|
||||
const auto& azimuthFinish = _particleProperties.azimuth.finish;
|
||||
const auto& emitDimensions = _particleProperties.emission.dimensions;
|
||||
const auto& emitAcceleration = _particleProperties.emission.acceleration.target;
|
||||
auto emitOrientation = _particleProperties.emission.orientation;
|
||||
const auto& emitRadiusStart = glm::max(_particleProperties.radiusStart, EPSILON); // Avoid math complications at center
|
||||
const auto& emitSpeed = _particleProperties.emission.speed.target;
|
||||
const auto& speedSpread = _particleProperties.emission.speed.spread;
|
||||
const auto& polarStart = _particleProperties.polar.start;
|
||||
const auto& polarFinish = _particleProperties.polar.finish;
|
||||
const auto& accelerationSpread = particleProperties.emission.acceleration.spread;
|
||||
const auto& azimuthStart = particleProperties.azimuth.start;
|
||||
const auto& azimuthFinish = particleProperties.azimuth.finish;
|
||||
const auto& emitDimensions = particleProperties.emission.dimensions;
|
||||
const auto& emitAcceleration = particleProperties.emission.acceleration.target;
|
||||
auto emitOrientation = particleProperties.emission.orientation;
|
||||
const auto& emitRadiusStart = glm::max(particleProperties.radiusStart, EPSILON); // Avoid math complications at center
|
||||
const auto& emitSpeed = particleProperties.emission.speed.target;
|
||||
const auto& speedSpread = particleProperties.emission.speed.spread;
|
||||
const auto& polarStart = particleProperties.polar.start;
|
||||
const auto& polarFinish = particleProperties.polar.finish;
|
||||
|
||||
particle.seed = randFloatInRange(-1.0f, 1.0f);
|
||||
particle.expiration = now + (uint64_t)(_particleProperties.lifespan * USECS_PER_SECOND);
|
||||
if (_particleProperties.emission.shouldTrail) {
|
||||
particle.position = _modelTransform.getTranslation();
|
||||
emitOrientation = _modelTransform.getRotation() * emitOrientation;
|
||||
particle.expiration = now + (uint64_t)(particleProperties.lifespan * USECS_PER_SECOND);
|
||||
if (particleProperties.emission.shouldTrail) {
|
||||
particle.position = baseTransform.getTranslation();
|
||||
emitOrientation = baseTransform.getRotation() * emitOrientation;
|
||||
}
|
||||
|
||||
// Position, velocity, and acceleration
|
||||
|
@ -232,7 +232,7 @@ void ParticleEffectEntityRenderer::createParticle(uint64_t now) {
|
|||
particle.acceleration = emitAcceleration + randFloatInRange(-1.0f, 1.0f) * accelerationSpread;
|
||||
}
|
||||
|
||||
_cpuParticles.push_back(particle);
|
||||
return particle;
|
||||
}
|
||||
|
||||
void ParticleEffectEntityRenderer::stepSimulation() {
|
||||
|
@ -244,14 +244,19 @@ void ParticleEffectEntityRenderer::stepSimulation() {
|
|||
const auto now = usecTimestampNow();
|
||||
const auto interval = std::min<uint64_t>(USECS_PER_SECOND / 60, now - _lastSimulated);
|
||||
_lastSimulated = now;
|
||||
|
||||
particle::Properties particleProperties;
|
||||
withReadLock([&]{
|
||||
particleProperties = _particleProperties;
|
||||
});
|
||||
|
||||
if (emitting()) {
|
||||
uint64_t emitInterval = (uint64_t)(USECS_PER_SECOND / _particleProperties.emission.rate);
|
||||
if (interval >= _timeUntilNextEmit) {
|
||||
if (_emitting && particleProperties.emitting()) {
|
||||
uint64_t emitInterval = particleProperties.emitIntervalUsecs();
|
||||
if (emitInterval > 0 && interval >= _timeUntilNextEmit) {
|
||||
auto timeRemaining = interval;
|
||||
while (timeRemaining > _timeUntilNextEmit) {
|
||||
// emit particle
|
||||
createParticle(now);
|
||||
_cpuParticles.push_back(createParticle(now, _modelTransform, particleProperties));
|
||||
_timeUntilNextEmit = emitInterval;
|
||||
if (emitInterval < timeRemaining) {
|
||||
timeRemaining -= emitInterval;
|
||||
|
@ -263,7 +268,7 @@ void ParticleEffectEntityRenderer::stepSimulation() {
|
|||
}
|
||||
|
||||
// Kill any particles that have expired or are over the max size
|
||||
while (_cpuParticles.size() > _particleProperties.maxParticles || (!_cpuParticles.empty() && _cpuParticles.front().expiration <= now)) {
|
||||
while (_cpuParticles.size() > particleProperties.maxParticles || (!_cpuParticles.empty() && _cpuParticles.front().expiration <= now)) {
|
||||
_cpuParticles.pop_front();
|
||||
}
|
||||
|
||||
|
|
|
@ -93,9 +93,8 @@ private:
|
|||
};
|
||||
|
||||
|
||||
void createParticle(uint64_t now);
|
||||
static CpuParticle createParticle(uint64_t now, const Transform& baseTransform, const particle::Properties& particleProperties);
|
||||
void stepSimulation();
|
||||
bool emitting() const;
|
||||
|
||||
particle::Properties _particleProperties;
|
||||
CpuParticles _cpuParticles;
|
||||
|
|
|
@ -30,14 +30,11 @@ TextEntityRenderer::TextEntityRenderer(const EntityItemPointer& entity) :
|
|||
|
||||
}
|
||||
|
||||
|
||||
void TextEntityRenderer::onRemoveFromSceneTyped(const TypedEntityPointer& entity) {
|
||||
TextEntityRenderer::~TextEntityRenderer() {
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
if (_geometryID && geometryCache) {
|
||||
geometryCache->releaseID(_geometryID);
|
||||
}
|
||||
delete _textRenderer;
|
||||
_textRenderer = nullptr;
|
||||
}
|
||||
|
||||
bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
|
||||
|
|
|
@ -24,14 +24,13 @@ class TextEntityRenderer : public TypedEntityRenderer<TextEntityItem> {
|
|||
using Pointer = std::shared_ptr<TextEntityRenderer>;
|
||||
public:
|
||||
TextEntityRenderer(const EntityItemPointer& entity);
|
||||
|
||||
~TextEntityRenderer();
|
||||
private:
|
||||
virtual void onRemoveFromSceneTyped(const TypedEntityPointer& entity) override;
|
||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
||||
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
||||
virtual void doRender(RenderArgs* args) override;
|
||||
int _geometryID{ 0 };
|
||||
TextRenderer3D* _textRenderer;
|
||||
std::shared_ptr<TextRenderer3D> _textRenderer;
|
||||
bool _faceCamera;
|
||||
glm::vec3 _dimensions;
|
||||
glm::vec3 _textColor;
|
||||
|
|
|
@ -104,7 +104,7 @@ bool operator!=(const Properties& a, const Properties& b) {
|
|||
return !(a == b);
|
||||
}
|
||||
|
||||
bool particle::Properties::valid() const {
|
||||
bool Properties::valid() const {
|
||||
if (glm::any(glm::isnan(emission.orientation))) {
|
||||
qCWarning(entities) << "Bad particle data";
|
||||
return false;
|
||||
|
@ -133,6 +133,19 @@ bool particle::Properties::valid() const {
|
|||
(radius.gradient.spread == glm::clamp(radius.gradient.spread, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS));
|
||||
}
|
||||
|
||||
bool Properties::emitting() const {
|
||||
return emission.rate > 0.0f && lifespan > 0.0f && polar.start <= polar.finish;
|
||||
|
||||
}
|
||||
|
||||
uint64_t Properties::emitIntervalUsecs() const {
|
||||
if (emission.rate > 0.0f) {
|
||||
return (uint64_t)(USECS_PER_SECOND / emission.rate);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
EntityItemPointer ParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity { new ParticleEffectEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
|
|
|
@ -160,7 +160,9 @@ namespace particle {
|
|||
Properties() {};
|
||||
Properties(const Properties& other) { *this = other; }
|
||||
bool valid() const;
|
||||
|
||||
bool emitting() const;
|
||||
uint64_t emitIntervalUsecs() const;
|
||||
|
||||
Properties& operator =(const Properties& other) {
|
||||
color = other.color;
|
||||
alpha = other.alpha;
|
||||
|
|
|
@ -40,8 +40,11 @@ const QSurfaceFormat& getDefaultOpenGLSurfaceFormat() {
|
|||
|
||||
int glVersionToInteger(QString glVersion) {
|
||||
QStringList versionParts = glVersion.split(QRegularExpression("[\\.\\s]"));
|
||||
int majorNumber = versionParts[0].toInt();
|
||||
int minorNumber = versionParts[1].toInt();
|
||||
int majorNumber = 0, minorNumber = 0;
|
||||
if (versionParts.size() >= 2) {
|
||||
majorNumber = versionParts[0].toInt();
|
||||
minorNumber = versionParts[1].toInt();
|
||||
}
|
||||
return (majorNumber << 16) | minorNumber;
|
||||
}
|
||||
|
||||
|
|
|
@ -467,12 +467,14 @@ void GLVariableAllocationSupport::updateMemoryPressure() {
|
|||
_demoteQueue = WorkQueue();
|
||||
|
||||
// Populate the existing textures into the queue
|
||||
for (const auto& texture : strongTextures) {
|
||||
// Race conditions can still leave nulls in the list, so we need to check
|
||||
if (!texture) {
|
||||
continue;
|
||||
if (_memoryPressureState != MemoryPressureState::Idle) {
|
||||
for (const auto& texture : strongTextures) {
|
||||
// Race conditions can still leave nulls in the list, so we need to check
|
||||
if (!texture) {
|
||||
continue;
|
||||
}
|
||||
addToWorkQueue(texture);
|
||||
}
|
||||
addToWorkQueue(texture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
13
libraries/render-utils/src/Outline.slf
Normal file
13
libraries/render-utils/src/Outline.slf
Normal file
|
@ -0,0 +1,13 @@
|
|||
// Outline.slf
|
||||
// Add outline effect based on two zbuffers : one containing the total scene z and another
|
||||
// with the z of only the objects to be outlined.
|
||||
// This is the version without the fill effect inside the silhouette.
|
||||
//
|
||||
// Created by Olivier Prat on 08/09/2017
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
<@include Outline.slh@>
|
||||
<$main(0)$>
|
97
libraries/render-utils/src/Outline.slh
Normal file
97
libraries/render-utils/src/Outline.slh
Normal file
|
@ -0,0 +1,97 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
<!
|
||||
// Outline.slh
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Olivier Prat on 9/7/17.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
!>
|
||||
<@include DeferredTransform.slh@>
|
||||
<$declareDeferredFrameTransform()$>
|
||||
|
||||
<@include Outline_shared.slh@>
|
||||
|
||||
uniform outlineParamsBuffer {
|
||||
OutlineParameters params;
|
||||
};
|
||||
|
||||
uniform sampler2D sceneDepthMap;
|
||||
uniform sampler2D outlinedDepthMap;
|
||||
|
||||
in vec2 varTexCoord0;
|
||||
out vec4 outFragColor;
|
||||
|
||||
const float FAR_Z = 1.0;
|
||||
const float LINEAR_DEPTH_BIAS = 5e-3;
|
||||
const float OPACITY_EPSILON = 5e-3;
|
||||
|
||||
<@func main(IS_FILLED)@>
|
||||
|
||||
void main(void) {
|
||||
// We offset by half a texel to be centered on the depth sample. If we don't do this
|
||||
// the blur will have a different width between the left / right sides and top / bottom
|
||||
// sides of the silhouette
|
||||
vec2 halfTexel = getInvWidthHeight() / 2;
|
||||
vec2 texCoord0 = varTexCoord0+halfTexel;
|
||||
float outlinedDepth = texture(outlinedDepthMap, texCoord0).x;
|
||||
float intensity = 0.0;
|
||||
|
||||
if (outlinedDepth < FAR_Z) {
|
||||
// We're not on the far plane so we are on the outlined object, thus no outline to do!
|
||||
<@if IS_FILLED@>
|
||||
// But we need to fill the interior
|
||||
float sceneDepth = texture(sceneDepthMap, texCoord0).x;
|
||||
// Transform to linear depth for better precision
|
||||
outlinedDepth = -evalZeyeFromZdb(outlinedDepth);
|
||||
sceneDepth = -evalZeyeFromZdb(sceneDepth);
|
||||
|
||||
// Are we occluded?
|
||||
if (sceneDepth < (outlinedDepth-LINEAR_DEPTH_BIAS)) {
|
||||
intensity = params._fillOpacityOccluded;
|
||||
} else {
|
||||
intensity = params._fillOpacityUnoccluded;
|
||||
}
|
||||
<@else@>
|
||||
discard;
|
||||
<@endif@>
|
||||
} else {
|
||||
float weight = 0.0;
|
||||
vec2 deltaUv = params._size / params._blurKernelSize;
|
||||
vec2 lineStartUv = texCoord0 - params._size / 2.0;
|
||||
vec2 uv;
|
||||
int x;
|
||||
int y;
|
||||
|
||||
for (y=0 ; y<params._blurKernelSize ; y++) {
|
||||
uv = lineStartUv;
|
||||
lineStartUv.y += deltaUv.y;
|
||||
|
||||
if (uv.y>=0.0 && uv.y<=1.0) {
|
||||
for (x=0 ; x<params._blurKernelSize ; x++) {
|
||||
if (uv.x>=0.0 && uv.x<=1.0)
|
||||
{
|
||||
outlinedDepth = texture(outlinedDepthMap, uv).x;
|
||||
intensity += (outlinedDepth < FAR_Z) ? 1.0 : 0.0;
|
||||
weight += 1.f;
|
||||
}
|
||||
uv.x += deltaUv.x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
intensity /= weight;
|
||||
if (intensity < OPACITY_EPSILON) {
|
||||
discard;
|
||||
}
|
||||
|
||||
intensity = min(1.0, intensity / params._threshold) * params._intensity;
|
||||
}
|
||||
|
||||
outFragColor = vec4(params._color.rgb, intensity);
|
||||
}
|
||||
|
||||
<@endfunc@>
|
371
libraries/render-utils/src/OutlineEffect.cpp
Normal file
371
libraries/render-utils/src/OutlineEffect.cpp
Normal file
|
@ -0,0 +1,371 @@
|
|||
//
|
||||
// OutlineEffect.cpp
|
||||
// render-utils/src/
|
||||
//
|
||||
// Created by Olivier Prat on 08/08/17.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#include "OutlineEffect.h"
|
||||
|
||||
#include "GeometryCache.h"
|
||||
|
||||
#include <render/FilterTask.h>
|
||||
#include <render/SortTask.h>
|
||||
|
||||
#include "gpu/Context.h"
|
||||
#include "gpu/StandardShaderLib.h"
|
||||
|
||||
|
||||
#include "surfaceGeometry_copyDepth_frag.h"
|
||||
#include "debug_deferred_buffer_vert.h"
|
||||
#include "debug_deferred_buffer_frag.h"
|
||||
#include "Outline_frag.h"
|
||||
#include "Outline_filled_frag.h"
|
||||
|
||||
using namespace render;
|
||||
|
||||
extern void initZPassPipelines(ShapePlumber& plumber, gpu::StatePointer state);
|
||||
|
||||
OutlineFramebuffer::OutlineFramebuffer() {
|
||||
}
|
||||
|
||||
void OutlineFramebuffer::update(const gpu::TexturePointer& colorBuffer) {
|
||||
// If the depth buffer or size changed, we need to delete our FBOs and recreate them at the
|
||||
// new correct dimensions.
|
||||
if (_depthTexture) {
|
||||
auto newFrameSize = glm::ivec2(colorBuffer->getDimensions());
|
||||
if (_frameSize != newFrameSize) {
|
||||
_frameSize = newFrameSize;
|
||||
clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OutlineFramebuffer::clear() {
|
||||
_depthFramebuffer.reset();
|
||||
_depthTexture.reset();
|
||||
}
|
||||
|
||||
void OutlineFramebuffer::allocate() {
|
||||
|
||||
auto width = _frameSize.x;
|
||||
auto height = _frameSize.y;
|
||||
auto format = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH);
|
||||
|
||||
_depthTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(format, width, height));
|
||||
_depthFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("outlineDepth"));
|
||||
_depthFramebuffer->setDepthStencilBuffer(_depthTexture, format);
|
||||
}
|
||||
|
||||
gpu::FramebufferPointer OutlineFramebuffer::getDepthFramebuffer() {
|
||||
if (!_depthFramebuffer) {
|
||||
allocate();
|
||||
}
|
||||
return _depthFramebuffer;
|
||||
}
|
||||
|
||||
gpu::TexturePointer OutlineFramebuffer::getDepthTexture() {
|
||||
if (!_depthTexture) {
|
||||
allocate();
|
||||
}
|
||||
return _depthTexture;
|
||||
}
|
||||
|
||||
void DrawOutlineDepth::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
auto& inShapes = inputs.get0();
|
||||
auto& deferredFrameBuffer = inputs.get1();
|
||||
|
||||
if (!inShapes.empty()) {
|
||||
RenderArgs* args = renderContext->args;
|
||||
ShapeKey::Builder defaultKeyBuilder;
|
||||
|
||||
if (!_outlineFramebuffer) {
|
||||
_outlineFramebuffer = std::make_shared<OutlineFramebuffer>();
|
||||
}
|
||||
_outlineFramebuffer->update(deferredFrameBuffer->getDeferredColorTexture());
|
||||
|
||||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||
args->_batch = &batch;
|
||||
|
||||
batch.setFramebuffer(_outlineFramebuffer->getDepthFramebuffer());
|
||||
// Clear it
|
||||
batch.clearFramebuffer(
|
||||
gpu::Framebuffer::BUFFER_DEPTH,
|
||||
vec4(vec3(1.0, 1.0, 1.0), 0.0), 1.0, 0, false);
|
||||
|
||||
// Setup camera, projection and viewport for all items
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
batch.setStateScissorRect(args->_viewport);
|
||||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->getViewFrustum().evalProjectionMatrix(projMat);
|
||||
args->getViewFrustum().evalViewTransform(viewMat);
|
||||
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
|
||||
auto shadowPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder);
|
||||
auto shadowSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned());
|
||||
|
||||
std::vector<ShapeKey> skinnedShapeKeys{};
|
||||
|
||||
// Iterate through all inShapes and render the unskinned
|
||||
args->_shapePipeline = shadowPipeline;
|
||||
batch.setPipeline(shadowPipeline->pipeline);
|
||||
for (auto items : inShapes) {
|
||||
if (items.first.isSkinned()) {
|
||||
skinnedShapeKeys.push_back(items.first);
|
||||
}
|
||||
else {
|
||||
renderItems(renderContext, items.second);
|
||||
}
|
||||
}
|
||||
|
||||
// Reiterate to render the skinned
|
||||
args->_shapePipeline = shadowSkinnedPipeline;
|
||||
batch.setPipeline(shadowSkinnedPipeline->pipeline);
|
||||
for (const auto& key : skinnedShapeKeys) {
|
||||
renderItems(renderContext, inShapes.at(key));
|
||||
}
|
||||
|
||||
args->_shapePipeline = nullptr;
|
||||
args->_batch = nullptr;
|
||||
});
|
||||
|
||||
output = _outlineFramebuffer;
|
||||
} else {
|
||||
output = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
DrawOutline::DrawOutline() {
|
||||
}
|
||||
|
||||
void DrawOutline::configure(const Config& config) {
|
||||
_color = config.color;
|
||||
_blurKernelSize = std::min(10, std::max(2, (int)floorf(config.width*2 + 0.5f)));
|
||||
// Size is in normalized screen height. We decide that for outline width = 1, this is equal to 1/400.
|
||||
_size = config.width / 400.f;
|
||||
_fillOpacityUnoccluded = config.fillOpacityUnoccluded;
|
||||
_fillOpacityOccluded = config.fillOpacityOccluded;
|
||||
_threshold = config.glow ? 1.f : 1e-3f;
|
||||
_intensity = config.intensity * (config.glow ? 2.f : 1.f);
|
||||
}
|
||||
|
||||
void DrawOutline::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) {
|
||||
auto outlineFrameBuffer = inputs.get1();
|
||||
|
||||
if (outlineFrameBuffer) {
|
||||
auto sceneDepthBuffer = inputs.get2();
|
||||
const auto frameTransform = inputs.get0();
|
||||
auto outlinedDepthTexture = outlineFrameBuffer->getDepthTexture();
|
||||
auto destinationFrameBuffer = inputs.get3();
|
||||
auto framebufferSize = glm::ivec2(outlinedDepthTexture->getDimensions());
|
||||
|
||||
if (!_primaryWithoutDepthBuffer || framebufferSize!=_frameBufferSize) {
|
||||
// Failing to recreate this frame buffer when the screen has been resized creates a bug on Mac
|
||||
_primaryWithoutDepthBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("primaryWithoutDepth"));
|
||||
_primaryWithoutDepthBuffer->setRenderBuffer(0, destinationFrameBuffer->getRenderBuffer(0));
|
||||
_frameBufferSize = framebufferSize;
|
||||
}
|
||||
|
||||
if (sceneDepthBuffer) {
|
||||
const auto OPACITY_EPSILON = 5e-3f;
|
||||
auto pipeline = getPipeline(_fillOpacityUnoccluded>OPACITY_EPSILON || _fillOpacityOccluded>OPACITY_EPSILON);
|
||||
auto args = renderContext->args;
|
||||
{
|
||||
auto& configuration = _configuration.edit();
|
||||
configuration._color = _color;
|
||||
configuration._intensity = _intensity;
|
||||
configuration._fillOpacityUnoccluded = _fillOpacityUnoccluded;
|
||||
configuration._fillOpacityOccluded = _fillOpacityOccluded;
|
||||
configuration._threshold = _threshold;
|
||||
configuration._blurKernelSize = _blurKernelSize;
|
||||
configuration._size.x = _size * _frameBufferSize.y / _frameBufferSize.x;
|
||||
configuration._size.y = _size;
|
||||
}
|
||||
|
||||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||
batch.enableStereo(false);
|
||||
batch.setFramebuffer(_primaryWithoutDepthBuffer);
|
||||
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
batch.setProjectionTransform(glm::mat4());
|
||||
batch.resetViewTransform();
|
||||
batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(_frameBufferSize, args->_viewport));
|
||||
batch.setPipeline(pipeline);
|
||||
|
||||
batch.setUniformBuffer(OUTLINE_PARAMS_SLOT, _configuration);
|
||||
batch.setUniformBuffer(FRAME_TRANSFORM_SLOT, frameTransform->getFrameTransformBuffer());
|
||||
batch.setResourceTexture(SCENE_DEPTH_SLOT, sceneDepthBuffer->getPrimaryDepthTexture());
|
||||
batch.setResourceTexture(OUTLINED_DEPTH_SLOT, outlinedDepthTexture);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
|
||||
// Restore previous frame buffer
|
||||
batch.setFramebuffer(destinationFrameBuffer);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const gpu::PipelinePointer& DrawOutline::getPipeline(bool isFilled) {
|
||||
if (!_pipeline) {
|
||||
auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS();
|
||||
auto ps = gpu::Shader::createPixel(std::string(Outline_frag));
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
||||
|
||||
gpu::Shader::BindingSet slotBindings;
|
||||
slotBindings.insert(gpu::Shader::Binding("outlineParamsBuffer", OUTLINE_PARAMS_SLOT));
|
||||
slotBindings.insert(gpu::Shader::Binding("deferredFrameTransformBuffer", FRAME_TRANSFORM_SLOT));
|
||||
slotBindings.insert(gpu::Shader::Binding("sceneDepthMap", SCENE_DEPTH_SLOT));
|
||||
slotBindings.insert(gpu::Shader::Binding("outlinedDepthMap", OUTLINED_DEPTH_SLOT));
|
||||
gpu::Shader::makeProgram(*program, slotBindings);
|
||||
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(gpu::State::DepthTest(false, false));
|
||||
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
|
||||
_pipeline = gpu::Pipeline::create(program, state);
|
||||
|
||||
ps = gpu::Shader::createPixel(std::string(Outline_filled_frag));
|
||||
program = gpu::Shader::createProgram(vs, ps);
|
||||
gpu::Shader::makeProgram(*program, slotBindings);
|
||||
_pipelineFilled = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
return isFilled ? _pipelineFilled : _pipeline;
|
||||
}
|
||||
|
||||
DebugOutline::DebugOutline() {
|
||||
_geometryId = DependencyManager::get<GeometryCache>()->allocateID();
|
||||
}
|
||||
|
||||
DebugOutline::~DebugOutline() {
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
if (geometryCache) {
|
||||
geometryCache->releaseID(_geometryId);
|
||||
}
|
||||
}
|
||||
|
||||
void DebugOutline::configure(const Config& config) {
|
||||
_isDisplayDepthEnabled = config.viewOutlinedDepth;
|
||||
}
|
||||
|
||||
void DebugOutline::run(const render::RenderContextPointer& renderContext, const Inputs& input) {
|
||||
const auto outlineFramebuffer = input;
|
||||
|
||||
if (_isDisplayDepthEnabled && outlineFramebuffer) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
||||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||
batch.enableStereo(false);
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
|
||||
const auto geometryBuffer = DependencyManager::get<GeometryCache>();
|
||||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->getViewFrustum().evalProjectionMatrix(projMat);
|
||||
args->getViewFrustum().evalViewTransform(viewMat);
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat, true);
|
||||
batch.setModelTransform(Transform());
|
||||
|
||||
batch.setPipeline(getDebugPipeline());
|
||||
batch.setResourceTexture(0, outlineFramebuffer->getDepthTexture());
|
||||
|
||||
const glm::vec4 color(1.0f, 0.5f, 0.2f, 1.0f);
|
||||
const glm::vec2 bottomLeft(-1.0f, -1.0f);
|
||||
const glm::vec2 topRight(1.0f, 1.0f);
|
||||
geometryBuffer->renderQuad(batch, bottomLeft, topRight, color, _geometryId);
|
||||
|
||||
batch.setResourceTexture(0, nullptr);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const gpu::PipelinePointer& DebugOutline::getDebugPipeline() {
|
||||
if (!_debugPipeline) {
|
||||
static const std::string VERTEX_SHADER{ debug_deferred_buffer_vert };
|
||||
static const std::string FRAGMENT_SHADER{ debug_deferred_buffer_frag };
|
||||
static const std::string SOURCE_PLACEHOLDER{ "//SOURCE_PLACEHOLDER" };
|
||||
static const auto SOURCE_PLACEHOLDER_INDEX = FRAGMENT_SHADER.find(SOURCE_PLACEHOLDER);
|
||||
Q_ASSERT_X(SOURCE_PLACEHOLDER_INDEX != std::string::npos, Q_FUNC_INFO,
|
||||
"Could not find source placeholder");
|
||||
static const std::string DEFAULT_DEPTH_SHADER{
|
||||
"vec4 getFragmentColor() {"
|
||||
" float Zdb = texelFetch(depthMap, ivec2(gl_FragCoord.xy), 0).x;"
|
||||
" Zdb = 1.0-(1.0-Zdb)*100;"
|
||||
" return vec4(Zdb, Zdb, Zdb, 1.0);"
|
||||
" }"
|
||||
};
|
||||
|
||||
auto bakedFragmentShader = FRAGMENT_SHADER;
|
||||
bakedFragmentShader.replace(SOURCE_PLACEHOLDER_INDEX, SOURCE_PLACEHOLDER.size(), DEFAULT_DEPTH_SHADER);
|
||||
|
||||
static const auto vs = gpu::Shader::createVertex(VERTEX_SHADER);
|
||||
const auto ps = gpu::Shader::createPixel(bakedFragmentShader);
|
||||
const auto program = gpu::Shader::createProgram(vs, ps);
|
||||
|
||||
gpu::Shader::BindingSet slotBindings;
|
||||
slotBindings.insert(gpu::Shader::Binding("depthMap", 0));
|
||||
gpu::Shader::makeProgram(*program, slotBindings);
|
||||
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
state->setDepthTest(gpu::State::DepthTest(false));
|
||||
_debugPipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
|
||||
return _debugPipeline;
|
||||
}
|
||||
|
||||
DrawOutlineTask::DrawOutlineTask() {
|
||||
|
||||
}
|
||||
|
||||
void DrawOutlineTask::configure(const Config& config) {
|
||||
|
||||
}
|
||||
|
||||
void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) {
|
||||
const auto input = inputs.get<Inputs>();
|
||||
const auto selectedMetas = inputs.getN<Inputs>(0);
|
||||
const auto shapePlumber = input.get1();
|
||||
const auto sceneFrameBuffer = inputs.getN<Inputs>(2);
|
||||
const auto primaryFramebuffer = inputs.getN<Inputs>(3);
|
||||
const auto deferredFrameTransform = inputs.getN<Inputs>(4);
|
||||
|
||||
// Prepare the ShapePipeline
|
||||
ShapePlumberPointer shapePlumberZPass = std::make_shared<ShapePlumber>();
|
||||
{
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
state->setColorWriteMask(false, false, false, false);
|
||||
|
||||
initZPassPipelines(*shapePlumberZPass, state);
|
||||
}
|
||||
|
||||
const auto outlinedItemIDs = task.addJob<render::MetaToSubItems>("OutlineMetaToSubItemIDs", selectedMetas);
|
||||
const auto outlinedItems = task.addJob<render::IDsToBounds>("OutlineMetaToSubItems", outlinedItemIDs, true);
|
||||
|
||||
// Sort
|
||||
const auto sortedPipelines = task.addJob<render::PipelineSortShapes>("OutlinePipelineSort", outlinedItems);
|
||||
const auto sortedShapes = task.addJob<render::DepthSortShapes>("OutlineDepthSort", sortedPipelines);
|
||||
|
||||
// Draw depth of outlined objects in separate buffer
|
||||
const auto drawOutlineDepthInputs = DrawOutlineDepth::Inputs(sortedShapes, sceneFrameBuffer).asVarying();
|
||||
const auto outlinedFrameBuffer = task.addJob<DrawOutlineDepth>("OutlineDepth", drawOutlineDepthInputs, shapePlumberZPass);
|
||||
|
||||
// Draw outline
|
||||
const auto drawOutlineInputs = DrawOutline::Inputs(deferredFrameTransform, outlinedFrameBuffer, sceneFrameBuffer, primaryFramebuffer).asVarying();
|
||||
task.addJob<DrawOutline>("OutlineEffect", drawOutlineInputs);
|
||||
|
||||
// Debug outline
|
||||
task.addJob<DebugOutline>("OutlineDebug", outlinedFrameBuffer);
|
||||
}
|
183
libraries/render-utils/src/OutlineEffect.h
Normal file
183
libraries/render-utils/src/OutlineEffect.h
Normal file
|
@ -0,0 +1,183 @@
|
|||
//
|
||||
// OutlineEffect.h
|
||||
// render-utils/src/
|
||||
//
|
||||
// Created by Olivier Prat on 08/08/17.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_render_utils_OutlineEffect_h
|
||||
#define hifi_render_utils_OutlineEffect_h
|
||||
|
||||
#include <render/Engine.h>
|
||||
#include "DeferredFramebuffer.h"
|
||||
#include "DeferredFrameTransform.h"
|
||||
|
||||
class OutlineFramebuffer {
|
||||
public:
|
||||
OutlineFramebuffer();
|
||||
|
||||
gpu::FramebufferPointer getDepthFramebuffer();
|
||||
gpu::TexturePointer getDepthTexture();
|
||||
|
||||
// Update the source framebuffer size which will drive the allocation of all the other resources.
|
||||
void update(const gpu::TexturePointer& colorBuffer);
|
||||
const glm::ivec2& getSourceFrameSize() const { return _frameSize; }
|
||||
|
||||
protected:
|
||||
|
||||
void clear();
|
||||
void allocate();
|
||||
|
||||
gpu::FramebufferPointer _depthFramebuffer;
|
||||
gpu::TexturePointer _depthTexture;
|
||||
|
||||
glm::ivec2 _frameSize;
|
||||
};
|
||||
|
||||
using OutlineFramebufferPointer = std::shared_ptr<OutlineFramebuffer>;
|
||||
|
||||
class DrawOutlineDepth {
|
||||
public:
|
||||
|
||||
using Inputs = render::VaryingSet2<render::ShapeBounds, DeferredFramebufferPointer>;
|
||||
// Output will contain outlined objects only z-depth texture and the input primary buffer but without the primary depth buffer
|
||||
using Outputs = OutlineFramebufferPointer;
|
||||
using JobModel = render::Job::ModelIO<DrawOutlineDepth, Inputs, Outputs>;
|
||||
|
||||
DrawOutlineDepth(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {}
|
||||
|
||||
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output);
|
||||
|
||||
protected:
|
||||
|
||||
render::ShapePlumberPointer _shapePlumber;
|
||||
OutlineFramebufferPointer _outlineFramebuffer;
|
||||
};
|
||||
|
||||
class DrawOutlineConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool glow MEMBER glow NOTIFY dirty)
|
||||
Q_PROPERTY(float width MEMBER width NOTIFY dirty)
|
||||
Q_PROPERTY(float intensity MEMBER intensity NOTIFY dirty)
|
||||
Q_PROPERTY(float colorR READ getColorR WRITE setColorR NOTIFY dirty)
|
||||
Q_PROPERTY(float colorG READ getColorG WRITE setColorG NOTIFY dirty)
|
||||
Q_PROPERTY(float colorB READ getColorB WRITE setColorB NOTIFY dirty)
|
||||
Q_PROPERTY(float fillOpacityUnoccluded MEMBER fillOpacityUnoccluded NOTIFY dirty)
|
||||
Q_PROPERTY(float fillOpacityOccluded MEMBER fillOpacityOccluded NOTIFY dirty)
|
||||
|
||||
public:
|
||||
|
||||
void setColorR(float value) { color.r = value; emit dirty(); }
|
||||
float getColorR() const { return color.r; }
|
||||
|
||||
void setColorG(float value) { color.g = value; emit dirty(); }
|
||||
float getColorG() const { return color.g; }
|
||||
|
||||
void setColorB(float value) { color.b = value; emit dirty(); }
|
||||
float getColorB() const { return color.b; }
|
||||
|
||||
glm::vec3 color{ 1.f, 0.7f, 0.2f };
|
||||
float width{ 3.f };
|
||||
float intensity{ 1.f };
|
||||
float fillOpacityUnoccluded{ 0.35f };
|
||||
float fillOpacityOccluded{ 0.1f };
|
||||
bool glow{ false };
|
||||
|
||||
signals:
|
||||
void dirty();
|
||||
};
|
||||
|
||||
class DrawOutline {
|
||||
public:
|
||||
using Inputs = render::VaryingSet4<DeferredFrameTransformPointer, OutlineFramebufferPointer, DeferredFramebufferPointer, gpu::FramebufferPointer>;
|
||||
using Config = DrawOutlineConfig;
|
||||
using JobModel = render::Job::ModelI<DrawOutline, Inputs, Config>;
|
||||
|
||||
DrawOutline();
|
||||
|
||||
void configure(const Config& config);
|
||||
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs);
|
||||
|
||||
private:
|
||||
|
||||
enum {
|
||||
SCENE_DEPTH_SLOT = 0,
|
||||
OUTLINED_DEPTH_SLOT,
|
||||
|
||||
OUTLINE_PARAMS_SLOT = 0,
|
||||
FRAME_TRANSFORM_SLOT
|
||||
};
|
||||
|
||||
#include "Outline_shared.slh"
|
||||
|
||||
using OutlineConfigurationBuffer = gpu::StructBuffer<OutlineParameters>;
|
||||
|
||||
const gpu::PipelinePointer& getPipeline(bool isFilled);
|
||||
|
||||
gpu::FramebufferPointer _primaryWithoutDepthBuffer;
|
||||
glm::ivec2 _frameBufferSize {0, 0};
|
||||
gpu::PipelinePointer _pipeline;
|
||||
gpu::PipelinePointer _pipelineFilled;
|
||||
OutlineConfigurationBuffer _configuration;
|
||||
glm::vec3 _color;
|
||||
float _size;
|
||||
int _blurKernelSize;
|
||||
float _intensity;
|
||||
float _fillOpacityUnoccluded;
|
||||
float _fillOpacityOccluded;
|
||||
float _threshold;
|
||||
};
|
||||
|
||||
class DebugOutlineConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool viewOutlinedDepth MEMBER viewOutlinedDepth NOTIFY dirty)
|
||||
|
||||
public:
|
||||
|
||||
bool viewOutlinedDepth{ false };
|
||||
|
||||
signals:
|
||||
void dirty();
|
||||
};
|
||||
|
||||
class DebugOutline {
|
||||
public:
|
||||
using Inputs = OutlineFramebufferPointer;
|
||||
using Config = DebugOutlineConfig;
|
||||
using JobModel = render::Job::ModelI<DebugOutline, Inputs, Config>;
|
||||
|
||||
DebugOutline();
|
||||
~DebugOutline();
|
||||
|
||||
void configure(const Config& config);
|
||||
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs);
|
||||
|
||||
private:
|
||||
|
||||
const gpu::PipelinePointer& getDebugPipeline();
|
||||
|
||||
gpu::PipelinePointer _debugPipeline;
|
||||
int _geometryId{ 0 };
|
||||
bool _isDisplayDepthEnabled{ false };
|
||||
};
|
||||
|
||||
class DrawOutlineTask {
|
||||
public:
|
||||
using Inputs = render::VaryingSet5<render::ItemBounds, render::ShapePlumberPointer, DeferredFramebufferPointer, gpu::FramebufferPointer, DeferredFrameTransformPointer>;
|
||||
using Config = render::Task::Config;
|
||||
using JobModel = render::Task::ModelI<DrawOutlineTask, Inputs, Config>;
|
||||
|
||||
DrawOutlineTask();
|
||||
|
||||
void configure(const Config& config);
|
||||
void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs);
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_render_utils_OutlineEffect_h
|
||||
|
||||
|
13
libraries/render-utils/src/Outline_filled.slf
Normal file
13
libraries/render-utils/src/Outline_filled.slf
Normal file
|
@ -0,0 +1,13 @@
|
|||
// Outline_filled.slf
|
||||
// Add outline effect based on two zbuffers : one containing the total scene z and another
|
||||
// with the z of only the objects to be outlined.
|
||||
// This is the version with the fill effect inside the silhouette.
|
||||
//
|
||||
// Created by Olivier Prat on 09/07/2017
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
<@include Outline.slh@>
|
||||
<$main(1)$>
|
28
libraries/render-utils/src/Outline_shared.slh
Normal file
28
libraries/render-utils/src/Outline_shared.slh
Normal file
|
@ -0,0 +1,28 @@
|
|||
// glsl / C++ compatible source as interface for Outline
|
||||
#ifdef __cplusplus
|
||||
# define VEC2 glm::vec2
|
||||
# define VEC3 glm::vec3
|
||||
#else
|
||||
# define VEC2 vec2
|
||||
# define VEC3 vec3
|
||||
#endif
|
||||
|
||||
struct OutlineParameters
|
||||
{
|
||||
VEC3 _color;
|
||||
float _intensity;
|
||||
|
||||
VEC2 _size;
|
||||
float _fillOpacityUnoccluded;
|
||||
float _fillOpacityOccluded;
|
||||
|
||||
float _threshold;
|
||||
int _blurKernelSize;
|
||||
float padding2;
|
||||
float padding3;
|
||||
};
|
||||
|
||||
// <@if 1@>
|
||||
// Trigger Scribe include
|
||||
// <@endif@> <!def that !>
|
||||
//
|
56
libraries/render-utils/src/PickItemsJob.cpp
Normal file
56
libraries/render-utils/src/PickItemsJob.cpp
Normal file
|
@ -0,0 +1,56 @@
|
|||
//
|
||||
// PickItemsJob.cpp
|
||||
// render-utils/src/
|
||||
//
|
||||
// Created by Olivier Prat on 08/08/17.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#include "PickItemsJob.h"
|
||||
|
||||
PickItemsJob::PickItemsJob(render::ItemKey::Flags validKeys, render::ItemKey::Flags excludeKeys) : _validKeys{ validKeys }, _excludeKeys{ excludeKeys } {
|
||||
}
|
||||
|
||||
void PickItemsJob::configure(const Config& config) {
|
||||
_isEnabled = config.pick;
|
||||
}
|
||||
|
||||
void PickItemsJob::run(const render::RenderContextPointer& renderContext, const PickItemsJob::Input& input, PickItemsJob::Output& output) {
|
||||
output.clear();
|
||||
if (_isEnabled) {
|
||||
float minIsectDistance = std::numeric_limits<float>::max();
|
||||
auto& itemBounds = input;
|
||||
auto item = findNearestItem(renderContext, itemBounds, minIsectDistance);
|
||||
|
||||
if (render::Item::isValidID(item.id)) {
|
||||
output.push_back(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render::ItemBound PickItemsJob::findNearestItem(const render::RenderContextPointer& renderContext, const render::ItemBounds& inputs, float& minIsectDistance) const {
|
||||
const glm::vec3 rayOrigin = renderContext->args->getViewFrustum().getPosition();
|
||||
const glm::vec3 rayDirection = renderContext->args->getViewFrustum().getDirection();
|
||||
BoxFace face;
|
||||
glm::vec3 normal;
|
||||
float isectDistance;
|
||||
render::ItemBound nearestItem( render::Item::INVALID_ITEM_ID );
|
||||
const float minDistance = 0.2f;
|
||||
const float maxDistance = 50.f;
|
||||
render::ItemKey itemKey;
|
||||
|
||||
for (const auto& itemBound : inputs) {
|
||||
if (!itemBound.bound.contains(rayOrigin) && itemBound.bound.findRayIntersection(rayOrigin, rayDirection, isectDistance, face, normal)) {
|
||||
auto& item = renderContext->_scene->getItem(itemBound.id);
|
||||
itemKey = item.getKey();
|
||||
if (itemKey.isWorldSpace() && isectDistance>minDistance && isectDistance < minIsectDistance && isectDistance<maxDistance
|
||||
&& (itemKey._flags & _validKeys)!=0 && (itemKey._flags & _excludeKeys)==0) {
|
||||
nearestItem = itemBound;
|
||||
minIsectDistance = isectDistance;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nearestItem;
|
||||
}
|
55
libraries/render-utils/src/PickItemsJob.h
Normal file
55
libraries/render-utils/src/PickItemsJob.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
//
|
||||
// PickItemsJob.h
|
||||
// render-utils/src/
|
||||
//
|
||||
// Created by Olivier Prat on 08/08/17.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_render_utils_PickItemsJob_h
|
||||
#define hifi_render_utils_PickItemsJob_h
|
||||
|
||||
#include <render/Engine.h>
|
||||
#include <render/Item.h>
|
||||
|
||||
class PickItemsConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool pick MEMBER pick NOTIFY dirty)
|
||||
|
||||
public:
|
||||
|
||||
bool pick{ false };
|
||||
|
||||
signals:
|
||||
void dirty();
|
||||
};
|
||||
|
||||
class PickItemsJob {
|
||||
|
||||
public:
|
||||
|
||||
using Config = PickItemsConfig;
|
||||
using Input = render::ItemBounds;
|
||||
using Output = render::ItemBounds;
|
||||
using JobModel = render::Job::ModelIO<PickItemsJob, Input, Output, Config>;
|
||||
|
||||
PickItemsJob(render::ItemKey::Flags validKeys = render::ItemKey::Builder().withTypeMeta().withTypeShape().build()._flags, render::ItemKey::Flags excludeKeys = 0);
|
||||
|
||||
void configure(const Config& config);
|
||||
void run(const render::RenderContextPointer& renderContext, const PickItemsJob::Input& input, PickItemsJob::Output& output);
|
||||
|
||||
private:
|
||||
|
||||
render::ItemKey::Flags _validKeys;
|
||||
render::ItemKey::Flags _excludeKeys;
|
||||
bool _isEnabled{ false };
|
||||
|
||||
render::ItemBound findNearestItem(const render::RenderContextPointer& renderContext, const render::ItemBounds& inputs, float& minIsectDistance) const;
|
||||
};
|
||||
|
||||
#endif // hifi_render_utils_PickItemsJob_h
|
||||
|
||||
|
|
@ -40,6 +40,7 @@
|
|||
#include "AntialiasingEffect.h"
|
||||
#include "ToneMappingEffect.h"
|
||||
#include "SubsurfaceScattering.h"
|
||||
#include "OutlineEffect.h"
|
||||
|
||||
#include <gpu/StandardShaderLib.h>
|
||||
|
||||
|
@ -93,6 +94,15 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
// draw a stencil mask in hidden regions of the framebuffer.
|
||||
task.addJob<PrepareStencil>("PrepareStencil", primaryFramebuffer);
|
||||
|
||||
// Select items that need to be outlined
|
||||
const auto selectionName = "contextOverlayHighlightList";
|
||||
const auto selectMetaInput = SelectItems::Inputs(metas, Varying()).asVarying();
|
||||
const auto selectedMetas = task.addJob<SelectItems>("PassTestMetaSelection", selectMetaInput, selectionName);
|
||||
const auto selectMetaAndOpaqueInput = SelectItems::Inputs(opaques, selectedMetas).asVarying();
|
||||
const auto selectedMetasAndOpaques = task.addJob<SelectItems>("PassTestOpaqueSelection", selectMetaAndOpaqueInput, selectionName);
|
||||
const auto selectItemInput = SelectItems::Inputs(transparents, selectedMetasAndOpaques).asVarying();
|
||||
const auto selectedItems = task.addJob<SelectItems>("PassTestTransparentSelection", selectItemInput, selectionName);
|
||||
|
||||
// Render opaque objects in DeferredBuffer
|
||||
const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel).asVarying();
|
||||
task.addJob<DrawStateSortDeferred>("DrawOpaqueDeferred", opaqueInputs, shapePlumber);
|
||||
|
@ -159,10 +169,15 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
const auto toneAndPostRangeTimer = task.addJob<BeginGPURangeTimer>("BeginToneAndPostRangeTimer", "PostToneOverlaysAntialiasing");
|
||||
|
||||
// Lighting Buffer ready for tone mapping
|
||||
const auto toneMappingInputs = render::Varying(ToneMappingDeferred::Inputs(lightingFramebuffer, primaryFramebuffer));
|
||||
const auto toneMappingInputs = ToneMappingDeferred::Inputs(lightingFramebuffer, primaryFramebuffer).asVarying();
|
||||
task.addJob<ToneMappingDeferred>("ToneMapping", toneMappingInputs);
|
||||
|
||||
{ // Debug the bounds of the rendered items, still look at the zbuffer
|
||||
const auto outlineRangeTimer = task.addJob<BeginGPURangeTimer>("BeginOutlineRangeTimer", "Outline");
|
||||
const auto outlineInputs = DrawOutlineTask::Inputs(selectedItems, shapePlumber, deferredFramebuffer, primaryFramebuffer, deferredFrameTransform).asVarying();
|
||||
task.addJob<DrawOutlineTask>("DrawOutline", outlineInputs);
|
||||
task.addJob<EndGPURangeTimer>("EndOutlineRangeTimer", outlineRangeTimer);
|
||||
|
||||
{ // DEbug the bounds of the rendered items, still look at the zbuffer
|
||||
task.addJob<DrawBounds>("DrawMetaBounds", metas);
|
||||
task.addJob<DrawBounds>("DrawOpaqueBounds", opaques);
|
||||
task.addJob<DrawBounds>("DrawTransparentBounds", transparents);
|
||||
|
@ -212,8 +227,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
task.addJob<DebugZoneLighting>("DrawZoneStack", deferredFrameTransform);
|
||||
|
||||
// Render.getConfig("RenderMainView.DrawSelectionBounds").enabled = true
|
||||
const auto selectedMetas = task.addJob<SelectItems>("PassTestSelection", metas, "contextOverlayHighlightList");
|
||||
task.addJob<DrawBounds>("DrawSelectionBounds", selectedMetas);
|
||||
task.addJob<DrawBounds>("DrawSelectionBounds", selectedItems);
|
||||
}
|
||||
|
||||
// AA job to be revisited
|
||||
|
|
|
@ -21,19 +21,15 @@
|
|||
#include "render/DrawTask.h"
|
||||
|
||||
#include "model_vert.h"
|
||||
#include "model_shadow_vert.h"
|
||||
#include "model_normal_map_vert.h"
|
||||
#include "model_lightmap_vert.h"
|
||||
#include "model_lightmap_normal_map_vert.h"
|
||||
#include "skin_model_vert.h"
|
||||
#include "skin_model_shadow_vert.h"
|
||||
#include "skin_model_normal_map_vert.h"
|
||||
|
||||
#include "model_shadow_fade_vert.h"
|
||||
#include "model_lightmap_fade_vert.h"
|
||||
#include "model_lightmap_normal_map_fade_vert.h"
|
||||
#include "skin_model_fade_vert.h"
|
||||
#include "skin_model_shadow_fade_vert.h"
|
||||
#include "skin_model_normal_map_fade_vert.h"
|
||||
|
||||
#include "simple_vert.h"
|
||||
|
@ -50,7 +46,6 @@
|
|||
|
||||
#include "model_frag.h"
|
||||
#include "model_unlit_frag.h"
|
||||
#include "model_shadow_frag.h"
|
||||
#include "model_normal_map_frag.h"
|
||||
#include "model_normal_specular_map_frag.h"
|
||||
#include "model_specular_map_frag.h"
|
||||
|
@ -59,7 +54,6 @@
|
|||
#include "model_normal_map_fade_vert.h"
|
||||
|
||||
#include "model_fade_frag.h"
|
||||
#include "model_shadow_fade_frag.h"
|
||||
#include "model_unlit_fade_frag.h"
|
||||
#include "model_normal_map_fade_frag.h"
|
||||
#include "model_normal_specular_map_fade_frag.h"
|
||||
|
@ -95,6 +89,17 @@
|
|||
#include "overlay3D_model_unlit_frag.h"
|
||||
#include "overlay3D_model_translucent_unlit_frag.h"
|
||||
|
||||
#include "model_shadow_vert.h"
|
||||
#include "skin_model_shadow_vert.h"
|
||||
|
||||
#include "model_shadow_frag.h"
|
||||
#include "skin_model_shadow_frag.h"
|
||||
|
||||
#include "model_shadow_fade_vert.h"
|
||||
#include "skin_model_shadow_fade_vert.h"
|
||||
|
||||
#include "model_shadow_fade_frag.h"
|
||||
#include "skin_model_shadow_fade_frag.h"
|
||||
|
||||
using namespace render;
|
||||
using namespace std::placeholders;
|
||||
|
@ -102,6 +107,7 @@ using namespace std::placeholders;
|
|||
void initOverlay3DPipelines(ShapePlumber& plumber, bool depthTest = false);
|
||||
void initDeferredPipelines(ShapePlumber& plumber, const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter);
|
||||
void initForwardPipelines(ShapePlumber& plumber);
|
||||
void initZPassPipelines(ShapePlumber& plumber, gpu::StatePointer state);
|
||||
|
||||
void addPlumberPipeline(ShapePlumber& plumber,
|
||||
const ShapeKey& key, const gpu::ShaderPointer& vertex, const gpu::ShaderPointer& pixel,
|
||||
|
@ -566,3 +572,33 @@ void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderAr
|
|||
pipeline.locations->lightAmbientMapUnit);
|
||||
}
|
||||
}
|
||||
|
||||
void initZPassPipelines(ShapePlumber& shapePlumber, gpu::StatePointer state) {
|
||||
auto modelVertex = gpu::Shader::createVertex(std::string(model_shadow_vert));
|
||||
auto modelPixel = gpu::Shader::createPixel(std::string(model_shadow_frag));
|
||||
gpu::ShaderPointer modelProgram = gpu::Shader::createProgram(modelVertex, modelPixel);
|
||||
shapePlumber.addPipeline(
|
||||
ShapeKey::Filter::Builder().withoutSkinned().withoutFade(),
|
||||
modelProgram, state);
|
||||
|
||||
auto skinVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert));
|
||||
auto skinPixel = gpu::Shader::createPixel(std::string(skin_model_shadow_frag));
|
||||
gpu::ShaderPointer skinProgram = gpu::Shader::createProgram(skinVertex, skinPixel);
|
||||
shapePlumber.addPipeline(
|
||||
ShapeKey::Filter::Builder().withSkinned().withoutFade(),
|
||||
skinProgram, state);
|
||||
|
||||
auto modelFadeVertex = gpu::Shader::createVertex(std::string(model_shadow_fade_vert));
|
||||
auto modelFadePixel = gpu::Shader::createPixel(std::string(model_shadow_fade_frag));
|
||||
gpu::ShaderPointer modelFadeProgram = gpu::Shader::createProgram(modelFadeVertex, modelFadePixel);
|
||||
shapePlumber.addPipeline(
|
||||
ShapeKey::Filter::Builder().withoutSkinned().withFade(),
|
||||
modelFadeProgram, state);
|
||||
|
||||
auto skinFadeVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_fade_vert));
|
||||
auto skinFadePixel = gpu::Shader::createPixel(std::string(skin_model_shadow_fade_frag));
|
||||
gpu::ShaderPointer skinFadeProgram = gpu::Shader::createProgram(skinFadeVertex, skinFadePixel);
|
||||
shapePlumber.addPipeline(
|
||||
ShapeKey::Filter::Builder().withSkinned().withFade(),
|
||||
skinFadeProgram, state);
|
||||
}
|
||||
|
|
|
@ -22,20 +22,10 @@
|
|||
#include "DeferredLightingEffect.h"
|
||||
#include "FramebufferCache.h"
|
||||
|
||||
#include "model_shadow_vert.h"
|
||||
#include "skin_model_shadow_vert.h"
|
||||
|
||||
#include "model_shadow_frag.h"
|
||||
#include "skin_model_shadow_frag.h"
|
||||
|
||||
#include "model_shadow_fade_vert.h"
|
||||
#include "skin_model_shadow_fade_vert.h"
|
||||
|
||||
#include "model_shadow_fade_frag.h"
|
||||
#include "skin_model_shadow_fade_frag.h"
|
||||
|
||||
using namespace render;
|
||||
|
||||
extern void initZPassPipelines(ShapePlumber& plumber, gpu::StatePointer state);
|
||||
|
||||
void RenderShadowMap::run(const render::RenderContextPointer& renderContext,
|
||||
const render::ShapeBounds& inShapes) {
|
||||
assert(renderContext->args);
|
||||
|
@ -108,33 +98,7 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende
|
|||
state->setCullMode(gpu::State::CULL_BACK);
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
|
||||
auto modelVertex = gpu::Shader::createVertex(std::string(model_shadow_vert));
|
||||
auto modelPixel = gpu::Shader::createPixel(std::string(model_shadow_frag));
|
||||
gpu::ShaderPointer modelProgram = gpu::Shader::createProgram(modelVertex, modelPixel);
|
||||
shapePlumber->addPipeline(
|
||||
ShapeKey::Filter::Builder().withoutSkinned().withoutFade(),
|
||||
modelProgram, state);
|
||||
|
||||
auto skinVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert));
|
||||
auto skinPixel = gpu::Shader::createPixel(std::string(skin_model_shadow_frag));
|
||||
gpu::ShaderPointer skinProgram = gpu::Shader::createProgram(skinVertex, skinPixel);
|
||||
shapePlumber->addPipeline(
|
||||
ShapeKey::Filter::Builder().withSkinned().withoutFade(),
|
||||
skinProgram, state);
|
||||
|
||||
auto modelFadeVertex = gpu::Shader::createVertex(std::string(model_shadow_fade_vert));
|
||||
auto modelFadePixel = gpu::Shader::createPixel(std::string(model_shadow_fade_frag));
|
||||
gpu::ShaderPointer modelFadeProgram = gpu::Shader::createProgram(modelFadeVertex, modelFadePixel);
|
||||
shapePlumber->addPipeline(
|
||||
ShapeKey::Filter::Builder().withoutSkinned().withFade(),
|
||||
modelFadeProgram, state);
|
||||
|
||||
auto skinFadeVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_fade_vert));
|
||||
auto skinFadePixel = gpu::Shader::createPixel(std::string(skin_model_shadow_fade_frag));
|
||||
gpu::ShaderPointer skinFadeProgram = gpu::Shader::createProgram(skinFadeVertex, skinFadePixel);
|
||||
shapePlumber->addPipeline(
|
||||
ShapeKey::Filter::Builder().withSkinned().withFade(),
|
||||
skinFadeProgram, state);
|
||||
initZPassPipelines(*shapePlumber, state);
|
||||
}
|
||||
|
||||
const auto cachedMode = task.addJob<RenderShadowSetup>("ShadowSetup");
|
||||
|
|
20
libraries/render-utils/src/surfaceGeometry_copyDepth.slf
Normal file
20
libraries/render-utils/src/surfaceGeometry_copyDepth.slf
Normal file
|
@ -0,0 +1,20 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// Created by Olivier Prat on 08/08/17.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
uniform sampler2D depthMap;
|
||||
|
||||
out vec4 outFragColor;
|
||||
|
||||
void main(void) {
|
||||
float Zdb = texelFetch(depthMap, ivec2(gl_FragCoord.xy), 0).x;
|
||||
outFragColor = vec4(Zdb, 0.0, 0.0, 1.0);
|
||||
}
|
||||
|
|
@ -9,6 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <LogHandler.h>
|
||||
|
||||
#include "DrawTask.h"
|
||||
#include "Logging.h"
|
||||
|
||||
|
@ -48,12 +50,14 @@ void renderShape(RenderArgs* args, const ShapePlumberPointer& shapeContext, cons
|
|||
if (args->_shapePipeline) {
|
||||
args->_shapePipeline->prepareShapeItem(args, key, item);
|
||||
item.render(args);
|
||||
}
|
||||
}
|
||||
args->_shapePipeline = nullptr;
|
||||
} else if (key.hasOwnPipeline()) {
|
||||
item.render(args);
|
||||
} else {
|
||||
qCDebug(renderlogging) << "Item could not be rendered with invalid key" << key;
|
||||
static QString repeatedCouldNotBeRendered = LogHandler::getInstance().addRepeatedMessageRegex(
|
||||
"Item could not be rendered with invalid key.*");
|
||||
}
|
||||
args->_itemShapeKey = 0;
|
||||
}
|
||||
|
@ -62,7 +66,7 @@ void render::renderShapes(const RenderContextPointer& renderContext,
|
|||
const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, int maxDrawnItems, const ShapeKey& globalKey) {
|
||||
auto& scene = renderContext->_scene;
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
||||
|
||||
int numItemsToDraw = (int)inItems.size();
|
||||
if (maxDrawnItems != -1) {
|
||||
numItemsToDraw = glm::min(numItemsToDraw, maxDrawnItems);
|
||||
|
@ -104,6 +108,8 @@ void render::renderStateSortShapes(const RenderContextPointer& renderContext,
|
|||
} else if (key.hasOwnPipeline()) {
|
||||
ownPipelineBucket.push_back( std::make_tuple(item, key) );
|
||||
} else {
|
||||
static QString repeatedCouldNotBeRendered = LogHandler::getInstance().addRepeatedMessageRegex(
|
||||
"Item could not be rendered with invalid key.*");
|
||||
qCDebug(renderlogging) << "Item could not be rendered with invalid key" << key;
|
||||
}
|
||||
}
|
||||
|
@ -113,7 +119,7 @@ void render::renderStateSortShapes(const RenderContextPointer& renderContext,
|
|||
for (auto& pipelineKey : sortedPipelines) {
|
||||
auto& bucket = sortedShapes[pipelineKey];
|
||||
args->_shapePipeline = shapeContext->pickPipeline(args, pipelineKey);
|
||||
if (!args->_shapePipeline) {
|
||||
if (!args->_shapePipeline) {
|
||||
continue;
|
||||
}
|
||||
args->_itemShapeKey = pipelineKey._flags.to_ulong();
|
||||
|
@ -182,7 +188,7 @@ void DrawBounds::run(const RenderContextPointer& renderContext,
|
|||
if (!_drawBuffer) {
|
||||
_drawBuffer = std::make_shared<gpu::Buffer>(sizeOfItemBound);
|
||||
}
|
||||
|
||||
|
||||
_drawBuffer->setData(numItems * sizeOfItemBound, (const gpu::Byte*) items.data());
|
||||
|
||||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||
|
|
|
@ -51,13 +51,20 @@ void SliceItems::run(const RenderContextPointer& renderContext, const ItemBounds
|
|||
|
||||
}
|
||||
|
||||
void SelectItems::run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems) {
|
||||
void SelectItems::run(const RenderContextPointer& renderContext, const Inputs& inputs, ItemBounds& outItems) {
|
||||
auto selection = renderContext->_scene->getSelection(_name);
|
||||
const auto& selectedItems = selection.getItems();
|
||||
outItems.clear();
|
||||
const auto& inItems = inputs.get0();
|
||||
const auto itemsToAppend = inputs[1];
|
||||
|
||||
if (itemsToAppend.isNull()) {
|
||||
outItems.clear();
|
||||
} else {
|
||||
outItems = itemsToAppend.get<ItemBounds>();
|
||||
}
|
||||
|
||||
if (!selectedItems.empty()) {
|
||||
outItems.reserve(selectedItems.size());
|
||||
outItems.reserve(outItems.size()+selectedItems.size());
|
||||
|
||||
for (auto src : inItems) {
|
||||
if (selection.contains(src.id)) {
|
||||
|
@ -111,3 +118,21 @@ void MetaToSubItems::run(const RenderContextPointer& renderContext, const ItemBo
|
|||
}
|
||||
}
|
||||
|
||||
void IDsToBounds::run(const RenderContextPointer& renderContext, const ItemIDs& inItems, ItemBounds& outItems) {
|
||||
auto& scene = renderContext->_scene;
|
||||
|
||||
// Now we have a selection of items to render
|
||||
outItems.clear();
|
||||
|
||||
if (!_disableAABBs) {
|
||||
for (auto id : inItems) {
|
||||
auto& item = scene->getItem(id);
|
||||
|
||||
outItems.emplace_back(ItemBound{ id, item.getBound() });
|
||||
}
|
||||
} else {
|
||||
for (auto id : inItems) {
|
||||
outItems.emplace_back(ItemBound{ id });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,22 +113,23 @@ namespace render {
|
|||
// Keep items belonging to the job selection
|
||||
class SelectItems {
|
||||
public:
|
||||
using JobModel = Job::ModelIO<SelectItems, ItemBounds, ItemBounds>;
|
||||
using Inputs = VaryingSet2<ItemBounds, ItemBounds>;
|
||||
using JobModel = Job::ModelIO<SelectItems, Inputs, ItemBounds>;
|
||||
|
||||
std::string _name;
|
||||
SelectItems(const Selection::Name& name) : _name(name) {}
|
||||
|
||||
void run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems);
|
||||
void run(const RenderContextPointer& renderContext, const Inputs& inputs, ItemBounds& outItems);
|
||||
};
|
||||
|
||||
// Same as SelectItems but reorder the output to match the selection order
|
||||
class SelectSortItems {
|
||||
public:
|
||||
using JobModel = Job::ModelIO<SelectSortItems, ItemBounds, ItemBounds>;
|
||||
|
||||
|
||||
std::string _name;
|
||||
SelectSortItems(const Selection::Name& name) : _name(name) {}
|
||||
|
||||
|
||||
void run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems);
|
||||
};
|
||||
|
||||
|
@ -142,6 +143,19 @@ namespace render {
|
|||
void run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemIDs& outItems);
|
||||
};
|
||||
|
||||
// From item IDs build item bounds
|
||||
class IDsToBounds {
|
||||
public:
|
||||
using JobModel = Job::ModelIO<IDsToBounds, ItemIDs, ItemBounds>;
|
||||
|
||||
IDsToBounds(bool disableAABBs = false) : _disableAABBs(disableAABBs) {}
|
||||
|
||||
void run(const RenderContextPointer& renderContext, const ItemIDs& inItems, ItemBounds& outItems);
|
||||
|
||||
private:
|
||||
bool _disableAABBs{ false };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // hifi_render_FilterTask_h;
|
|
@ -238,6 +238,24 @@ public:
|
|||
const T5& get5() const { return std::get<5>((*this)).template get<T5>(); }
|
||||
T5& edit5() { return std::get<5>((*this)).template edit<T5>(); }
|
||||
|
||||
virtual Varying operator[] (uint8_t index) const {
|
||||
switch (index) {
|
||||
default:
|
||||
return std::get<0>((*this));
|
||||
case 1:
|
||||
return std::get<1>((*this));
|
||||
case 2:
|
||||
return std::get<2>((*this));
|
||||
case 3:
|
||||
return std::get<3>((*this));
|
||||
case 4:
|
||||
return std::get<4>((*this));
|
||||
case 5:
|
||||
return std::get<5>((*this));
|
||||
};
|
||||
}
|
||||
virtual uint8_t length() const { return 6; }
|
||||
|
||||
Varying asVarying() const { return Varying((*this)); }
|
||||
};
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ float Interpolate::simpleNonLinearBlend(float fraction) {
|
|||
}
|
||||
|
||||
float Interpolate::calculateFadeRatio(quint64 start) {
|
||||
const float FADE_TIME = 1.0f;
|
||||
const float FADE_TIME = 0.5f;
|
||||
float t = 2.0f * std::min(((float)(usecTimestampNow() - start)) / ((float)(FADE_TIME * USECS_PER_SECOND)), 1.0f);
|
||||
float fadeRatio = (t < 1.0f) ? 0.5f * powf(2.0f, 10.0f * (t - 1.0f)) : 0.5f * (-powf(2.0f, -10.0f * (t - 1.0f)) + 2.0f);
|
||||
|
||||
|
|
|
@ -528,6 +528,12 @@ void OffscreenQmlSurface::create() {
|
|||
|
||||
connect(_quickWindow, &QQuickWindow::focusObjectChanged, this, &OffscreenQmlSurface::onFocusObjectChanged);
|
||||
|
||||
// acquireEngine interrogates the GL context, so we need to have the context current here
|
||||
if (!_canvas->makeCurrent()) {
|
||||
qFatal("Failed to make context current for QML Renderer");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a QML engine.
|
||||
auto qmlEngine = acquireEngine(_quickWindow);
|
||||
|
||||
|
@ -540,11 +546,6 @@ void OffscreenQmlSurface::create() {
|
|||
// FIXME Compatibility mechanism for existing HTML and JS that uses eventBridgeWrapper
|
||||
// Find a way to flag older scripts using this mechanism and wanr that this is deprecated
|
||||
_qmlContext->setContextProperty("eventBridgeWrapper", new EventBridgeWrapper(this, _qmlContext));
|
||||
|
||||
if (!_canvas->makeCurrent()) {
|
||||
qWarning("Failed to make context current for QML Renderer");
|
||||
return;
|
||||
}
|
||||
_renderControl->initialize(_canvas->getContext());
|
||||
|
||||
// When Quick says there is a need to render, we will not render immediately. Instead,
|
||||
|
@ -639,7 +640,7 @@ void OffscreenQmlSurface::setBaseUrl(const QUrl& baseUrl) {
|
|||
_qmlContext->setBaseUrl(baseUrl);
|
||||
}
|
||||
|
||||
void OffscreenQmlSurface::load(const QUrl& qmlSource, bool createNewContext, std::function<void(QQmlContext*, QObject*)> f) {
|
||||
void OffscreenQmlSurface::load(const QUrl& qmlSource, bool createNewContext, std::function<void(QQmlContext*, QObject*)> onQmlLoadedCallback) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
qCWarning(uiLogging) << "Called load on a non-surface thread";
|
||||
}
|
||||
|
@ -659,28 +660,28 @@ void OffscreenQmlSurface::load(const QUrl& qmlSource, bool createNewContext, std
|
|||
auto qmlComponent = new QQmlComponent(_qmlContext->engine(), finalQmlSource, QQmlComponent::PreferSynchronous);
|
||||
if (qmlComponent->isLoading()) {
|
||||
connect(qmlComponent, &QQmlComponent::statusChanged, this,
|
||||
[this, qmlComponent, targetContext, f](QQmlComponent::Status) {
|
||||
finishQmlLoad(qmlComponent, targetContext, f);
|
||||
[this, qmlComponent, targetContext, onQmlLoadedCallback](QQmlComponent::Status) {
|
||||
finishQmlLoad(qmlComponent, targetContext, onQmlLoadedCallback);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
finishQmlLoad(qmlComponent, targetContext, f);
|
||||
finishQmlLoad(qmlComponent, targetContext, onQmlLoadedCallback);
|
||||
}
|
||||
|
||||
void OffscreenQmlSurface::loadInNewContext(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f) {
|
||||
load(qmlSource, true, f);
|
||||
void OffscreenQmlSurface::loadInNewContext(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> onQmlLoadedCallback) {
|
||||
load(qmlSource, true, onQmlLoadedCallback);
|
||||
}
|
||||
|
||||
void OffscreenQmlSurface::load(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f) {
|
||||
load(qmlSource, false, f);
|
||||
void OffscreenQmlSurface::load(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> onQmlLoadedCallback) {
|
||||
load(qmlSource, false, onQmlLoadedCallback);
|
||||
}
|
||||
|
||||
void OffscreenQmlSurface::clearCache() {
|
||||
_qmlContext->engine()->clearComponentCache();
|
||||
}
|
||||
|
||||
void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, std::function<void(QQmlContext*, QObject*)> f) {
|
||||
void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, std::function<void(QQmlContext*, QObject*)> onQmlLoadedCallback) {
|
||||
disconnect(qmlComponent, &QQmlComponent::statusChanged, this, 0);
|
||||
if (qmlComponent->isError()) {
|
||||
for (const auto& error : qmlComponent->errors()) {
|
||||
|
@ -690,7 +691,6 @@ void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
QObject* newObject = qmlComponent->beginCreate(qmlContext);
|
||||
if (qmlComponent->isError()) {
|
||||
for (const auto& error : qmlComponent->errors()) {
|
||||
|
@ -704,7 +704,20 @@ void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext
|
|||
}
|
||||
|
||||
qmlContext->engine()->setObjectOwnership(this, QQmlEngine::CppOwnership);
|
||||
f(qmlContext, newObject);
|
||||
|
||||
// All quick items should be focusable
|
||||
QQuickItem* newItem = qobject_cast<QQuickItem*>(newObject);
|
||||
if (newItem) {
|
||||
// Make sure we make items focusable (critical for
|
||||
// supporting keyboard shortcuts)
|
||||
newItem->setFlag(QQuickItem::ItemIsFocusScope, true);
|
||||
}
|
||||
|
||||
// Make sure we will call callback for this codepath
|
||||
// Call this before qmlComponent->completeCreate() otherwise ghost window appears
|
||||
if (newItem && _rootItem) {
|
||||
onQmlLoadedCallback(qmlContext, newObject);
|
||||
}
|
||||
|
||||
QObject* eventBridge = qmlContext->contextProperty("eventBridge").value<QObject*>();
|
||||
if (qmlContext != _qmlContext && eventBridge && eventBridge != this) {
|
||||
|
@ -716,15 +729,6 @@ void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext
|
|||
qmlComponent->completeCreate();
|
||||
qmlComponent->deleteLater();
|
||||
|
||||
|
||||
// All quick items should be focusable
|
||||
QQuickItem* newItem = qobject_cast<QQuickItem*>(newObject);
|
||||
if (newItem) {
|
||||
// Make sure we make items focusable (critical for
|
||||
// supporting keyboard shortcuts)
|
||||
newItem->setFlag(QQuickItem::ItemIsFocusScope, true);
|
||||
}
|
||||
|
||||
// If we already have a root, just set a couple of flags and the ancestry
|
||||
if (newItem && _rootItem) {
|
||||
// Allow child windows to be destroyed from JS
|
||||
|
@ -747,6 +751,8 @@ void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext
|
|||
_rootItem = newItem;
|
||||
_rootItem->setParentItem(_quickWindow->contentItem());
|
||||
_rootItem->setSize(_quickWindow->renderTargetSize());
|
||||
// Call this callback after rootitem is set, otherwise VrMenu wont work
|
||||
onQmlLoadedCallback(qmlContext, newObject);
|
||||
}
|
||||
|
||||
void OffscreenQmlSurface::updateQuick() {
|
||||
|
|
|
@ -50,11 +50,11 @@ public:
|
|||
void resize(const QSize& size, bool forceResize = false);
|
||||
QSize size() const;
|
||||
|
||||
Q_INVOKABLE void load(const QUrl& qmlSource, bool createNewContext, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
|
||||
Q_INVOKABLE void loadInNewContext(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
|
||||
Q_INVOKABLE void load(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
|
||||
Q_INVOKABLE void load(const QString& qmlSourceFile, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {}) {
|
||||
return load(QUrl(qmlSourceFile), f);
|
||||
Q_INVOKABLE void load(const QUrl& qmlSource, bool createNewContext, std::function<void(QQmlContext*, QObject*)> onQmlLoadedCallback = [](QQmlContext*, QObject*) {});
|
||||
Q_INVOKABLE void loadInNewContext(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> onQmlLoadedCallback = [](QQmlContext*, QObject*) {});
|
||||
Q_INVOKABLE void load(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> onQmlLoadedCallback = [](QQmlContext*, QObject*) {});
|
||||
Q_INVOKABLE void load(const QString& qmlSourceFile, std::function<void(QQmlContext*, QObject*)> onQmlLoadedCallback = [](QQmlContext*, QObject*) {}) {
|
||||
return load(QUrl(qmlSourceFile), onQmlLoadedCallback);
|
||||
}
|
||||
void clearCache();
|
||||
void setMaxFps(uint8_t maxFps) { _maxFps = maxFps; }
|
||||
|
@ -120,7 +120,7 @@ protected:
|
|||
private:
|
||||
static QOpenGLContext* getSharedContext();
|
||||
|
||||
void finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, std::function<void(QQmlContext*, QObject*)> f);
|
||||
void finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, std::function<void(QQmlContext*, QObject*)> onQmlLoadedCallback);
|
||||
QPointF mapWindowToUi(const QPointF& sourcePosition, QObject* sourceObject);
|
||||
void setupFbo();
|
||||
bool allowNewFrame(uint8_t fps);
|
||||
|
|
|
@ -54,49 +54,6 @@ SDL_JoystickID SDL2Manager::getInstanceId(SDL_GameController* controller) {
|
|||
}
|
||||
|
||||
void SDL2Manager::init() {
|
||||
loadSettings();
|
||||
|
||||
auto preferences = DependencyManager::get<Preferences>();
|
||||
static const QString SDL2_PLUGIN { "Game Controller" };
|
||||
{
|
||||
auto getter = [this]()->bool { return _isEnabled; };
|
||||
auto setter = [this](bool value) {
|
||||
_isEnabled = value;
|
||||
saveSettings();
|
||||
};
|
||||
auto preference = new CheckPreference(SDL2_PLUGIN, "Enabled", getter, setter);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
|
||||
bool initSuccess = (SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC) == 0);
|
||||
|
||||
if (initSuccess) {
|
||||
int joystickCount = SDL_NumJoysticks();
|
||||
|
||||
for (int i = 0; i < joystickCount; i++) {
|
||||
SDL_GameController* controller = SDL_GameControllerOpen(i);
|
||||
|
||||
if (controller) {
|
||||
SDL_JoystickID id = getInstanceId(controller);
|
||||
if (!_openJoysticks.contains(id)) {
|
||||
//Joystick* joystick = new Joystick(id, SDL_GameControllerName(controller), controller);
|
||||
Joystick::Pointer joystick = std::make_shared<Joystick>(id, controller);
|
||||
_openJoysticks[id] = joystick;
|
||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||
userInputMapper->registerDevice(joystick);
|
||||
auto name = SDL_GameControllerName(controller);
|
||||
_subdeviceNames << name;
|
||||
emit joystickAdded(joystick.get());
|
||||
emit subdeviceConnected(getName(), name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_isInitialized = true;
|
||||
}
|
||||
else {
|
||||
qDebug() << "Error initializing SDL2 Manager";
|
||||
}
|
||||
}
|
||||
|
||||
QStringList SDL2Manager::getSubdeviceNames() {
|
||||
|
@ -110,8 +67,61 @@ void SDL2Manager::deinit() {
|
|||
}
|
||||
|
||||
bool SDL2Manager::activate() {
|
||||
|
||||
// FIXME for some reason calling this code in the `init` function triggers a crash
|
||||
// on OSX in PR builds, but not on my local debug build. Attempting a workaround by
|
||||
//
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [&]{
|
||||
loadSettings();
|
||||
|
||||
auto preferences = DependencyManager::get<Preferences>();
|
||||
static const QString SDL2_PLUGIN { "Game Controller" };
|
||||
{
|
||||
auto getter = [this]()->bool { return _isEnabled; };
|
||||
auto setter = [this](bool value) {
|
||||
_isEnabled = value;
|
||||
saveSettings();
|
||||
};
|
||||
auto preference = new CheckPreference(SDL2_PLUGIN, "Enabled", getter, setter);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
|
||||
bool initSuccess = (SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC) == 0);
|
||||
|
||||
if (initSuccess) {
|
||||
int joystickCount = SDL_NumJoysticks();
|
||||
|
||||
for (int i = 0; i < joystickCount; i++) {
|
||||
SDL_GameController* controller = SDL_GameControllerOpen(i);
|
||||
|
||||
if (controller) {
|
||||
SDL_JoystickID id = getInstanceId(controller);
|
||||
if (!_openJoysticks.contains(id)) {
|
||||
//Joystick* joystick = new Joystick(id, SDL_GameControllerName(controller), controller);
|
||||
Joystick::Pointer joystick = std::make_shared<Joystick>(id, controller);
|
||||
_openJoysticks[id] = joystick;
|
||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||
userInputMapper->registerDevice(joystick);
|
||||
auto name = SDL_GameControllerName(controller);
|
||||
_subdeviceNames << name;
|
||||
emit joystickAdded(joystick.get());
|
||||
emit subdeviceConnected(getName(), name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_isInitialized = true;
|
||||
} else {
|
||||
qDebug() << "Error initializing SDL2 Manager";
|
||||
}
|
||||
});
|
||||
|
||||
if (!_isInitialized) {
|
||||
return false;
|
||||
}
|
||||
|
||||
InputPlugin::activate();
|
||||
|
||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||
for (auto joystick : _openJoysticks) {
|
||||
userInputMapper->registerDevice(joystick);
|
||||
|
|
20
scripts/developer/utilities/render/debugOutline.js
Normal file
20
scripts/developer/utilities/render/debugOutline.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
//
|
||||
// debugOutline.js
|
||||
// developer/utilities/render
|
||||
//
|
||||
// Olivier Prat, created on 08/08/2017.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
// Set up the qml ui
|
||||
var qml = Script.resolvePath('outline.qml');
|
||||
var window = new OverlayWindow({
|
||||
title: 'Outline',
|
||||
source: qml,
|
||||
width: 285,
|
||||
height: 370,
|
||||
});
|
||||
window.closed.connect(function() { Script.stop(); });
|
119
scripts/developer/utilities/render/outline.qml
Normal file
119
scripts/developer/utilities/render/outline.qml
Normal file
|
@ -0,0 +1,119 @@
|
|||
//
|
||||
// outline.qml
|
||||
// developer/utilities/render
|
||||
//
|
||||
// Olivier Prat, created on 08/08/2017.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import "configSlider"
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property var debugConfig: Render.getConfig("RenderMainView.OutlineDebug")
|
||||
property var drawConfig: Render.getConfig("RenderMainView.OutlineEffect")
|
||||
|
||||
Column {
|
||||
spacing: 8
|
||||
|
||||
CheckBox {
|
||||
text: "View Outlined Depth"
|
||||
checked: root.debugConfig["viewOutlinedDepth"]
|
||||
onCheckedChanged: {
|
||||
root.debugConfig["viewOutlinedDepth"] = checked;
|
||||
}
|
||||
}
|
||||
CheckBox {
|
||||
text: "Glow"
|
||||
checked: root.drawConfig["glow"]
|
||||
onCheckedChanged: {
|
||||
root.drawConfig["glow"] = checked;
|
||||
}
|
||||
}
|
||||
ConfigSlider {
|
||||
label: "Width"
|
||||
integral: false
|
||||
config: root.drawConfig
|
||||
property: "width"
|
||||
max: 15.0
|
||||
min: 0.0
|
||||
width: 280
|
||||
}
|
||||
ConfigSlider {
|
||||
label: "Intensity"
|
||||
integral: false
|
||||
config: root.drawConfig
|
||||
property: "intensity"
|
||||
max: 1.0
|
||||
min: 0.0
|
||||
width: 280
|
||||
}
|
||||
|
||||
GroupBox {
|
||||
title: "Color"
|
||||
width: 280
|
||||
Column {
|
||||
spacing: 8
|
||||
|
||||
ConfigSlider {
|
||||
label: "Red"
|
||||
integral: false
|
||||
config: root.drawConfig
|
||||
property: "colorR"
|
||||
max: 1.0
|
||||
min: 0.0
|
||||
width: 270
|
||||
}
|
||||
ConfigSlider {
|
||||
label: "Green"
|
||||
integral: false
|
||||
config: root.drawConfig
|
||||
property: "colorG"
|
||||
max: 1.0
|
||||
min: 0.0
|
||||
width: 270
|
||||
}
|
||||
ConfigSlider {
|
||||
label: "Blue"
|
||||
integral: false
|
||||
config: root.drawConfig
|
||||
property: "colorB"
|
||||
max: 1.0
|
||||
min: 0.0
|
||||
width: 270
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GroupBox {
|
||||
title: "Fill Opacity"
|
||||
width: 280
|
||||
Column {
|
||||
spacing: 8
|
||||
|
||||
ConfigSlider {
|
||||
label: "Unoccluded"
|
||||
integral: false
|
||||
config: root.drawConfig
|
||||
property: "fillOpacityUnoccluded"
|
||||
max: 1.0
|
||||
min: 0.0
|
||||
width: 270
|
||||
}
|
||||
ConfigSlider {
|
||||
label: "Occluded"
|
||||
integral: false
|
||||
config: root.drawConfig
|
||||
property: "fillOpacityOccluded"
|
||||
max: 1.0
|
||||
min: 0.0
|
||||
width: 270
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue