merge from master
|
@ -15,10 +15,6 @@ if (WIN32)
|
|||
cmake_policy(SET CMP0020 NEW)
|
||||
endif (WIN32)
|
||||
|
||||
if (POLICY CMP0028)
|
||||
cmake_policy(SET CMP0028 OLD)
|
||||
endif ()
|
||||
|
||||
if (POLICY CMP0043)
|
||||
cmake_policy(SET CMP0043 OLD)
|
||||
endif ()
|
||||
|
@ -83,7 +79,7 @@ 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
|
||||
# GLM 0.9.8 on Ubuntu 14 (gcc 4.4) has issues with the simd declarations
|
||||
add_definitions(-DGLM_FORCE_PURE)
|
||||
endif()
|
||||
endif()
|
||||
|
|
|
@ -184,6 +184,9 @@ void Agent::run() {
|
|||
// make sure we hear about connected nodes so we can grab an ATP script if a request is pending
|
||||
connect(nodeList.data(), &LimitedNodeList::nodeActivated, this, &Agent::nodeActivated);
|
||||
|
||||
// make sure we hear about dissappearing nodes so we can clear the entity tree if an entity server goes away
|
||||
connect(nodeList.data(), &LimitedNodeList::nodeKilled, this, &Agent::nodeKilled);
|
||||
|
||||
nodeList->addSetOfNodeTypesToNodeInterestSet({
|
||||
NodeType::AudioMixer, NodeType::AvatarMixer, NodeType::EntityServer, NodeType::MessagesMixer, NodeType::AssetServer
|
||||
});
|
||||
|
@ -259,6 +262,13 @@ void Agent::nodeActivated(SharedNodePointer activatedNode) {
|
|||
}
|
||||
}
|
||||
|
||||
void Agent::nodeKilled(SharedNodePointer killedNode) {
|
||||
if (killedNode->getType() == NodeType::EntityServer) {
|
||||
// an entity server has gone away, ask the headless viewer to clear its tree
|
||||
_entityViewer.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void Agent::negotiateAudioFormat() {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
auto negotiateFormatPacket = NLPacket::create(PacketType::NegotiateAudioFormat);
|
||||
|
|
|
@ -77,6 +77,7 @@ private slots:
|
|||
void handleSelectedAudioFormat(QSharedPointer<ReceivedMessage> message);
|
||||
|
||||
void nodeActivated(SharedNodePointer activatedNode);
|
||||
void nodeKilled(SharedNodePointer killedNode);
|
||||
|
||||
void processAgentAvatar();
|
||||
void processAgentAvatarAudio();
|
||||
|
|
99
cmake/externals/tbb/CMakeLists.txt
vendored
|
@ -2,57 +2,30 @@ set(EXTERNAL_NAME tbb)
|
|||
|
||||
include(ExternalProject)
|
||||
|
||||
if (ANDROID)
|
||||
|
||||
find_program(NDK_BUILD_COMMAND NAMES ndk-build DOC "Path to the ndk-build command")
|
||||
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL http://hifi-public.s3.amazonaws.com/dependencies/tbb43_20150316oss_src.tgz
|
||||
URL_MD5 bf090eaa86cf89ea014b7b462786a440
|
||||
BUILD_COMMAND ${NDK_BUILD_COMMAND} --directory=jni target=android tbb tbbmalloc arch=arm
|
||||
BUILD_IN_SOURCE 1
|
||||
CONFIGURE_COMMAND ""
|
||||
INSTALL_COMMAND ${CMAKE_COMMAND} -DTBB_LIBS_SUFFIX=so -P ${CMAKE_CURRENT_SOURCE_DIR}/TBBLibCopy.cmake
|
||||
LOG_DOWNLOAD 1
|
||||
LOG_CONFIGURE 1
|
||||
LOG_BUILD 1
|
||||
)
|
||||
if (WIN32)
|
||||
set(DOWNLOAD_URL http://hifi-public.s3.amazonaws.com/dependencies/tbb2017_20170604oss_win_slim.zip)
|
||||
set(DOWNLOAD_MD5 065934458e3db88397f3d10e7eea536c)
|
||||
elseif (APPLE)
|
||||
find_program(MAKE_COMMAND NAMES make DOC "Path to the make command")
|
||||
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL http://hifi-public.s3.amazonaws.com/dependencies/tbb43_20150316oss_src.tgz
|
||||
URL_MD5 bf090eaa86cf89ea014b7b462786a440
|
||||
BUILD_COMMAND ${MAKE_COMMAND} tbb_os=macos
|
||||
BUILD_IN_SOURCE 1
|
||||
CONFIGURE_COMMAND ""
|
||||
INSTALL_COMMAND ${CMAKE_COMMAND} -DTBB_LIBS_SUFFIX=dylib -P ${CMAKE_CURRENT_SOURCE_DIR}/TBBLibCopy.cmake
|
||||
LOG_DOWNLOAD 1
|
||||
LOG_CONFIGURE 1
|
||||
LOG_BUILD 1
|
||||
)
|
||||
set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/tbb2017_20170604oss_mac_slim.tar.gz)
|
||||
set(DOWNLOAD_MD5 62bde626b396f8e1a85c6a8ded1d8105)
|
||||
elseif (ANDROID)
|
||||
set(DOWNLOAD_URL http://hifi-public.s3.amazonaws.com/dependencies/tbb2017_20170604oss_and_slim.tar.gz)
|
||||
set(DOWNLOAD_MD5 04d50b64e1d81245a1be5f75f34d64c7)
|
||||
else ()
|
||||
if (WIN32)
|
||||
set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/tbb43_20150316oss_win.zip)
|
||||
set(DOWNLOAD_MD5 d250d40bb93b255f75bcbb19e976a440)
|
||||
else ()
|
||||
set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/tbb43_20150316oss_lin.tgz)
|
||||
set(DOWNLOAD_MD5 7830ba2bc62438325fba2ec0c95367a5)
|
||||
endif ()
|
||||
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL ${DOWNLOAD_URL}
|
||||
URL_MD5 ${DOWNLOAD_MD5}
|
||||
BUILD_COMMAND ""
|
||||
CONFIGURE_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
LOG_DOWNLOAD ON
|
||||
)
|
||||
set(DOWNLOAD_URL http://hifi-public.s3.amazonaws.com/dependencies/tbb2017_20170604oss_lin_slim.tar.gz)
|
||||
set(DOWNLOAD_MD5 2a5c721f40fa3503ffc12c18dd00011c)
|
||||
endif ()
|
||||
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL ${DOWNLOAD_URL}
|
||||
URL_MD5 ${DOWNLOAD_MD5}
|
||||
BUILD_COMMAND ""
|
||||
CONFIGURE_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
LOG_DOWNLOAD ON
|
||||
)
|
||||
|
||||
# Hide this external target (for ide users)
|
||||
set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
|
||||
|
||||
|
@ -70,22 +43,32 @@ if (APPLE)
|
|||
change-install-name
|
||||
COMMENT "Calling install_name_tool on TBB libraries to fix install name for dylib linking"
|
||||
COMMAND ${CMAKE_COMMAND} -DINSTALL_NAME_LIBRARY_DIR=${_TBB_LIB_DIR} -P ${EXTERNAL_PROJECT_DIR}/OSXInstallNameChange.cmake
|
||||
DEPENDEES install
|
||||
DEPENDEES download
|
||||
WORKING_DIRECTORY <SOURCE_DIR>
|
||||
LOG 1
|
||||
)
|
||||
|
||||
elseif (WIN32)
|
||||
if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
|
||||
set(_TBB_LIB_DIR "${SOURCE_DIR}/lib/intel64/vc12")
|
||||
set(${EXTERNAL_NAME_UPPER}_DLL_PATH "${SOURCE_DIR}/bin/intel64/vc12" CACHE PATH "Path to TBB DLLs")
|
||||
if (MSVC_VERSION GREATER_EQUAL 1900)
|
||||
set(_TBB_MSVC_DIR "vc14")
|
||||
elseif (MSVC_VERSION GREATER_EQUAL 1800)
|
||||
set(_TBB_MSVC_DIR "vc12")
|
||||
elseif (MSVC_VERSION GREATER_EQUAL 1700)
|
||||
set(_TBB_MSVC_DIR "vc11")
|
||||
else()
|
||||
set(_TBB_LIB_DIR "${SOURCE_DIR}/lib/ia32/vc12")
|
||||
set(${EXTERNAL_NAME_UPPER}_DLL_PATH "${SOURCE_DIR}/bin/ia32/vc12" CACHE PATH "Path to TBB DLLs")
|
||||
message(FATAL_ERROR "MSVC ${MSVC_VERSION} not supported by Intel TBB")
|
||||
endif()
|
||||
|
||||
if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
|
||||
set(_TBB_LIB_DIR "${SOURCE_DIR}/lib/intel64/${_TBB_MSVC_DIR}")
|
||||
set(${EXTERNAL_NAME_UPPER}_DLL_PATH "${SOURCE_DIR}/bin/intel64/${_TBB_MSVC_DIR}" CACHE PATH "Path to TBB DLLs")
|
||||
else()
|
||||
set(_TBB_LIB_DIR "${SOURCE_DIR}/lib/ia32/${_TBB_MSVC_DIR}")
|
||||
set(${EXTERNAL_NAME_UPPER}_DLL_PATH "${SOURCE_DIR}/bin/ia32/${_TBB_MSVC_DIR}" CACHE PATH "Path to TBB DLLs")
|
||||
endif()
|
||||
|
||||
set(_LIB_EXT "lib")
|
||||
elseif (ANDROID)
|
||||
set(_TBB_LIB_DIR "${SOURCE_DIR}/lib")
|
||||
set(_TBB_LIB_DIR "${SOURCE_DIR}/lib/android")
|
||||
set(_LIB_PREFIX "lib")
|
||||
set(_LIB_EXT "so")
|
||||
elseif (UNIX)
|
||||
|
@ -103,15 +86,15 @@ elseif (UNIX)
|
|||
OUTPUT_VARIABLE GCC_VERSION
|
||||
)
|
||||
|
||||
if (GCC_VERSION VERSION_GREATER 4.4 OR GCC_VERSION VERSION_EQUAL 4.4)
|
||||
if (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7)
|
||||
set(_TBB_LIB_DIR "${SOURCE_DIR}/lib/${_TBB_ARCH_DIR}/gcc4.7")
|
||||
elseif (GCC_VERSION VERSION_GREATER 4.4 OR GCC_VERSION VERSION_EQUAL 4.4)
|
||||
set(_TBB_LIB_DIR "${SOURCE_DIR}/lib/${_TBB_ARCH_DIR}/gcc4.4")
|
||||
elseif (GCC_VERSION VERSION_GREATER 4.1 OR GCC_VERSION VERSION_EQUAL 4.1)
|
||||
set(_TBB_LIB_DIR "${SOURCE_DIR}/lib/${_TBB_ARCH_DIR}/gcc4.1")
|
||||
else ()
|
||||
message(STATUS "Could not find a compatible version of Threading Building Blocks library for your compiler.")
|
||||
endif ()
|
||||
|
||||
|
||||
endif ()
|
||||
|
||||
if (DEFINED _TBB_LIB_DIR)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#
|
||||
#
|
||||
# FindTBB.cmake
|
||||
#
|
||||
#
|
||||
# Try to find the Intel Threading Building Blocks library
|
||||
#
|
||||
# You can provide a TBB_ROOT_DIR which contains lib and include directories
|
||||
|
@ -16,7 +16,7 @@
|
|||
#
|
||||
# Distributed under the Apache License, Version 2.0.
|
||||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
#
|
||||
|
||||
include("${MACRO_DIR}/HifiLibrarySearchHints.cmake")
|
||||
hifi_library_search_hints("tbb")
|
||||
|
@ -34,31 +34,43 @@ elseif (UNIX AND NOT ANDROID)
|
|||
else()
|
||||
set(_TBB_ARCH_DIR "ia32")
|
||||
endif()
|
||||
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_C_COMPILER} -dumpversion
|
||||
OUTPUT_VARIABLE GCC_VERSION
|
||||
)
|
||||
|
||||
if (GCC_VERSION VERSION_GREATER 4.4 OR GCC_VERSION VERSION_EQUAL 4.4)
|
||||
|
||||
if (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7)
|
||||
set(_TBB_LIB_DIR "lib/${_TBB_ARCH_DIR}/gcc4.7")
|
||||
elseif (GCC_VERSION VERSION_GREATER 4.4 OR GCC_VERSION VERSION_EQUAL 4.4)
|
||||
set(_TBB_LIB_DIR "lib/${_TBB_ARCH_DIR}/gcc4.4")
|
||||
elseif (GCC_VERSION VERSION_GREATER 4.1 OR GCC_VERSION VERSION_EQUAL 4.1)
|
||||
set(_TBB_LIB_DIR "lib/${_TBB_ARCH_DIR}/gcc4.1")
|
||||
else ()
|
||||
message(FATAL_ERROR "Could not find a compatible version of Threading Building Blocks library for your compiler.")
|
||||
endif ()
|
||||
|
||||
|
||||
elseif (WIN32)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(_TBB_ARCH_DIR "intel64")
|
||||
else()
|
||||
set(_TBB_ARCH_DIR "ia32")
|
||||
endif()
|
||||
|
||||
set(_TBB_LIB_DIR "lib/${_TBB_ARCH_DIR}/vc12")
|
||||
|
||||
find_path(TBB_DLL_PATH tbb_debug.dll PATH_SUFFIXES "bin/${_TBB_ARCH_DIR}/vc12" HINTS ${TBB_SEARCH_DIRS})
|
||||
|
||||
|
||||
if (MSVC_VERSION GREATER_EQUAL 1900)
|
||||
set(_TBB_MSVC_DIR "vc14")
|
||||
elseif (MSVC_VERSION GREATER_EQUAL 1800)
|
||||
set(_TBB_MSVC_DIR "vc12")
|
||||
elseif (MSVC_VERSION GREATER_EQUAL 1700)
|
||||
set(_TBB_MSVC_DIR "vc11")
|
||||
else()
|
||||
message(FATAL_ERROR "MSVC ${MSVC_VERSION} not supported by Intel TBB")
|
||||
endif()
|
||||
|
||||
set(_TBB_LIB_DIR "lib/${_TBB_ARCH_DIR}/${_TBB_MSVC_DIR}")
|
||||
|
||||
find_path(TBB_DLL_PATH tbb_debug.dll PATH_SUFFIXES "bin/${_TBB_ARCH_DIR}/${_TBB_MSVC_DIR}" HINTS ${TBB_SEARCH_DIRS})
|
||||
|
||||
elseif (ANDROID)
|
||||
set(_TBB_DEFAULT_INSTALL_DIR "/tbb")
|
||||
set(_TBB_LIB_NAME "tbb")
|
||||
|
|
|
@ -811,6 +811,7 @@ Section "-Core installation"
|
|||
Delete "$INSTDIR\server-console.exe"
|
||||
RMDir /r "$INSTDIR\locales"
|
||||
RMDir /r "$INSTDIR\resources\app"
|
||||
RMDir /r "$INSTDIR\plugins"
|
||||
Delete "$INSTDIR\resources\atom.asar"
|
||||
Delete "$INSTDIR\build-info.json"
|
||||
Delete "$INSTDIR\content_resources_200_percent.pak"
|
||||
|
|
Before Width: | Height: | Size: 254 KiB After Width: | Height: | Size: 312 KiB |
Before Width: | Height: | Size: 186 KiB After Width: | Height: | Size: 232 KiB |
Before Width: | Height: | Size: 253 KiB After Width: | Height: | Size: 307 KiB |
Before Width: | Height: | Size: 211 KiB After Width: | Height: | Size: 268 KiB |
BIN
interface/resources/images/fadeMask.png
Normal file
After Width: | Height: | Size: 67 KiB |
158
interface/resources/qml/hifi/DesktopLetterboxMessage.qml
Normal file
|
@ -0,0 +1,158 @@
|
|||
//
|
||||
// LetterboxMessage.qml
|
||||
// qml/hifi
|
||||
//
|
||||
// Created by Dante Ruiz on 7/21/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
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import "../styles-uit"
|
||||
|
||||
Item {
|
||||
property alias text: popupText.text
|
||||
property alias headerGlyph: headerGlyph.text
|
||||
property alias headerText: headerText.text
|
||||
property alias headerGlyphSize: headerGlyph.size
|
||||
property real popupRadius: hifi.dimensions.borderRadius
|
||||
property real headerTextPixelSize: 22
|
||||
property real popupTextPixelSize: 16
|
||||
property real headerTextMargin: -5
|
||||
property real headerGlyphMargin: -15
|
||||
property bool isDesktop: false
|
||||
FontLoader { id: ralewayRegular; source: "../../fonts/Raleway-Regular.ttf"; }
|
||||
FontLoader { id: ralewaySemiBold; source: "../../fonts/Raleway-SemiBold.ttf"; }
|
||||
visible: false
|
||||
id: letterbox
|
||||
anchors.fill: parent
|
||||
Rectangle {
|
||||
id: textContainer;
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
anchors.centerIn: parent
|
||||
radius: popupRadius
|
||||
color: "white"
|
||||
Item {
|
||||
id: contentContainer
|
||||
width: parent.width - 50
|
||||
height: childrenRect.height
|
||||
anchors.centerIn: parent
|
||||
Item {
|
||||
id: popupHeaderContainer
|
||||
visible: headerText.text !== "" || headerGlyph.text !== ""
|
||||
height: 30
|
||||
// Anchors
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
// Header Glyph
|
||||
HiFiGlyphs {
|
||||
id: headerGlyph
|
||||
visible: headerGlyph.text !== ""
|
||||
// Size
|
||||
height: parent.height
|
||||
// Anchors
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: headerGlyphMargin
|
||||
// Text Size
|
||||
size: headerTextPixelSize*2.5
|
||||
// Style
|
||||
horizontalAlignment: Text.AlignHLeft
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: hifi.colors.darkGray
|
||||
}
|
||||
// Header Text
|
||||
Text {
|
||||
id: headerText
|
||||
visible: headerText.text !== ""
|
||||
// Size
|
||||
|
||||
height: parent.height
|
||||
// Anchors
|
||||
anchors.left: headerGlyph.right
|
||||
anchors.leftMargin: headerTextMargin
|
||||
// Text Size
|
||||
font.pixelSize: headerTextPixelSize
|
||||
// Style
|
||||
font.family: ralewaySemiBold.name
|
||||
color: hifi.colors.darkGray
|
||||
horizontalAlignment: Text.AlignHLeft
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
wrapMode: Text.WordWrap
|
||||
textFormat: Text.StyledText
|
||||
}
|
||||
}
|
||||
// Popup Text
|
||||
Text {
|
||||
id: popupText
|
||||
// Size
|
||||
width: parent.width
|
||||
// Anchors
|
||||
anchors.top: popupHeaderContainer.visible ? popupHeaderContainer.bottom : parent.top
|
||||
anchors.topMargin: popupHeaderContainer.visible ? 15 : 0
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
// Text alignment
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHLeft
|
||||
// Style
|
||||
font.pixelSize: popupTextPixelSize
|
||||
font.family: ralewayRegular.name
|
||||
color: hifi.colors.darkGray
|
||||
wrapMode: Text.WordWrap
|
||||
textFormat: Text.StyledText
|
||||
onLinkActivated: {
|
||||
Qt.openUrlExternally(link)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Left gray MouseArea
|
||||
MouseArea {
|
||||
anchors.left: parent.left;
|
||||
anchors.right: textContainer.left;
|
||||
anchors.top: textContainer.top;
|
||||
anchors.bottom: textContainer.bottom;
|
||||
acceptedButtons: Qt.LeftButton
|
||||
onClicked: {
|
||||
letterbox.visible = false
|
||||
}
|
||||
}
|
||||
// Right gray MouseArea
|
||||
MouseArea {
|
||||
anchors.left: textContainer.left;
|
||||
anchors.right: parent.left;
|
||||
anchors.top: textContainer.top;
|
||||
anchors.bottom: textContainer.bottom;
|
||||
acceptedButtons: Qt.LeftButton
|
||||
onClicked: {
|
||||
letterbox.visible = false
|
||||
}
|
||||
}
|
||||
// Top gray MouseArea
|
||||
MouseArea {
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
anchors.top: parent.top;
|
||||
anchors.bottom: textContainer.top;
|
||||
acceptedButtons: Qt.LeftButton
|
||||
onClicked: {
|
||||
letterbox.visible = false
|
||||
}
|
||||
}
|
||||
// Bottom gray MouseArea
|
||||
MouseArea {
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
anchors.top: textContainer.bottom;
|
||||
anchors.bottom: parent.bottom;
|
||||
acceptedButtons: Qt.LeftButton
|
||||
onClicked: {
|
||||
letterbox.visible = false
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,9 +17,12 @@ Item {
|
|||
property alias text: popupText.text
|
||||
property alias headerGlyph: headerGlyph.text
|
||||
property alias headerText: headerText.text
|
||||
property alias headerGlyphSize: headerGlyph.size
|
||||
property real popupRadius: hifi.dimensions.borderRadius
|
||||
property real headerTextPixelSize: 22
|
||||
property real popupTextPixelSize: 16
|
||||
property real headerTextMargin: -5
|
||||
property real headerGlyphMargin: -15
|
||||
FontLoader { id: ralewayRegular; source: "../../fonts/Raleway-Regular.ttf"; }
|
||||
FontLoader { id: ralewaySemiBold; source: "../../fonts/Raleway-SemiBold.ttf"; }
|
||||
visible: false
|
||||
|
@ -59,7 +62,7 @@ Item {
|
|||
height: parent.height
|
||||
// Anchors
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: -15
|
||||
anchors.leftMargin: headerGlyphMargin
|
||||
// Text Size
|
||||
size: headerTextPixelSize*2.5
|
||||
// Style
|
||||
|
@ -75,7 +78,7 @@ Item {
|
|||
height: parent.height
|
||||
// Anchors
|
||||
anchors.left: headerGlyph.right
|
||||
anchors.leftMargin: -5
|
||||
anchors.leftMargin: headerTextMargin
|
||||
// Text Size
|
||||
font.pixelSize: headerTextPixelSize
|
||||
// Style
|
||||
|
|
|
@ -25,6 +25,7 @@ Rectangle {
|
|||
|
||||
id: checkoutRoot;
|
||||
property string itemId;
|
||||
property string itemHref;
|
||||
// Style
|
||||
color: hifi.colors.baseGray;
|
||||
Hifi.QmlCommerce {
|
||||
|
@ -234,6 +235,7 @@ Rectangle {
|
|||
|
||||
// "Cancel" button
|
||||
HifiControlsUit.Button {
|
||||
id: cancelButton;
|
||||
color: hifi.buttons.black;
|
||||
colorScheme: hifi.colorSchemes.dark;
|
||||
anchors.top: parent.top;
|
||||
|
@ -251,6 +253,8 @@ Rectangle {
|
|||
|
||||
// "Buy" button
|
||||
HifiControlsUit.Button {
|
||||
property bool buyFailed: false;
|
||||
id: buyButton;
|
||||
color: hifi.buttons.black;
|
||||
colorScheme: hifi.colorSchemes.dark;
|
||||
anchors.top: parent.top;
|
||||
|
@ -262,7 +266,11 @@ Rectangle {
|
|||
width: parent.width/2 - anchors.rightMargin*2;
|
||||
text: "Buy"
|
||||
onClicked: {
|
||||
sendToScript({method: 'checkout_buyClicked', params: {success: commerce.buy(itemId, parseInt(itemPriceText.text))}});
|
||||
if (buyFailed) {
|
||||
sendToScript({method: 'checkout_cancelClicked', params: itemId});
|
||||
} else {
|
||||
sendToScript({method: 'checkout_buyClicked', success: commerce.buy(itemId, parseInt(itemPriceText.text)), itemId: itemId, itemHref: itemHref});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -293,6 +301,13 @@ Rectangle {
|
|||
itemNameText.text = message.params.itemName;
|
||||
itemAuthorText.text = message.params.itemAuthor;
|
||||
itemPriceText.text = message.params.itemPrice;
|
||||
itemHref = message.params.itemHref;
|
||||
buyButton.text = "Buy";
|
||||
buyButton.buyFailed = false;
|
||||
break;
|
||||
case 'buyFailed':
|
||||
buyButton.text = "Buy Failed";
|
||||
buyButton.buyFailed = true;
|
||||
break;
|
||||
default:
|
||||
console.log('Unrecognized message from marketplaces.js:', JSON.stringify(message));
|
||||
|
|
|
@ -16,6 +16,7 @@ import Qt.labs.settings 1.0
|
|||
import "../../styles-uit"
|
||||
import "../../controls-uit" as HifiControls
|
||||
import "../../windows"
|
||||
import "../"
|
||||
|
||||
ScrollingWindow {
|
||||
id: root
|
||||
|
@ -28,10 +29,11 @@ ScrollingWindow {
|
|||
minSize: Qt.vector2d(424, 300)
|
||||
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
|
||||
property var scripts: ScriptDiscoveryService;
|
||||
property var scriptsModel: scripts.scriptsModelFilter
|
||||
property var runningScriptsModel: ListModel { }
|
||||
property bool developerMenuEnabled: false
|
||||
property bool isHMD: false
|
||||
|
||||
Settings {
|
||||
|
@ -39,6 +41,28 @@ ScrollingWindow {
|
|||
property alias x: root.x
|
||||
property alias y: root.y
|
||||
}
|
||||
|
||||
Component {
|
||||
id: letterBoxMessage
|
||||
Window {
|
||||
implicitWidth: 400
|
||||
implicitHeight: 300
|
||||
minSize: Qt.vector2d(424, 300)
|
||||
DesktopLetterboxMessage {
|
||||
visible: true
|
||||
headerGlyph: hifi.glyphs.lock
|
||||
headerText: "Developer Mode only"
|
||||
text: ( "In order to edit, delete or reload this script," +
|
||||
" turn on Developer Mode by going to:" +
|
||||
" Menu > Settings > Developer Menus")
|
||||
popupRadius: 0
|
||||
headerGlyphSize: 20
|
||||
headerTextMargin: 2
|
||||
headerGlyphMargin: -3
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Timer {
|
||||
id: refreshTimer
|
||||
|
@ -47,6 +71,15 @@ ScrollingWindow {
|
|||
running: false
|
||||
onTriggered: updateRunningScripts();
|
||||
}
|
||||
|
||||
|
||||
Timer {
|
||||
id: checkMenu
|
||||
interval: 1000
|
||||
repeat: true
|
||||
running: false
|
||||
onTriggered: developerMenuEnabled = MenuInterface.isMenuEnabled("Developer Menus");
|
||||
}
|
||||
|
||||
Component {
|
||||
id: listModelBuilder
|
||||
|
@ -64,6 +97,8 @@ ScrollingWindow {
|
|||
Component.onCompleted: {
|
||||
isHMD = HMD.active;
|
||||
updateRunningScripts();
|
||||
developerMenuEnabled = MenuInterface.isMenuEnabled("Developer Menus");
|
||||
checkMenu.restart();
|
||||
}
|
||||
|
||||
function updateRunningScripts() {
|
||||
|
@ -110,7 +145,17 @@ ScrollingWindow {
|
|||
|
||||
function reloadAll() {
|
||||
console.log("Reload all scripts");
|
||||
scripts.reloadAllScripts();
|
||||
if (!developerMenuEnabled) {
|
||||
for (var index = 0; index < runningScriptsModel.count; index++) {
|
||||
var url = runningScriptsModel.get(index).url;
|
||||
var fileName = url.substring(url.lastIndexOf('/')+1);
|
||||
if (canEditScript(fileName)) {
|
||||
scripts.stopScript(url, true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
scripts.reloadAllScripts();
|
||||
}
|
||||
}
|
||||
|
||||
function loadDefaults() {
|
||||
|
@ -120,7 +165,22 @@ ScrollingWindow {
|
|||
|
||||
function stopAll() {
|
||||
console.log("Stop all scripts");
|
||||
scripts.stopAllScripts();
|
||||
for (var index = 0; index < runningScriptsModel.count; index++) {
|
||||
var url = runningScriptsModel.get(index).url;
|
||||
var fileName = url.substring(url.lastIndexOf('/')+1);
|
||||
if (canEditScript(fileName)) {
|
||||
scripts.stopScript(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function canEditScript(script) {
|
||||
if ((script === "controllerScripts.js") || (script === "defaultScripts.js")) {
|
||||
return developerMenuEnabled;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Column {
|
||||
|
@ -146,6 +206,14 @@ ScrollingWindow {
|
|||
color: hifi.buttons.red
|
||||
onClicked: stopAll()
|
||||
}
|
||||
|
||||
HifiControls.Button {
|
||||
text: "Load Defaults"
|
||||
color: hifi.buttons.black
|
||||
height: 26
|
||||
visible: root.developerMenuEnabled;
|
||||
onClicked: loadDefaults()
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.VerticalSpacer {
|
||||
|
@ -162,6 +230,7 @@ ScrollingWindow {
|
|||
expandSelectedRow: true
|
||||
|
||||
itemDelegate: Item {
|
||||
property bool canEdit: canEditScript(styleData.value);
|
||||
anchors {
|
||||
left: parent ? parent.left : undefined
|
||||
leftMargin: hifi.dimensions.tablePadding
|
||||
|
@ -185,8 +254,9 @@ ScrollingWindow {
|
|||
|
||||
HiFiGlyphs {
|
||||
id: reloadButton
|
||||
text: hifi.glyphs.reloadSmall
|
||||
text: ((canEditScript(styleData.value)) ? hifi.glyphs.reload : hifi.glyphs.lock)
|
||||
color: reloadButtonArea.pressed ? hifi.colors.white : parent.color
|
||||
size: 21
|
||||
anchors {
|
||||
top: parent.top
|
||||
right: stopButton.left
|
||||
|
@ -195,7 +265,13 @@ ScrollingWindow {
|
|||
MouseArea {
|
||||
id: reloadButtonArea
|
||||
anchors { fill: parent; margins: -2 }
|
||||
onClicked: reloadScript(model.url)
|
||||
onClicked: {
|
||||
if (canEdit) {
|
||||
reloadScript(model.url)
|
||||
} else {
|
||||
letterBoxMessage.createObject(desktop)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,6 +279,7 @@ ScrollingWindow {
|
|||
id: stopButton
|
||||
text: hifi.glyphs.closeSmall
|
||||
color: stopButtonArea.pressed ? hifi.colors.white : parent.color
|
||||
visible: canEditScript(styleData.value)
|
||||
anchors {
|
||||
top: parent.top
|
||||
right: parent.right
|
||||
|
@ -211,7 +288,11 @@ ScrollingWindow {
|
|||
MouseArea {
|
||||
id: stopButtonArea
|
||||
anchors { fill: parent; margins: -2 }
|
||||
onClicked: stopScript(model.url)
|
||||
onClicked: {
|
||||
if (canEdit) {
|
||||
stopScript(model.url);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -264,13 +345,6 @@ ScrollingWindow {
|
|||
height: 26
|
||||
onClickedQueued: ApplicationInterface.loadDialog()
|
||||
}
|
||||
|
||||
HifiControls.Button {
|
||||
text: "Load Defaults"
|
||||
color: hifi.buttons.black
|
||||
height: 26
|
||||
onClicked: loadDefaults()
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.VerticalSpacer {}
|
||||
|
|
|
@ -16,6 +16,7 @@ import Qt.labs.settings 1.0
|
|||
import "../../styles-uit"
|
||||
import "../../controls-uit" as HifiControls
|
||||
import "../../windows"
|
||||
import "../"
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
@ -26,26 +27,90 @@ Rectangle {
|
|||
property var scripts: ScriptDiscoveryService;
|
||||
property var scriptsModel: scripts.scriptsModelFilter
|
||||
property var runningScriptsModel: ListModel { }
|
||||
property bool developerMenuEnabled: false
|
||||
property bool isHMD: false
|
||||
|
||||
color: hifi.colors.baseGray
|
||||
|
||||
|
||||
LetterboxMessage {
|
||||
id: letterBoxMessage
|
||||
z: 999
|
||||
visible: false
|
||||
}
|
||||
|
||||
function letterBox(glyph, text, message) {
|
||||
letterBoxMessage.headerGlyph = glyph;
|
||||
letterBoxMessage.headerText = text;
|
||||
letterBoxMessage.text = message;
|
||||
letterBoxMessage.visible = true;
|
||||
letterBoxMessage.popupRadius = 0;
|
||||
letterBoxMessage.headerGlyphSize = 20
|
||||
letterBoxMessage.headerTextMargin = 2
|
||||
letterBoxMessage.headerGlyphMargin = -3
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: refreshTimer
|
||||
interval: 100
|
||||
repeat: false
|
||||
running: false
|
||||
onTriggered: updateRunningScripts();
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: checkMenu
|
||||
interval: 1000
|
||||
repeat: true
|
||||
running: false
|
||||
onTriggered: developerMenuEnabled = MenuInterface.isMenuEnabled("Developer Menus");
|
||||
}
|
||||
|
||||
Component {
|
||||
id: listModelBuilder
|
||||
ListModel {}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: ScriptDiscoveryService
|
||||
onScriptCountChanged: updateRunningScripts();
|
||||
onScriptCountChanged: {
|
||||
runningScriptsModel = listModelBuilder.createObject(root);
|
||||
refreshTimer.restart();
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
isHMD = HMD.active;
|
||||
updateRunningScripts();
|
||||
developerMenuEnabled = MenuInterface.isMenuEnabled("Developer Menus");
|
||||
checkMenu.restart();
|
||||
}
|
||||
|
||||
function updateRunningScripts() {
|
||||
var runningScripts = ScriptDiscoveryService.getRunning();
|
||||
runningScriptsModel.clear()
|
||||
for (var i = 0; i < runningScripts.length; ++i) {
|
||||
runningScriptsModel.append(runningScripts[i]);
|
||||
function simplify(path) {
|
||||
// trim URI querystring/fragment
|
||||
path = (path+'').replace(/[#?].*$/,'');
|
||||
// normalize separators and grab last path segment (ie: just the filename)
|
||||
path = path.replace(/\\/g, '/').split('/').pop();
|
||||
// return lowercased because we want to sort mnemonically
|
||||
return path.toLowerCase();
|
||||
}
|
||||
var runningScripts = ScriptDiscoveryService.getRunning();
|
||||
runningScripts.sort(function(a,b) {
|
||||
a = simplify(a.path);
|
||||
b = simplify(b.path);
|
||||
return a < b ? -1 : a > b ? 1 : 0;
|
||||
});
|
||||
// Calling `runningScriptsModel.clear()` here instead of creating a new object
|
||||
// triggers some kind of weird heap corruption deep inside Qt. So instead of
|
||||
// modifying the model in place, possibly triggering behaviors in the table
|
||||
// instead we create a new `ListModel`, populate it and update the
|
||||
// existing model atomically.
|
||||
var newRunningScriptsModel = listModelBuilder.createObject(root);
|
||||
for (var i = 0; i < runningScripts.length; ++i) {
|
||||
newRunningScriptsModel.append(runningScripts[i]);
|
||||
}
|
||||
runningScriptsModel = newRunningScriptsModel;
|
||||
}
|
||||
|
||||
function loadScript(script) {
|
||||
|
@ -65,7 +130,17 @@ Rectangle {
|
|||
|
||||
function reloadAll() {
|
||||
console.log("Reload all scripts");
|
||||
scripts.reloadAllScripts();
|
||||
if (!developerMenuEnabled) {
|
||||
for (var index = 0; index < runningScriptsModel.count; index++) {
|
||||
var url = runningScriptsModel.get(index).url;
|
||||
var fileName = url.substring(url.lastIndexOf('/')+1);
|
||||
if (canEditScript(fileName)) {
|
||||
scripts.stopScript(url, true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
scripts.reloadAllScripts();
|
||||
}
|
||||
}
|
||||
|
||||
function loadDefaults() {
|
||||
|
@ -75,7 +150,22 @@ Rectangle {
|
|||
|
||||
function stopAll() {
|
||||
console.log("Stop all scripts");
|
||||
scripts.stopAllScripts();
|
||||
for (var index = 0; index < runningScriptsModel.count; index++) {
|
||||
var url = runningScriptsModel.get(index).url;
|
||||
console.log(url);
|
||||
var fileName = url.substring(url.lastIndexOf('/')+1);
|
||||
if (canEditScript(fileName)) {
|
||||
scripts.stopScript(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function canEditScript(script) {
|
||||
if ((script === "controllerScripts.js") || (script === "defaultScripts.js")) {
|
||||
return developerMenuEnabled;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Flickable {
|
||||
|
@ -110,6 +200,14 @@ Rectangle {
|
|||
color: hifi.buttons.red
|
||||
onClicked: stopAll()
|
||||
}
|
||||
|
||||
HifiControls.Button {
|
||||
text: "Load Defaults"
|
||||
color: hifi.buttons.black
|
||||
height: 26
|
||||
visible: root.developerMenuEnabled;
|
||||
onClicked: loadDefaults()
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.VerticalSpacer {
|
||||
|
@ -125,6 +223,7 @@ Rectangle {
|
|||
expandSelectedRow: true
|
||||
|
||||
itemDelegate: Item {
|
||||
property bool canEdit: canEditScript(styleData.value);
|
||||
anchors {
|
||||
left: parent ? parent.left : undefined
|
||||
leftMargin: hifi.dimensions.tablePadding
|
||||
|
@ -148,8 +247,9 @@ Rectangle {
|
|||
|
||||
HiFiGlyphs {
|
||||
id: reloadButton
|
||||
text: hifi.glyphs.reloadSmall
|
||||
text: ((canEditScript(styleData.value)) ? hifi.glyphs.reload : hifi.glyphs.lock)
|
||||
color: reloadButtonArea.pressed ? hifi.colors.white : parent.color
|
||||
size: 21
|
||||
anchors {
|
||||
top: parent.top
|
||||
right: stopButton.left
|
||||
|
@ -158,7 +258,17 @@ Rectangle {
|
|||
MouseArea {
|
||||
id: reloadButtonArea
|
||||
anchors { fill: parent; margins: -2 }
|
||||
onClicked: reloadScript(model.url)
|
||||
onClicked: {
|
||||
if (canEdit) {
|
||||
reloadScript(model.url)
|
||||
} else {
|
||||
letterBox(hifi.glyphs.lock,
|
||||
"Developer Mode only",
|
||||
"In order to edit, delete or reload this script," +
|
||||
" turn on Developer Mode by going to:" +
|
||||
" Menu > Settings > Developer Menus");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,6 +276,7 @@ Rectangle {
|
|||
id: stopButton
|
||||
text: hifi.glyphs.closeSmall
|
||||
color: stopButtonArea.pressed ? hifi.colors.white : parent.color
|
||||
visible: canEditScript(styleData.value)
|
||||
anchors {
|
||||
top: parent.top
|
||||
right: parent.right
|
||||
|
@ -174,7 +285,11 @@ Rectangle {
|
|||
MouseArea {
|
||||
id: stopButtonArea
|
||||
anchors { fill: parent; margins: -2 }
|
||||
onClicked: stopScript(model.url)
|
||||
onClicked: {
|
||||
if (canEdit) {
|
||||
stopScript(model.url)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -250,13 +365,6 @@ Rectangle {
|
|||
onTriggered: ApplicationInterface.loadDialog();
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.Button {
|
||||
text: "Load Defaults"
|
||||
color: hifi.buttons.black
|
||||
height: 26
|
||||
onClicked: loadDefaults()
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.VerticalSpacer {}
|
||||
|
|
|
@ -116,6 +116,7 @@ Item {
|
|||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
enabled: true
|
||||
preventStealing: true
|
||||
onClicked: {
|
||||
console.log("Tablet Button Clicked!");
|
||||
if (tabletButton.inDebugMode) {
|
||||
|
|
|
@ -337,5 +337,6 @@ Item {
|
|||
readonly property string playback_play: "\ue01d"
|
||||
readonly property string stop_square: "\ue01e"
|
||||
readonly property string avatarTPose: "\ue01f"
|
||||
readonly property string lock: "\ue006"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -966,6 +966,53 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
// Make sure we don't time out during slow operations at startup
|
||||
updateHeartbeat();
|
||||
|
||||
// Now that OpenGL is initialized, we are sure we have a valid context and can create the various pipeline shaders with success.
|
||||
DependencyManager::get<GeometryCache>()->initializeShapePipelines();
|
||||
|
||||
// sessionRunTime will be reset soon by loadSettings. Grab it now to get previous session value.
|
||||
// The value will be 0 if the user blew away settings this session, which is both a feature and a bug.
|
||||
static const QString TESTER = "HIFI_TESTER";
|
||||
auto gpuIdent = GPUIdent::getInstance();
|
||||
auto glContextData = getGLContextData();
|
||||
QJsonObject properties = {
|
||||
{ "version", applicationVersion() },
|
||||
{ "tester", QProcessEnvironment::systemEnvironment().contains(TESTER) },
|
||||
{ "previousSessionCrashed", _previousSessionCrashed },
|
||||
{ "previousSessionRuntime", sessionRunTime.get() },
|
||||
{ "cpu_architecture", QSysInfo::currentCpuArchitecture() },
|
||||
{ "kernel_type", QSysInfo::kernelType() },
|
||||
{ "kernel_version", QSysInfo::kernelVersion() },
|
||||
{ "os_type", QSysInfo::productType() },
|
||||
{ "os_version", QSysInfo::productVersion() },
|
||||
{ "gpu_name", gpuIdent->getName() },
|
||||
{ "gpu_driver", gpuIdent->getDriver() },
|
||||
{ "gpu_memory", static_cast<qint64>(gpuIdent->getMemory()) },
|
||||
{ "gl_version_int", glVersionToInteger(glContextData.value("version").toString()) },
|
||||
{ "gl_version", glContextData["version"] },
|
||||
{ "gl_vender", glContextData["vendor"] },
|
||||
{ "gl_sl_version", glContextData["sl_version"] },
|
||||
{ "gl_renderer", glContextData["renderer"] },
|
||||
{ "ideal_thread_count", QThread::idealThreadCount() }
|
||||
};
|
||||
auto macVersion = QSysInfo::macVersion();
|
||||
if (macVersion != QSysInfo::MV_None) {
|
||||
properties["os_osx_version"] = QSysInfo::macVersion();
|
||||
}
|
||||
auto windowsVersion = QSysInfo::windowsVersion();
|
||||
if (windowsVersion != QSysInfo::WV_None) {
|
||||
properties["os_win_version"] = QSysInfo::windowsVersion();
|
||||
}
|
||||
|
||||
ProcessorInfo procInfo;
|
||||
if (getProcessorInfo(procInfo)) {
|
||||
properties["processor_core_count"] = procInfo.numProcessorCores;
|
||||
properties["logical_processor_count"] = procInfo.numLogicalProcessors;
|
||||
properties["processor_l1_cache_count"] = procInfo.numProcessorCachesL1;
|
||||
properties["processor_l2_cache_count"] = procInfo.numProcessorCachesL2;
|
||||
properties["processor_l3_cache_count"] = procInfo.numProcessorCachesL3;
|
||||
}
|
||||
|
||||
// add firstRun flag from settings to launch event
|
||||
Setting::Handle<bool> firstRun { Settings::firstRun, true };
|
||||
|
||||
// once the settings have been loaded, check if we need to flip the default for UserActivityLogger
|
||||
|
|
|
@ -298,6 +298,7 @@ public:
|
|||
QUuid getTabletFrameID() const; // may be an entity or an overlay
|
||||
|
||||
void setAvatarOverrideUrl(const QUrl& url, bool save);
|
||||
void clearAvatarOverrideUrl() { _avatarOverrideUrl = QUrl(); _saveAvatarOverrideUrl = false; }
|
||||
QUrl getAvatarOverrideUrl() { return _avatarOverrideUrl; }
|
||||
bool getSaveAvatarOverrideUrl() { return _saveAvatarOverrideUrl; }
|
||||
|
||||
|
|
|
@ -273,19 +273,15 @@ void AvatarManager::simulateAvatarFades(float deltaTime) {
|
|||
return;
|
||||
}
|
||||
|
||||
const float SHRINK_RATE = 0.15f;
|
||||
const float MIN_FADE_SCALE = MIN_AVATAR_SCALE;
|
||||
|
||||
QReadLocker locker(&_hashLock);
|
||||
QVector<AvatarSharedPointer>::iterator avatarItr = _avatarsToFade.begin();
|
||||
const render::ScenePointer& scene = qApp->getMain3DScene();
|
||||
while (avatarItr != _avatarsToFade.end()) {
|
||||
auto avatar = std::static_pointer_cast<Avatar>(*avatarItr);
|
||||
avatar->setTargetScale(avatar->getUniformScale() * SHRINK_RATE);
|
||||
avatar->animateScaleChanges(deltaTime);
|
||||
if (avatar->getTargetScale() <= MIN_FADE_SCALE) {
|
||||
avatar->updateFadingStatus(scene);
|
||||
if (!avatar->isFading()) {
|
||||
// fading to zero is such a rare event we push a unique transaction for each
|
||||
if (avatar->isInScene()) {
|
||||
const render::ScenePointer& scene = qApp->getMain3DScene();
|
||||
render::Transaction transaction;
|
||||
avatar->removeFromScene(*avatarItr, scene, transaction);
|
||||
scene->enqueueTransaction(transaction);
|
||||
|
@ -323,6 +319,7 @@ void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar
|
|||
// remove from node sets, if present
|
||||
DependencyManager::get<NodeList>()->removeFromIgnoreMuteSets(avatar->getSessionUUID());
|
||||
DependencyManager::get<UsersScriptingInterface>()->avatarDisconnected(avatar->getSessionUUID());
|
||||
avatar->fadeOut(qApp->getMain3DScene(), removalReason);
|
||||
}
|
||||
_avatarsToFade.push_back(removedAvatar);
|
||||
}
|
||||
|
|
|
@ -1898,8 +1898,8 @@ void MyAvatar::updateOrientation(float deltaTime) {
|
|||
totalBodyYaw += (speedFactor * deltaAngle * (180.0f / PI));
|
||||
}
|
||||
|
||||
// Use head/HMD roll to turn while walking or flying.
|
||||
if (qApp->isHMDMode() && _hmdRollControlEnabled) {
|
||||
// Use head/HMD roll to turn while walking or flying, but not when standing still
|
||||
if (qApp->isHMDMode() && _hmdRollControlEnabled && hasDriveInput()) {
|
||||
// Turn with head roll.
|
||||
const float MIN_CONTROL_SPEED = 0.01f;
|
||||
float speed = glm::length(getVelocity());
|
||||
|
|
|
@ -33,6 +33,11 @@ bool Ledger::buy(const QString& hfc_key, int cost, const QString& asset_id, cons
|
|||
request["signature"] = signature;
|
||||
|
||||
qCInfo(commerce) << "Transaction:" << QJsonDocument(request).toJson(QJsonDocument::Compact);
|
||||
// FIXME: talk to server instead
|
||||
QStringList keySet{ hfc_key };
|
||||
if (initializedBalance() < cost) return false;
|
||||
_balance -= cost;
|
||||
_inventory.push_back(asset_id);
|
||||
return true; // FIXME send to server.
|
||||
}
|
||||
|
||||
|
@ -45,4 +50,16 @@ bool Ledger::receiveAt(const QString& hfc_key) {
|
|||
auto username = accountManager->getAccountInfo().getUsername();
|
||||
qCInfo(commerce) << "Setting default receiving key for" << username;
|
||||
return true; // FIXME send to server.
|
||||
}
|
||||
|
||||
int Ledger::balance(const QStringList& keys) {
|
||||
// FIXME: talk to server instead
|
||||
qCInfo(commerce) << "Balance:" << initializedBalance();
|
||||
return _balance;
|
||||
}
|
||||
|
||||
QStringList Ledger::inventory(const QStringList& keys) {
|
||||
// FIXME: talk to server instead
|
||||
qCInfo(commerce) << "Inventory:" << _inventory;
|
||||
return _inventory;
|
||||
}
|
|
@ -23,6 +23,14 @@ class Ledger : public QObject, public Dependency {
|
|||
public:
|
||||
bool buy(const QString& hfc_key, int cost, const QString& asset_id, const QString& inventory_key, const QString& buyerUsername = "");
|
||||
bool receiveAt(const QString& hfc_key);
|
||||
int balance(const QStringList& keys);
|
||||
QStringList inventory(const QStringList& keys);
|
||||
|
||||
private:
|
||||
// These in-memory caches is temporary, until we start sending things to the server.
|
||||
int _balance{ -1 };
|
||||
QStringList _inventory{};
|
||||
int initializedBalance() { if (_balance < 0) _balance = 100; return _balance; }
|
||||
};
|
||||
|
||||
#endif // hifi_Ledger_h
|
||||
|
|
|
@ -26,5 +26,20 @@ bool QmlCommerce::buy(const QString& assetId, int cost, const QString& buyerUser
|
|||
}
|
||||
QString key = keys[0];
|
||||
// For now, we receive at the same key that pays for it.
|
||||
return ledger->buy(key, cost, assetId, key, buyerUsername);
|
||||
bool success = ledger->buy(key, cost, assetId, key, buyerUsername);
|
||||
// FIXME: until we start talking to server, report post-transaction balance and inventory so we can see log for testing.
|
||||
balance();
|
||||
inventory();
|
||||
return success;
|
||||
}
|
||||
|
||||
int QmlCommerce::balance() {
|
||||
auto ledger = DependencyManager::get<Ledger>();
|
||||
auto wallet = DependencyManager::get<Wallet>();
|
||||
return ledger->balance(wallet->listPublicKeys());
|
||||
}
|
||||
QStringList QmlCommerce::inventory() {
|
||||
auto ledger = DependencyManager::get<Ledger>();
|
||||
auto wallet = DependencyManager::get<Wallet>();
|
||||
return ledger->inventory(wallet->listPublicKeys());
|
||||
}
|
|
@ -21,8 +21,13 @@ class QmlCommerce : public OffscreenQmlDialog {
|
|||
Q_OBJECT
|
||||
HIFI_QML_DECL
|
||||
|
||||
signals:
|
||||
void buyResult(const QString& failureMessage);
|
||||
|
||||
protected:
|
||||
Q_INVOKABLE bool buy(const QString& assetId, int cost, const QString& buyerUsername = "");
|
||||
Q_INVOKABLE int balance();
|
||||
Q_INVOKABLE QStringList inventory();
|
||||
};
|
||||
|
||||
#endif // hifi_QmlCommerce_h
|
||||
|
|
|
@ -52,7 +52,7 @@ void setupPreferences() {
|
|||
|
||||
{
|
||||
auto getter = [=]()->QString { return myAvatar->getFullAvatarURLFromPreferences().toString(); };
|
||||
auto setter = [=](const QString& value) { myAvatar->useFullAvatarURL(value, ""); };
|
||||
auto setter = [=](const QString& value) { myAvatar->useFullAvatarURL(value, ""); qApp->clearAvatarOverrideUrl(); };
|
||||
auto preference = new AvatarPreference(AVATAR_BASICS, "Appearance", getter, setter);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ void Overlays::cleanupOverlaysToDelete() {
|
|||
} while (!_overlaysToDelete.isEmpty());
|
||||
}
|
||||
|
||||
if (transaction._removedItems.size() > 0) {
|
||||
if (transaction.hasRemovedItems()) {
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "scripting/AccountScriptingInterface.h"
|
||||
#include "scripting/HMDScriptingInterface.h"
|
||||
#include "scripting/AssetMappingsScriptingInterface.h"
|
||||
#include "scripting/MenuScriptingInterface.h"
|
||||
#include <Preferences.h>
|
||||
#include <ScriptEngines.h>
|
||||
#include "FileDialogHelper.h"
|
||||
|
@ -191,6 +192,7 @@ void Web3DOverlay::loadSourceURL() {
|
|||
_webSurface->getSurfaceContext()->setContextProperty("DialogsManager", DialogsManagerScriptingInterface::getInstance());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("InputConfiguration", DependencyManager::get<InputConfiguration>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("SoundCache", DependencyManager::get<SoundCache>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("MenuInterface", MenuScriptingInterface::getInstance());
|
||||
|
||||
_webSurface->getSurfaceContext()->setContextProperty("pathToFonts", "../../");
|
||||
|
||||
|
|
|
@ -160,6 +160,7 @@ AudioClient::AudioClient() :
|
|||
AbstractAudioInterface(),
|
||||
_gate(this),
|
||||
_audioInput(NULL),
|
||||
_dummyAudioInput(NULL),
|
||||
_desiredInputFormat(),
|
||||
_inputFormat(),
|
||||
_numInputCallbackBytes(0),
|
||||
|
@ -617,12 +618,11 @@ void AudioClient::start() {
|
|||
|
||||
void AudioClient::stop() {
|
||||
|
||||
// "switch" to invalid devices in order to shut down the state
|
||||
qCDebug(audioclient) << "AudioClient::stop(), about to call switchInputToAudioDevice(null)";
|
||||
switchInputToAudioDevice(QAudioDeviceInfo());
|
||||
qCDebug(audioclient) << "AudioClient::stop(), requesting switchInputToAudioDevice() to shut down";
|
||||
switchInputToAudioDevice(QAudioDeviceInfo(), true);
|
||||
|
||||
qCDebug(audioclient) << "AudioClient::stop(), about to call switchOutputToAudioDevice(null)";
|
||||
switchOutputToAudioDevice(QAudioDeviceInfo());
|
||||
qCDebug(audioclient) << "AudioClient::stop(), requesting switchOutputToAudioDevice() to shut down";
|
||||
switchOutputToAudioDevice(QAudioDeviceInfo(), true);
|
||||
}
|
||||
|
||||
void AudioClient::handleAudioEnvironmentDataPacket(QSharedPointer<ReceivedMessage> message) {
|
||||
|
@ -1125,6 +1125,15 @@ void AudioClient::handleMicAudioInput() {
|
|||
}
|
||||
}
|
||||
|
||||
void AudioClient::handleDummyAudioInput() {
|
||||
const int numNetworkBytes = _isStereoInput
|
||||
? AudioConstants::NETWORK_FRAME_BYTES_STEREO
|
||||
: AudioConstants::NETWORK_FRAME_BYTES_PER_CHANNEL;
|
||||
|
||||
QByteArray audioBuffer(numNetworkBytes, 0); // silent
|
||||
handleAudioInput(audioBuffer);
|
||||
}
|
||||
|
||||
void AudioClient::handleRecordedAudioInput(const QByteArray& audio) {
|
||||
QByteArray audioBuffer(audio);
|
||||
handleAudioInput(audioBuffer);
|
||||
|
@ -1401,7 +1410,7 @@ void AudioClient::outputFormatChanged() {
|
|||
_receivedAudioStream.outputFormatChanged(_outputFormat.sampleRate(), OUTPUT_CHANNEL_COUNT);
|
||||
}
|
||||
|
||||
bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceInfo) {
|
||||
bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceInfo, bool isShutdownRequest) {
|
||||
qCDebug(audioclient) << __FUNCTION__ << "inputDeviceInfo: [" << inputDeviceInfo.deviceName() << "]";
|
||||
bool supportedFormat = false;
|
||||
|
||||
|
@ -1423,16 +1432,29 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceIn
|
|||
_inputDeviceInfo = QAudioDeviceInfo();
|
||||
}
|
||||
|
||||
if (_dummyAudioInput) {
|
||||
_dummyAudioInput->stop();
|
||||
|
||||
_dummyAudioInput->deleteLater();
|
||||
_dummyAudioInput = NULL;
|
||||
}
|
||||
|
||||
if (_inputToNetworkResampler) {
|
||||
// if we were using an input to network resampler, delete it here
|
||||
delete _inputToNetworkResampler;
|
||||
_inputToNetworkResampler = NULL;
|
||||
}
|
||||
|
||||
if (_audioGate) {
|
||||
delete _audioGate;
|
||||
_audioGate = nullptr;
|
||||
}
|
||||
|
||||
if (isShutdownRequest) {
|
||||
qCDebug(audioclient) << "The audio input device has shut down.";
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!inputDeviceInfo.isNull()) {
|
||||
qCDebug(audioclient) << "The audio input device " << inputDeviceInfo.deviceName() << "is available.";
|
||||
_inputDeviceInfo = inputDeviceInfo;
|
||||
|
@ -1480,11 +1502,34 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceIn
|
|||
supportedFormat = true;
|
||||
} else {
|
||||
qCDebug(audioclient) << "Error starting audio input -" << _audioInput->error();
|
||||
_audioInput->deleteLater();
|
||||
_audioInput = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there is no working input device, use the dummy input device.
|
||||
// It generates audio callbacks on a timer to simulate a mic stream of silent packets.
|
||||
// This enables clients without a mic to still receive an audio stream from the mixer.
|
||||
if (!_audioInput) {
|
||||
qCDebug(audioclient) << "Audio input device is not available, using dummy input.";
|
||||
_inputDeviceInfo = QAudioDeviceInfo();
|
||||
emit deviceChanged(QAudio::AudioInput, _inputDeviceInfo);
|
||||
|
||||
_inputFormat = _desiredInputFormat;
|
||||
qCDebug(audioclient) << "The format to be used for audio input is" << _inputFormat;
|
||||
qCDebug(audioclient) << "No resampling required for audio input to match desired network format.";
|
||||
|
||||
_audioGate = new AudioGate(_desiredInputFormat.sampleRate(), _desiredInputFormat.channelCount());
|
||||
qCDebug(audioclient) << "Noise gate created with" << _desiredInputFormat.channelCount() << "channels.";
|
||||
|
||||
// generate audio callbacks at the network sample rate
|
||||
_dummyAudioInput = new QTimer(this);
|
||||
connect(_dummyAudioInput, SIGNAL(timeout()), this, SLOT(handleDummyAudioInput()));
|
||||
_dummyAudioInput->start((int)(AudioConstants::NETWORK_FRAME_MSECS + 0.5f));
|
||||
}
|
||||
|
||||
return supportedFormat;
|
||||
}
|
||||
|
||||
|
@ -1518,9 +1563,8 @@ void AudioClient::outputNotify() {
|
|||
}
|
||||
}
|
||||
|
||||
bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDeviceInfo) {
|
||||
bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDeviceInfo, bool isShutdownRequest) {
|
||||
qCDebug(audioclient) << "AudioClient::switchOutputToAudioDevice() outputDeviceInfo: [" << outputDeviceInfo.deviceName() << "]";
|
||||
|
||||
bool supportedFormat = false;
|
||||
|
||||
// NOTE: device start() uses the Qt internal device list
|
||||
|
@ -1564,6 +1608,11 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDevice
|
|||
_localToOutputResampler = NULL;
|
||||
}
|
||||
|
||||
if (isShutdownRequest) {
|
||||
qCDebug(audioclient) << "The audio output device has shut down.";
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!outputDeviceInfo.isNull()) {
|
||||
qCDebug(audioclient) << "The audio output device " << outputDeviceInfo.deviceName() << "is available.";
|
||||
_outputDeviceInfo = outputDeviceInfo;
|
||||
|
|
|
@ -170,6 +170,7 @@ public slots:
|
|||
|
||||
void sendDownstreamAudioStatsPacket() { _stats.publish(); }
|
||||
void handleMicAudioInput();
|
||||
void handleDummyAudioInput();
|
||||
void handleRecordedAudioInput(const QByteArray& audio);
|
||||
void reset();
|
||||
void audioMixerKilled();
|
||||
|
@ -277,6 +278,7 @@ private:
|
|||
|
||||
Mutex _injectorsMutex;
|
||||
QAudioInput* _audioInput;
|
||||
QTimer* _dummyAudioInput;
|
||||
QAudioFormat _desiredInputFormat;
|
||||
QAudioFormat _inputFormat;
|
||||
QIODevice* _inputDevice;
|
||||
|
@ -350,8 +352,8 @@ private:
|
|||
|
||||
void handleLocalEchoAndReverb(QByteArray& inputByteArray);
|
||||
|
||||
bool switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceInfo);
|
||||
bool switchOutputToAudioDevice(const QAudioDeviceInfo& outputDeviceInfo);
|
||||
bool switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceInfo, bool isShutdownRequest = false);
|
||||
bool switchOutputToAudioDevice(const QAudioDeviceInfo& outputDeviceInfo, bool isShutdownRequest = false);
|
||||
|
||||
// Callback acceleration dependent calculations
|
||||
int calculateNumberOfInputCallbackBytes(const QAudioFormat& format) const;
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <DebugDraw.h>
|
||||
#include <shared/Camera.h>
|
||||
#include <SoftAttachmentModel.h>
|
||||
#include <render/TransitionStage.h>
|
||||
|
||||
#include "Logging.h"
|
||||
|
||||
|
@ -61,7 +62,7 @@ namespace render {
|
|||
template <> uint32_t metaFetchMetaSubItems(const AvatarSharedPointer& avatar, ItemIDs& subItems) {
|
||||
auto avatarPtr = static_pointer_cast<Avatar>(avatar);
|
||||
if (avatarPtr->getSkeletonModel()) {
|
||||
auto metaSubItems = avatarPtr->getSkeletonModel()->fetchRenderItemIDs();
|
||||
auto& metaSubItems = avatarPtr->getSkeletonModel()->fetchRenderItemIDs();
|
||||
subItems.insert(subItems.end(), metaSubItems.begin(), metaSubItems.end());
|
||||
return (uint32_t) metaSubItems.size();
|
||||
}
|
||||
|
@ -493,6 +494,48 @@ void Avatar::addToScene(AvatarSharedPointer self, const render::ScenePointer& sc
|
|||
for (auto& attachmentModel : _attachmentModels) {
|
||||
attachmentModel->addToScene(scene, transaction);
|
||||
}
|
||||
|
||||
_mustFadeIn = true;
|
||||
}
|
||||
|
||||
void Avatar::fadeIn(render::ScenePointer scene) {
|
||||
render::Transaction transaction;
|
||||
fade(transaction, render::Transition::USER_ENTER_DOMAIN);
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
|
||||
void Avatar::fadeOut(render::ScenePointer scene, KillAvatarReason reason) {
|
||||
render::Transition::Type transitionType = render::Transition::USER_LEAVE_DOMAIN;
|
||||
render::Transaction transaction;
|
||||
|
||||
if (reason == KillAvatarReason::YourAvatarEnteredTheirBubble) {
|
||||
transitionType = render::Transition::BUBBLE_ISECT_TRESPASSER;
|
||||
}
|
||||
else if (reason == KillAvatarReason::TheirAvatarEnteredYourBubble) {
|
||||
transitionType = render::Transition::BUBBLE_ISECT_OWNER;
|
||||
}
|
||||
fade(transaction, transitionType);
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
|
||||
void Avatar::fade(render::Transaction& transaction, render::Transition::Type type) {
|
||||
transaction.addTransitionToItem(_renderItemID, type);
|
||||
for (auto& attachmentModel : _attachmentModels) {
|
||||
for (auto itemId : attachmentModel->fetchRenderItemIDs()) {
|
||||
transaction.addTransitionToItem(itemId, type, _renderItemID);
|
||||
}
|
||||
}
|
||||
_isFading = true;
|
||||
}
|
||||
|
||||
void Avatar::updateFadingStatus(render::ScenePointer scene) {
|
||||
render::Transaction transaction;
|
||||
transaction.queryTransitionOnItem(_renderItemID, [this](render::ItemID id, const render::Transition* transition) {
|
||||
if (transition == nullptr || transition->isFinished) {
|
||||
_isFading = false;
|
||||
}
|
||||
});
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
|
||||
void Avatar::removeFromScene(AvatarSharedPointer self, const render::ScenePointer& scene, render::Transaction& transaction) {
|
||||
|
@ -629,6 +672,8 @@ void Avatar::render(RenderArgs* renderArgs) {
|
|||
}
|
||||
|
||||
void Avatar::fixupModelsInScene(const render::ScenePointer& scene) {
|
||||
bool canTryFade{ false };
|
||||
|
||||
_attachmentsToDelete.clear();
|
||||
|
||||
// check to see if when we added our models to the scene they were ready, if they were not ready, then
|
||||
|
@ -637,6 +682,7 @@ void Avatar::fixupModelsInScene(const render::ScenePointer& scene) {
|
|||
if (_skeletonModel->isRenderable() && _skeletonModel->needsFixupInScene()) {
|
||||
_skeletonModel->removeFromScene(scene, transaction);
|
||||
_skeletonModel->addToScene(scene, transaction);
|
||||
canTryFade = true;
|
||||
}
|
||||
for (auto attachmentModel : _attachmentModels) {
|
||||
if (attachmentModel->isRenderable() && attachmentModel->needsFixupInScene()) {
|
||||
|
@ -645,6 +691,12 @@ void Avatar::fixupModelsInScene(const render::ScenePointer& scene) {
|
|||
}
|
||||
}
|
||||
|
||||
if (_mustFadeIn && canTryFade) {
|
||||
// Do it now to be sure all the sub items are ready and the fade is sent to them too
|
||||
fade(transaction, render::Transition::USER_ENTER_DOMAIN);
|
||||
_mustFadeIn = false;
|
||||
}
|
||||
|
||||
for (auto attachmentModelToRemove : _attachmentsToRemove) {
|
||||
attachmentModelToRemove->removeFromScene(scene, transaction);
|
||||
}
|
||||
|
|
|
@ -246,6 +246,11 @@ public:
|
|||
void addPhysicsFlags(uint32_t flags);
|
||||
bool isInPhysicsSimulation() const { return _physicsCallback != nullptr; }
|
||||
|
||||
void fadeIn(render::ScenePointer scene);
|
||||
void fadeOut(render::ScenePointer scene, KillAvatarReason reason);
|
||||
bool isFading() const { return _isFading; }
|
||||
void updateFadingStatus(render::ScenePointer scene);
|
||||
|
||||
public slots:
|
||||
|
||||
// FIXME - these should be migrated to use Pose data instead
|
||||
|
@ -297,6 +302,8 @@ protected:
|
|||
// protected methods...
|
||||
bool isLookingAtMe(AvatarSharedPointer avatar) const;
|
||||
|
||||
void fade(render::Transaction& transaction, render::Transition::Type type);
|
||||
|
||||
glm::vec3 getBodyRightDirection() const { return getOrientation() * IDENTITY_RIGHT; }
|
||||
glm::vec3 getBodyUpDirection() const { return getOrientation() * IDENTITY_UP; }
|
||||
void measureMotionDerivatives(float deltaTime);
|
||||
|
@ -344,6 +351,8 @@ private:
|
|||
bool _initialized { false };
|
||||
bool _isLookAtTarget { false };
|
||||
bool _isAnimatingScale { false };
|
||||
bool _mustFadeIn { false };
|
||||
bool _isFading { false };
|
||||
|
||||
static int _jointConesID;
|
||||
|
||||
|
|
|
@ -675,7 +675,7 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) {
|
|||
|
||||
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
||||
|
||||
bool precisionPicking = true; // for mouse moves we do precision picking
|
||||
bool precisionPicking = false; // for mouse moves we do not do precision picking
|
||||
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::TryLock, precisionPicking);
|
||||
if (rayPickResult.intersects) {
|
||||
|
||||
|
|
|
@ -130,3 +130,42 @@ void makeEntityItemStatusGetters(EntityItemPointer entity, render::Item::Status:
|
|||
(unsigned char)RenderItemStatusIcon::CLIENT_ONLY);
|
||||
});
|
||||
}
|
||||
|
||||
bool SimplerRenderableEntitySupport::addToScene(const EntityItemPointer& self, const render::ScenePointer& scene, render::Transaction& transaction) {
|
||||
_myItem = scene->allocateID();
|
||||
|
||||
auto renderData = std::make_shared<RenderableEntityItemProxy>(self, _myItem);
|
||||
auto renderPayload = std::make_shared<RenderableEntityItemProxy::Payload>(renderData);
|
||||
|
||||
render::Item::Status::Getters statusGetters;
|
||||
makeEntityItemStatusGetters(self, statusGetters);
|
||||
renderPayload->addStatusGetters(statusGetters);
|
||||
|
||||
transaction.resetItem(_myItem, renderPayload);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SimplerRenderableEntitySupport::removeFromScene(const EntityItemPointer& self, const render::ScenePointer& scene, render::Transaction& transaction) {
|
||||
transaction.removeItem(_myItem);
|
||||
render::Item::clearID(_myItem);
|
||||
}
|
||||
|
||||
void SimplerRenderableEntitySupport::notifyChanged() {
|
||||
if (!render::Item::isValidID(_myItem)) {
|
||||
return;
|
||||
}
|
||||
|
||||
render::Transaction transaction;
|
||||
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
|
||||
|
||||
if (scene) {
|
||||
transaction.updateItem<RenderableEntityItemProxy>(_myItem, [](RenderableEntityItemProxy& data) {
|
||||
});
|
||||
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
else {
|
||||
qCWarning(entitiesrenderer) << "SimpleRenderableEntityItem::notifyChanged(), Unexpected null scene, possibly during application shutdown";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,44 +70,13 @@ namespace render {
|
|||
// Mixin class for implementing basic single item rendering
|
||||
class SimplerRenderableEntitySupport : public RenderableEntityInterface {
|
||||
public:
|
||||
bool addToScene(const EntityItemPointer& self, const render::ScenePointer& scene, render::Transaction& transaction) override {
|
||||
_myItem = scene->allocateID();
|
||||
|
||||
auto renderData = std::make_shared<RenderableEntityItemProxy>(self, _myItem);
|
||||
auto renderPayload = std::make_shared<RenderableEntityItemProxy::Payload>(renderData);
|
||||
bool addToScene(const EntityItemPointer& self, const render::ScenePointer& scene, render::Transaction& transaction) override;
|
||||
void removeFromScene(const EntityItemPointer& self, const render::ScenePointer& scene, render::Transaction& transaction) override;
|
||||
void notifyChanged();
|
||||
|
||||
render::Item::Status::Getters statusGetters;
|
||||
makeEntityItemStatusGetters(self, statusGetters);
|
||||
renderPayload->addStatusGetters(statusGetters);
|
||||
protected:
|
||||
|
||||
transaction.resetItem(_myItem, renderPayload);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void removeFromScene(const EntityItemPointer& self, const render::ScenePointer& scene, render::Transaction& transaction) override {
|
||||
transaction.removeItem(_myItem);
|
||||
render::Item::clearID(_myItem);
|
||||
}
|
||||
|
||||
void notifyChanged() {
|
||||
if (!render::Item::isValidID(_myItem)) {
|
||||
return;
|
||||
}
|
||||
|
||||
render::Transaction transaction;
|
||||
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
|
||||
|
||||
if (scene) {
|
||||
transaction.updateItem<RenderableEntityItemProxy>(_myItem, [](RenderableEntityItemProxy& data) {
|
||||
});
|
||||
|
||||
scene->enqueueTransaction(transaction);
|
||||
} else {
|
||||
qCWarning(entitiesrenderer) << "SimpleRenderableEntityItem::notifyChanged(), Unexpected null scene, possibly during application shutdown";
|
||||
}
|
||||
}
|
||||
private:
|
||||
render::ItemID _myItem { render::Item::INVALID_ITEM_ID };
|
||||
};
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <PerfStat.h>
|
||||
#include <render/Scene.h>
|
||||
#include <DependencyManager.h>
|
||||
#include <AnimationCache.h>
|
||||
#include <shared/QtHelpers.h>
|
||||
|
||||
#include "EntityTreeRenderer.h"
|
||||
|
@ -218,8 +219,9 @@ namespace render {
|
|||
}
|
||||
template <> uint32_t metaFetchMetaSubItems(const RenderableModelEntityItemMeta::Pointer& payload, ItemIDs& subItems) {
|
||||
auto modelEntity = std::static_pointer_cast<RenderableModelEntityItem>(payload->entity);
|
||||
if (modelEntity->hasModel()) {
|
||||
auto metaSubItems = modelEntity->getModelNotSafe()->fetchRenderItemIDs();
|
||||
auto model = modelEntity->getModelNotSafe();
|
||||
if (model && modelEntity->hasModel()) {
|
||||
auto& metaSubItems = model->fetchRenderItemIDs();
|
||||
subItems.insert(subItems.end(), metaSubItems.begin(), metaSubItems.end());
|
||||
return (uint32_t) metaSubItems.size();
|
||||
}
|
||||
|
@ -242,6 +244,12 @@ bool RenderableModelEntityItem::addToScene(const EntityItemPointer& self, const
|
|||
|
||||
// note: we don't mind if the model fails to add, we'll retry (in render()) until it succeeds
|
||||
_model->addToScene(scene, transaction, statusGetters);
|
||||
#ifdef MODEL_ENTITY_USE_FADE_EFFECT
|
||||
if (!_hasTransitioned) {
|
||||
transaction.addTransitionToItem(_myMetaItem, render::Transition::ELEMENT_ENTER_DOMAIN);
|
||||
_hasTransitioned = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// we've successfully added _myMetaItem so we always return true
|
||||
|
@ -364,6 +372,7 @@ void RenderableModelEntityItem::updateModelBounds() {
|
|||
// the per frame simulation/update that might be required if the models properties changed.
|
||||
void RenderableModelEntityItem::render(RenderArgs* args) {
|
||||
PerformanceTimer perfTimer("RMEIrender");
|
||||
|
||||
assert(getType() == EntityTypes::Model);
|
||||
|
||||
// When the individual mesh parts of a model finish fading, they will mark their Model as needing updating
|
||||
|
@ -490,6 +499,12 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
|
|||
makeEntityItemStatusGetters(getThisPointer(), statusGetters);
|
||||
_model->addToScene(scene, transaction, statusGetters);
|
||||
|
||||
#ifdef MODEL_ENTITY_USE_FADE_EFFECT
|
||||
if (!_hasTransitioned) {
|
||||
transaction.addTransitionToItem(_myMetaItem, render::Transition::ELEMENT_ENTER_DOMAIN);
|
||||
_hasTransitioned = true;
|
||||
}
|
||||
#endif
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,11 +16,14 @@
|
|||
#include <QStringList>
|
||||
|
||||
#include <ModelEntityItem.h>
|
||||
#include <AnimationCache.h>
|
||||
|
||||
#include "RenderableEntityItem.h"
|
||||
|
||||
class Model;
|
||||
class EntityTreeRenderer;
|
||||
|
||||
//#define MODEL_ENTITY_USE_FADE_EFFECT
|
||||
|
||||
class RenderableModelEntityItem : public ModelEntityItem, RenderableEntityInterface {
|
||||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
@ -133,7 +136,9 @@ private:
|
|||
QVariantMap _originalTextures;
|
||||
bool _originalTexturesRead = false;
|
||||
bool _dimensionsInitialized = true;
|
||||
|
||||
#ifdef MODEL_ENTITY_USE_FADE_EFFECT
|
||||
bool _hasTransitioned{ false };
|
||||
#endif
|
||||
AnimationPropertyGroup _renderAnimationProperties;
|
||||
|
||||
render::ItemID _myMetaItem{ render::Item::INVALID_ITEM_ID };
|
||||
|
|
|
@ -17,22 +17,101 @@
|
|||
#include <PathUtils.h>
|
||||
#include <PerfStat.h>
|
||||
|
||||
//#define POLYLINE_ENTITY_USE_FADE_EFFECT
|
||||
#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
|
||||
# include <FadeEffect.h>
|
||||
#endif
|
||||
|
||||
#include "RenderablePolyLineEntityItem.h"
|
||||
|
||||
#include "paintStroke_vert.h"
|
||||
#include "paintStroke_frag.h"
|
||||
|
||||
#include "paintStroke_fade_vert.h"
|
||||
#include "paintStroke_fade_frag.h"
|
||||
|
||||
uint8_t PolyLinePayload::CUSTOM_PIPELINE_NUMBER = 0;
|
||||
|
||||
gpu::PipelinePointer PolyLinePayload::_pipeline;
|
||||
gpu::PipelinePointer PolyLinePayload::_fadePipeline;
|
||||
|
||||
const int32_t PolyLinePayload::PAINTSTROKE_TEXTURE_SLOT;
|
||||
const int32_t PolyLinePayload::PAINTSTROKE_UNIFORM_SLOT;
|
||||
|
||||
render::ShapePipelinePointer PolyLinePayload::shapePipelineFactory(const render::ShapePlumber& plumber, const render::ShapeKey& key) {
|
||||
if (!_pipeline) {
|
||||
auto VS = gpu::Shader::createVertex(std::string(paintStroke_vert));
|
||||
auto PS = gpu::Shader::createPixel(std::string(paintStroke_frag));
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(VS, PS);
|
||||
#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
|
||||
auto fadeVS = gpu::Shader::createVertex(std::string(paintStroke_fade_vert));
|
||||
auto fadePS = gpu::Shader::createPixel(std::string(paintStroke_fade_frag));
|
||||
gpu::ShaderPointer fadeProgram = gpu::Shader::createProgram(fadeVS, fadePS);
|
||||
#endif
|
||||
gpu::Shader::BindingSet slotBindings;
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("originalTexture"), PAINTSTROKE_TEXTURE_SLOT));
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("polyLineBuffer"), PAINTSTROKE_UNIFORM_SLOT));
|
||||
gpu::Shader::makeProgram(*program, slotBindings);
|
||||
#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), PAINTSTROKE_TEXTURE_SLOT + 1));
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("fadeParametersBuffer"), PAINTSTROKE_UNIFORM_SLOT+1));
|
||||
gpu::Shader::makeProgram(*fadeProgram, slotBindings);
|
||||
#endif
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
PrepareStencil::testMask(*state);
|
||||
state->setBlendFunction(true,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
_pipeline = gpu::Pipeline::create(program, state);
|
||||
#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
|
||||
_fadePipeline = gpu::Pipeline::create(fadeProgram, state);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
|
||||
if (key.isFaded()) {
|
||||
auto fadeEffect = DependencyManager::get<FadeEffect>();
|
||||
return std::make_shared<render::ShapePipeline>(_fadePipeline, nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter());
|
||||
} else {
|
||||
#endif
|
||||
return std::make_shared<render::ShapePipeline>(_pipeline, nullptr, nullptr, nullptr);
|
||||
#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace render {
|
||||
template <> const ItemKey payloadGetKey(const PolyLinePayload::Pointer& payload) {
|
||||
return payloadGetKey(std::static_pointer_cast<RenderableEntityItemProxy>(payload));
|
||||
}
|
||||
template <> const Item::Bound payloadGetBound(const PolyLinePayload::Pointer& payload) {
|
||||
return payloadGetBound(std::static_pointer_cast<RenderableEntityItemProxy>(payload));
|
||||
}
|
||||
template <> void payloadRender(const PolyLinePayload::Pointer& payload, RenderArgs* args) {
|
||||
payloadRender(std::static_pointer_cast<RenderableEntityItemProxy>(payload), args);
|
||||
}
|
||||
template <> uint32_t metaFetchMetaSubItems(const PolyLinePayload::Pointer& payload, ItemIDs& subItems) {
|
||||
return metaFetchMetaSubItems(std::static_pointer_cast<RenderableEntityItemProxy>(payload), subItems);
|
||||
}
|
||||
|
||||
template <> const ShapeKey shapeGetShapeKey(const PolyLinePayload::Pointer& payload) {
|
||||
auto shapeKey = ShapeKey::Builder().withCustom(PolyLinePayload::CUSTOM_PIPELINE_NUMBER);
|
||||
return shapeKey.build();
|
||||
}
|
||||
}
|
||||
|
||||
struct PolyLineUniforms {
|
||||
glm::vec3 color;
|
||||
};
|
||||
|
||||
|
||||
|
||||
EntityItemPointer RenderablePolyLineEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity{ new RenderablePolyLineEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
|
||||
// As we create the first PolyLine entity, let's register its special shapePipeline factory:
|
||||
PolyLinePayload::registerShapePipeline();
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
|
@ -45,12 +124,9 @@ _numVertices(0)
|
|||
_uniformBuffer = std::make_shared<gpu::Buffer>(sizeof(PolyLineUniforms), (const gpu::Byte*) &uniforms);
|
||||
}
|
||||
|
||||
gpu::PipelinePointer RenderablePolyLineEntityItem::_pipeline;
|
||||
gpu::Stream::FormatPointer RenderablePolyLineEntityItem::_format;
|
||||
const int32_t RenderablePolyLineEntityItem::PAINTSTROKE_TEXTURE_SLOT;
|
||||
const int32_t RenderablePolyLineEntityItem::PAINTSTROKE_UNIFORM_SLOT;
|
||||
|
||||
void RenderablePolyLineEntityItem::createPipeline() {
|
||||
void RenderablePolyLineEntityItem::createStreamFormat() {
|
||||
static const int NORMAL_OFFSET = 12;
|
||||
static const int TEXTURE_OFFSET = 24;
|
||||
|
||||
|
@ -58,23 +134,6 @@ void RenderablePolyLineEntityItem::createPipeline() {
|
|||
_format->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
|
||||
_format->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), NORMAL_OFFSET);
|
||||
_format->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), TEXTURE_OFFSET);
|
||||
|
||||
auto VS = gpu::Shader::createVertex(std::string(paintStroke_vert));
|
||||
auto PS = gpu::Shader::createPixel(std::string(paintStroke_frag));
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(VS, PS);
|
||||
|
||||
gpu::Shader::BindingSet slotBindings;
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("originalTexture"), PAINTSTROKE_TEXTURE_SLOT));
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("polyLineBuffer"), PAINTSTROKE_UNIFORM_SLOT));
|
||||
gpu::Shader::makeProgram(*program, slotBindings);
|
||||
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
PrepareStencil::testMask(*state);
|
||||
state->setBlendFunction(true,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
_pipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
|
||||
void RenderablePolyLineEntityItem::updateGeometry() {
|
||||
|
@ -158,10 +217,7 @@ void RenderablePolyLineEntityItem::updateVertices() {
|
|||
|
||||
}
|
||||
|
||||
void RenderablePolyLineEntityItem::update(const quint64& now) {
|
||||
PolyLineUniforms uniforms;
|
||||
uniforms.color = toGlm(getXColor());
|
||||
memcpy(&_uniformBuffer.edit<PolyLineUniforms>(), &uniforms, sizeof(PolyLineUniforms));
|
||||
void RenderablePolyLineEntityItem::updateMesh() {
|
||||
if (_pointsChanged || _strokeWidthsChanged || _normalsChanged) {
|
||||
QWriteLocker lock(&_quadReadWriteLock);
|
||||
_empty = (_points.size() < 2 || _normals.size() < 2 || _strokeWidths.size() < 2);
|
||||
|
@ -170,18 +226,46 @@ void RenderablePolyLineEntityItem::update(const quint64& now) {
|
|||
updateGeometry();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderablePolyLineEntityItem::update(const quint64& now) {
|
||||
PolyLineUniforms uniforms;
|
||||
uniforms.color = toGlm(getXColor());
|
||||
memcpy(&_uniformBuffer.edit<PolyLineUniforms>(), &uniforms, sizeof(PolyLineUniforms));
|
||||
updateMesh();
|
||||
}
|
||||
|
||||
bool RenderablePolyLineEntityItem::addToScene(const EntityItemPointer& self,
|
||||
const render::ScenePointer& scene,
|
||||
render::Transaction& transaction) {
|
||||
_myItem = scene->allocateID();
|
||||
|
||||
auto renderData = std::make_shared<PolyLinePayload>(self, _myItem);
|
||||
auto renderPayload = std::make_shared<PolyLinePayload::Payload>(renderData);
|
||||
|
||||
render::Item::Status::Getters statusGetters;
|
||||
makeEntityItemStatusGetters(self, statusGetters);
|
||||
renderPayload->addStatusGetters(statusGetters);
|
||||
|
||||
transaction.resetItem(_myItem, renderPayload);
|
||||
#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
|
||||
transaction.addTransitionToItem(_myItem, render::Transition::ELEMENT_ENTER_DOMAIN);
|
||||
#endif
|
||||
updateMesh();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RenderablePolyLineEntityItem::render(RenderArgs* args) {
|
||||
#ifndef POLYLINE_ENTITY_USE_FADE_EFFECT
|
||||
checkFading();
|
||||
|
||||
#endif
|
||||
if (_empty) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_pipeline) {
|
||||
createPipeline();
|
||||
if (!_format) {
|
||||
createStreamFormat();
|
||||
}
|
||||
|
||||
if (!_texture || _texturesChangedFlag) {
|
||||
|
@ -199,24 +283,26 @@ void RenderablePolyLineEntityItem::render(RenderArgs* args) {
|
|||
Transform transform = Transform();
|
||||
transform.setTranslation(getPosition());
|
||||
transform.setRotation(getRotation());
|
||||
batch.setUniformBuffer(PAINTSTROKE_UNIFORM_SLOT, _uniformBuffer);
|
||||
batch.setUniformBuffer(PolyLinePayload::PAINTSTROKE_UNIFORM_SLOT, _uniformBuffer);
|
||||
batch.setModelTransform(transform);
|
||||
|
||||
batch.setPipeline(_pipeline);
|
||||
if (_texture->isLoaded()) {
|
||||
batch.setResourceTexture(PAINTSTROKE_TEXTURE_SLOT, _texture->getGPUTexture());
|
||||
batch.setResourceTexture(PolyLinePayload::PAINTSTROKE_TEXTURE_SLOT, _texture->getGPUTexture());
|
||||
} else {
|
||||
batch.setResourceTexture(PAINTSTROKE_TEXTURE_SLOT, nullptr);
|
||||
batch.setResourceTexture(PolyLinePayload::PAINTSTROKE_TEXTURE_SLOT, nullptr);
|
||||
}
|
||||
|
||||
batch.setInputFormat(_format);
|
||||
batch.setInputBuffer(0, _verticesBuffer, 0, _format->getChannels().at(0)._stride);
|
||||
|
||||
#ifndef POLYLINE_ENTITY_USE_FADE_EFFECT
|
||||
if (_isFading) {
|
||||
batch._glColor4f(1.0f, 1.0f, 1.0f, Interpolate::calculateFadeRatio(_fadeStartTime));
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
#endif
|
||||
|
||||
batch.draw(gpu::TRIANGLE_STRIP, _numVertices, 0);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -22,15 +22,48 @@
|
|||
#include <QReadWriteLock>
|
||||
|
||||
|
||||
class PolyLinePayload : public RenderableEntityItemProxy {
|
||||
public:
|
||||
|
||||
static uint8_t CUSTOM_PIPELINE_NUMBER;
|
||||
static render::ShapePipelinePointer shapePipelineFactory(const render::ShapePlumber& plumber, const render::ShapeKey& key);
|
||||
static void registerShapePipeline() {
|
||||
if (!CUSTOM_PIPELINE_NUMBER) {
|
||||
CUSTOM_PIPELINE_NUMBER = render::ShapePipeline::registerCustomShapePipelineFactory(shapePipelineFactory);
|
||||
}
|
||||
}
|
||||
static gpu::PipelinePointer _pipeline;
|
||||
static gpu::PipelinePointer _fadePipeline;
|
||||
|
||||
static const int32_t PAINTSTROKE_TEXTURE_SLOT{ 0 };
|
||||
static const int32_t PAINTSTROKE_UNIFORM_SLOT{ 0 };
|
||||
|
||||
PolyLinePayload(const EntityItemPointer& entity, render::ItemID metaID)
|
||||
: RenderableEntityItemProxy(entity, metaID) {}
|
||||
typedef render::Payload<PolyLinePayload> Payload;
|
||||
typedef Payload::DataPointer Pointer;
|
||||
|
||||
};
|
||||
|
||||
namespace render {
|
||||
template <> const ItemKey payloadGetKey(const PolyLinePayload::Pointer& payload);
|
||||
template <> const Item::Bound payloadGetBound(const PolyLinePayload::Pointer& payload);
|
||||
template <> void payloadRender(const PolyLinePayload::Pointer& payload, RenderArgs* args);
|
||||
template <> uint32_t metaFetchMetaSubItems(const PolyLinePayload::Pointer& payload, ItemIDs& subItems);
|
||||
template <> const ShapeKey shapeGetShapeKey(const PolyLinePayload::Pointer& payload);
|
||||
}
|
||||
|
||||
class RenderablePolyLineEntityItem : public PolyLineEntityItem, public SimplerRenderableEntitySupport {
|
||||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
static void createPipeline();
|
||||
RenderablePolyLineEntityItem(const EntityItemID& entityItemID);
|
||||
|
||||
virtual void render(RenderArgs* args) override;
|
||||
virtual void update(const quint64& now) override;
|
||||
virtual bool needsToCallUpdate() const override { return true; }
|
||||
virtual bool addToScene(const EntityItemPointer& self,
|
||||
const render::ScenePointer& scene,
|
||||
render::Transaction& transaction) override;
|
||||
|
||||
bool isTransparent() override { return true; }
|
||||
|
||||
|
@ -38,15 +71,15 @@ public:
|
|||
|
||||
NetworkTexturePointer _texture;
|
||||
|
||||
static gpu::PipelinePointer _pipeline;
|
||||
static gpu::Stream::FormatPointer _format;
|
||||
|
||||
static const int32_t PAINTSTROKE_TEXTURE_SLOT { 0 };
|
||||
static const int32_t PAINTSTROKE_UNIFORM_SLOT { 0 };
|
||||
|
||||
protected:
|
||||
void updateGeometry();
|
||||
void updateVertices();
|
||||
void updateMesh();
|
||||
|
||||
static void createStreamFormat();
|
||||
|
||||
gpu::BufferPointer _verticesBuffer;
|
||||
gpu::BufferView _uniformBuffer;
|
||||
unsigned int _numVertices;
|
||||
|
|
|
@ -20,6 +20,10 @@
|
|||
#include <model-networking/SimpleMeshProxy.h>
|
||||
#include "ModelScriptingInterface.h"
|
||||
|
||||
#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT
|
||||
# include <FadeEffect.h>
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdouble-promotion"
|
||||
|
@ -56,6 +60,10 @@
|
|||
#include "EntityTreeRenderer.h"
|
||||
#include "polyvox_vert.h"
|
||||
#include "polyvox_frag.h"
|
||||
#include "polyvox_fade_vert.h"
|
||||
#include "polyvox_fade_frag.h"
|
||||
|
||||
#include "RenderablePolyVoxEntityItem.h"
|
||||
#include "EntityEditPacketSender.h"
|
||||
#include "PhysicalEntitySimulation.h"
|
||||
|
||||
|
@ -803,6 +811,12 @@ bool RenderablePolyVoxEntityItem::addToScene(const EntityItemPointer& self,
|
|||
renderPayload->addStatusGetters(statusGetters);
|
||||
|
||||
transaction.resetItem(_myItem, renderPayload);
|
||||
#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT
|
||||
if (_mesh && _mesh->getIndexBuffer()._buffer) {
|
||||
transaction.addTransitionToItem(_myItem, render::Transition::ELEMENT_ENTER_DOMAIN);
|
||||
_hasTransitioned = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -816,44 +830,64 @@ void RenderablePolyVoxEntityItem::removeFromScene(const EntityItemPointer& self,
|
|||
|
||||
uint8_t PolyVoxPayload::CUSTOM_PIPELINE_NUMBER = 0;
|
||||
|
||||
std::shared_ptr<gpu::Pipeline> PolyVoxPayload::_pipeline;
|
||||
std::shared_ptr<gpu::Pipeline> PolyVoxPayload::_wireframePipeline;
|
||||
gpu::PipelinePointer PolyVoxPayload::_pipelines[2] = { nullptr, nullptr };
|
||||
gpu::PipelinePointer PolyVoxPayload::_wireframePipelines[2] = { nullptr, nullptr };
|
||||
|
||||
render::ShapePipelinePointer PolyVoxPayload::shapePipelineFactory(const render::ShapePlumber& plumber, const render::ShapeKey& key) {
|
||||
if (!_pipeline) {
|
||||
gpu::ShaderPointer vertexShader = gpu::Shader::createVertex(std::string(polyvox_vert));
|
||||
gpu::ShaderPointer pixelShader = gpu::Shader::createPixel(std::string(polyvox_frag));
|
||||
if (!_pipelines[0]) {
|
||||
gpu::ShaderPointer vertexShaders[2] = { gpu::Shader::createVertex(std::string(polyvox_vert)), gpu::Shader::createVertex(std::string(polyvox_fade_vert)) };
|
||||
gpu::ShaderPointer pixelShaders[2] = { gpu::Shader::createPixel(std::string(polyvox_frag)), gpu::Shader::createPixel(std::string(polyvox_fade_frag)) };
|
||||
|
||||
gpu::Shader::BindingSet slotBindings;
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), PolyVoxPayload::MATERIAL_GPU_SLOT));
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), MATERIAL_GPU_SLOT));
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("xMap"), 0));
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("yMap"), 1));
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("zMap"), 2));
|
||||
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vertexShader, pixelShader);
|
||||
gpu::Shader::makeProgram(*program, slotBindings);
|
||||
#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), 3));
|
||||
#endif
|
||||
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
state->setCullMode(gpu::State::CULL_BACK);
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
PrepareStencil::testMaskDrawShape(*state);
|
||||
|
||||
_pipeline = gpu::Pipeline::create(program, state);
|
||||
|
||||
auto wireframeState = std::make_shared<gpu::State>();
|
||||
wireframeState->setCullMode(gpu::State::CULL_BACK);
|
||||
wireframeState->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
wireframeState->setFillMode(gpu::State::FILL_LINE);
|
||||
PrepareStencil::testMaskDrawShape(*wireframeState);
|
||||
|
||||
_wireframePipeline = gpu::Pipeline::create(program, wireframeState);
|
||||
// Two sets of pipelines: normal and fading
|
||||
for (auto i = 0; i < 2; i++) {
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vertexShaders[i], pixelShaders[i]);
|
||||
gpu::Shader::makeProgram(*program, slotBindings);
|
||||
|
||||
_pipelines[i] = gpu::Pipeline::create(program, state);
|
||||
_wireframePipelines[i] = gpu::Pipeline::create(program, wireframeState);
|
||||
}
|
||||
}
|
||||
|
||||
if (key.isWireframe()) {
|
||||
return std::make_shared<render::ShapePipeline>(_wireframePipeline, nullptr, nullptr, nullptr);
|
||||
#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT
|
||||
if (key.isFaded()) {
|
||||
const auto& fadeEffect = DependencyManager::get<FadeEffect>();
|
||||
if (key.isWireframe()) {
|
||||
return std::make_shared<render::ShapePipeline>(_wireframePipelines[1], nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter());
|
||||
}
|
||||
else {
|
||||
return std::make_shared<render::ShapePipeline>(_pipelines[1], nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter());
|
||||
}
|
||||
} else {
|
||||
return std::make_shared<render::ShapePipeline>(_pipeline, nullptr, nullptr, nullptr);
|
||||
#endif
|
||||
if (key.isWireframe()) {
|
||||
return std::make_shared<render::ShapePipeline>(_wireframePipelines[0], nullptr, nullptr, nullptr);
|
||||
}
|
||||
else {
|
||||
return std::make_shared<render::ShapePipeline>(_pipelines[0], nullptr, nullptr, nullptr);
|
||||
}
|
||||
#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace render {
|
||||
|
@ -1368,6 +1402,16 @@ void RenderablePolyVoxEntityItem::setMesh(model::MeshPointer mesh) {
|
|||
if (neighborsNeedUpdate) {
|
||||
bonkNeighbors();
|
||||
}
|
||||
|
||||
#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT
|
||||
if (!_hasTransitioned) {
|
||||
render::Transaction transaction;
|
||||
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
|
||||
transaction.addTransitionToItem(_myItem, render::Transition::ELEMENT_ENTER_DOMAIN);
|
||||
scene->enqueueTransaction(transaction);
|
||||
_hasTransitioned = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void RenderablePolyVoxEntityItem::computeShapeInfoWorker() {
|
||||
|
@ -1631,6 +1675,7 @@ void RenderablePolyVoxEntityItem::bonkNeighbors() {
|
|||
|
||||
void RenderablePolyVoxEntityItem::locationChanged(bool tellPhysics) {
|
||||
EntityItem::locationChanged(tellPhysics);
|
||||
|
||||
if (!render::Item::isValidID(_myItem)) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
|
||||
#include "RenderableEntityItem.h"
|
||||
|
||||
//#define POLYVOX_ENTITY_USE_FADE_EFFECT
|
||||
|
||||
class PolyVoxPayload {
|
||||
public:
|
||||
|
||||
|
@ -38,8 +40,8 @@ public:
|
|||
}
|
||||
|
||||
static const int MATERIAL_GPU_SLOT = 3;
|
||||
static std::shared_ptr<gpu::Pipeline> _pipeline;
|
||||
static std::shared_ptr<gpu::Pipeline> _wireframePipeline;
|
||||
static gpu::PipelinePointer _pipelines[2];
|
||||
static gpu::PipelinePointer _wireframePipelines[2];
|
||||
|
||||
PolyVoxPayload(EntityItemPointer owner) : _owner(owner), _bounds(AABox()) { }
|
||||
typedef render::Payload<PolyVoxPayload> Payload;
|
||||
|
@ -161,7 +163,7 @@ public:
|
|||
|
||||
void setVolDataDirty() { withWriteLock([&] { _volDataDirty = true; _meshReady = false; }); }
|
||||
|
||||
// Transparent polyvox didn't seem to be working so disable for now
|
||||
// Transparent polyvox didn't seem to be working so disable for now.
|
||||
bool isTransparent() override { return false; }
|
||||
|
||||
bool getMeshes(MeshProxyList& result) override;
|
||||
|
@ -177,7 +179,9 @@ private:
|
|||
gpu::Stream::FormatPointer _vertexFormat;
|
||||
bool _meshDirty { true }; // does collision-shape need to be recomputed?
|
||||
bool _meshReady { false };
|
||||
|
||||
#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT
|
||||
bool _hasTransitioned{ false };
|
||||
#endif
|
||||
NetworkTexturePointer _xTexture;
|
||||
NetworkTexturePointer _yTexture;
|
||||
NetworkTexturePointer _zTexture;
|
||||
|
@ -217,4 +221,5 @@ private:
|
|||
bool inUserBounds(const PolyVox::SimpleVolume<uint8_t>* vol, PolyVoxEntityItem::PolyVoxSurfaceStyle surfaceStyle,
|
||||
int x, int y, int z);
|
||||
|
||||
|
||||
#endif // hifi_RenderablePolyVoxEntityItem_h
|
||||
|
|
|
@ -20,6 +20,11 @@
|
|||
#include <render-utils/simple_vert.h>
|
||||
#include <render-utils/simple_frag.h>
|
||||
|
||||
//#define SHAPE_ENTITY_USE_FADE_EFFECT
|
||||
#ifdef SHAPE_ENTITY_USE_FADE_EFFECT
|
||||
# include <FadeEffect.h>
|
||||
#endif
|
||||
|
||||
// Sphere entities should fit inside a cube entity of the same size, so a sphere that has dimensions 1x1x1
|
||||
// is a half unit sphere. However, the geometry cache renders a UNIT sphere, so we need to scale down.
|
||||
static const float SPHERE_ENTITY_SCALE = 0.5f;
|
||||
|
@ -73,6 +78,9 @@ void RenderableShapeEntityItem::setUserData(const QString& value) {
|
|||
}
|
||||
|
||||
bool RenderableShapeEntityItem::isTransparent() {
|
||||
#ifdef SHAPE_ENTITY_USE_FADE_EFFECT
|
||||
return getLocalRenderAlpha() < 1.0f;
|
||||
#else
|
||||
if (_procedural && _procedural->isFading()) {
|
||||
float isFading = Interpolate::calculateFadeRatio(_procedural->getFadeStartTime()) < 1.0f;
|
||||
_procedural->setIsFading(isFading);
|
||||
|
@ -80,6 +88,51 @@ bool RenderableShapeEntityItem::isTransparent() {
|
|||
} else {
|
||||
return getLocalRenderAlpha() < 1.0f || EntityItem::isTransparent();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace render {
|
||||
template <> const ItemKey payloadGetKey(const ShapePayload::Pointer& payload) {
|
||||
return payloadGetKey(std::static_pointer_cast<RenderableEntityItemProxy>(payload));
|
||||
}
|
||||
template <> const Item::Bound payloadGetBound(const ShapePayload::Pointer& payload) {
|
||||
return payloadGetBound(std::static_pointer_cast<RenderableEntityItemProxy>(payload));
|
||||
}
|
||||
template <> void payloadRender(const ShapePayload::Pointer& payload, RenderArgs* args) {
|
||||
payloadRender(std::static_pointer_cast<RenderableEntityItemProxy>(payload), args);
|
||||
}
|
||||
template <> uint32_t metaFetchMetaSubItems(const ShapePayload::Pointer& payload, ItemIDs& subItems) {
|
||||
return metaFetchMetaSubItems(std::static_pointer_cast<RenderableEntityItemProxy>(payload), subItems);
|
||||
}
|
||||
|
||||
template <> const ShapeKey shapeGetShapeKey(const ShapePayload::Pointer& payload) {
|
||||
auto shapeKey = ShapeKey::Builder();
|
||||
#ifdef SHAPE_ENTITY_USE_FADE_EFFECT
|
||||
shapeKey.withCustom(GeometryCache::CUSTOM_PIPELINE_NUMBER);
|
||||
#endif
|
||||
auto entity = payload->_entity;
|
||||
if (entity->getLocalRenderAlpha() < 1.f) {
|
||||
shapeKey.withTranslucent();
|
||||
}
|
||||
return shapeKey.build();
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderableShapeEntityItem::addToScene(const EntityItemPointer& self, const render::ScenePointer& scene, render::Transaction& transaction) {
|
||||
_myItem = scene->allocateID();
|
||||
|
||||
auto renderData = std::make_shared<ShapePayload>(self, _myItem);
|
||||
auto renderPayload = std::make_shared<ShapePayload::Payload>(renderData);
|
||||
|
||||
render::Item::Status::Getters statusGetters;
|
||||
makeEntityItemStatusGetters(self, statusGetters);
|
||||
renderPayload->addStatusGetters(statusGetters);
|
||||
|
||||
transaction.resetItem(_myItem, renderPayload);
|
||||
#ifdef SHAPE_ENTITY_USE_FADE_EFFECT
|
||||
transaction.addTransitionToItem(_myItem, render::Transition::ELEMENT_ENTER_DOMAIN);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void RenderableShapeEntityItem::computeShapeInfo(ShapeInfo& info) {
|
||||
|
@ -160,7 +213,9 @@ void RenderableShapeEntityItem::render(RenderArgs* args) {
|
|||
PerformanceTimer perfTimer("RenderableShapeEntityItem::render");
|
||||
//Q_ASSERT(getType() == EntityTypes::Shape);
|
||||
Q_ASSERT(args->_batch);
|
||||
#ifndef SHAPE_ENTITY_USE_FADE_EFFECT
|
||||
checkFading();
|
||||
#endif
|
||||
|
||||
if (!_procedural) {
|
||||
_procedural.reset(new Procedural(getUserData()));
|
||||
|
@ -188,7 +243,9 @@ void RenderableShapeEntityItem::render(RenderArgs* args) {
|
|||
if (_procedural->ready()) {
|
||||
_procedural->prepare(batch, getPosition(), getDimensions(), getOrientation());
|
||||
auto outColor = _procedural->getColor(color);
|
||||
#ifndef SHAPE_ENTITY_USE_FADE_EFFECT
|
||||
outColor.a *= _procedural->isFading() ? Interpolate::calculateFadeRatio(_procedural->getFadeStartTime()) : 1.0f;
|
||||
#endif
|
||||
batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a);
|
||||
if (render::ShapeKey(args->_globalShapeKey).isWireframe()) {
|
||||
DependencyManager::get<GeometryCache>()->renderWireShape(batch, MAPPING[_shape]);
|
||||
|
@ -197,15 +254,46 @@ void RenderableShapeEntityItem::render(RenderArgs* args) {
|
|||
}
|
||||
} else {
|
||||
// FIXME, support instanced multi-shape rendering using multidraw indirect
|
||||
color.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
auto pipeline = color.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline();
|
||||
#ifdef SHAPE_ENTITY_USE_FADE_EFFECT
|
||||
auto shapeKey = render::ShapeKey(args->_itemShapeKey);
|
||||
|
||||
assert(args->_shapePipeline != nullptr);
|
||||
|
||||
if (shapeKey.isFaded()) {
|
||||
auto fadeEffect = DependencyManager::get<FadeEffect>();
|
||||
auto fadeCategory = fadeEffect->getLastCategory();
|
||||
auto fadeThreshold = fadeEffect->getLastThreshold();
|
||||
auto fadeNoiseOffset = fadeEffect->getLastNoiseOffset();
|
||||
auto fadeBaseOffset = fadeEffect->getLastBaseOffset();
|
||||
auto fadeBaseInvSize = fadeEffect->getLastBaseInvSize();
|
||||
|
||||
if (shapeKey.isWireframe()) {
|
||||
geometryCache->renderWireFadeShapeInstance(args, batch, MAPPING[_shape], color, fadeCategory, fadeThreshold,
|
||||
fadeNoiseOffset, fadeBaseOffset, fadeBaseInvSize, args->_shapePipeline);
|
||||
}
|
||||
else {
|
||||
geometryCache->renderSolidFadeShapeInstance(args, batch, MAPPING[_shape], color, fadeCategory, fadeThreshold,
|
||||
fadeNoiseOffset, fadeBaseOffset, fadeBaseInvSize, args->_shapePipeline);
|
||||
}
|
||||
} else {
|
||||
if (shapeKey.isWireframe()) {
|
||||
geometryCache->renderWireShapeInstance(args, batch, MAPPING[_shape], color, args->_shapePipeline);
|
||||
}
|
||||
else {
|
||||
geometryCache->renderSolidShapeInstance(args, batch, MAPPING[_shape], color, args->_shapePipeline);
|
||||
}
|
||||
}
|
||||
#else
|
||||
color.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
|
||||
auto pipeline = color.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline();
|
||||
if (render::ShapeKey(args->_globalShapeKey).isWireframe()) {
|
||||
geometryCache->renderWireShapeInstance(args, batch, MAPPING[_shape], color, pipeline);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
geometryCache->renderSolidShapeInstance(args, batch, MAPPING[_shape], color, pipeline);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static const auto triCount = DependencyManager::get<GeometryCache>()->getShapeTriangleCount(MAPPING[_shape]);
|
||||
|
|
|
@ -14,6 +14,23 @@
|
|||
|
||||
#include "RenderableEntityItem.h"
|
||||
|
||||
class ShapePayload : public RenderableEntityItemProxy {
|
||||
public:
|
||||
ShapePayload(const EntityItemPointer& entity, render::ItemID metaID)
|
||||
: RenderableEntityItemProxy(entity, metaID) {}
|
||||
typedef render::Payload<ShapePayload> Payload;
|
||||
typedef Payload::DataPointer Pointer;
|
||||
|
||||
};
|
||||
|
||||
namespace render {
|
||||
template <> const ItemKey payloadGetKey(const ShapePayload::Pointer& payload);
|
||||
template <> const Item::Bound payloadGetBound(const ShapePayload::Pointer& payload);
|
||||
template <> void payloadRender(const ShapePayload::Pointer& payload, RenderArgs* args);
|
||||
template <> uint32_t metaFetchMetaSubItems(const ShapePayload::Pointer& payload, ItemIDs& subItems);
|
||||
template <> const ShapeKey shapeGetShapeKey(const ShapePayload::Pointer& payload);
|
||||
}
|
||||
|
||||
class RenderableShapeEntityItem : public ShapeEntityItem, private SimplerRenderableEntitySupport {
|
||||
using Pointer = std::shared_ptr<RenderableShapeEntityItem>;
|
||||
static Pointer baseFactory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
@ -23,6 +40,7 @@ public:
|
|||
static EntityItemPointer sphereFactory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
RenderableShapeEntityItem(const EntityItemID& entityItemID) : ShapeEntityItem(entityItemID) {}
|
||||
|
||||
bool addToScene(const EntityItemPointer& self, const render::ScenePointer& scene, render::Transaction& transaction) override;
|
||||
void render(RenderArgs* args) override;
|
||||
void setUserData(const QString& value) override;
|
||||
|
||||
|
|
53
libraries/entities-renderer/src/paintStroke_fade.slf
Normal file
|
@ -0,0 +1,53 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// paintStroke_fade.slf
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Olivier Prat on 19/07/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 DeferredBufferWrite.slh@>
|
||||
|
||||
<@include Fade.slh@>
|
||||
<$declareFadeFragment()$>
|
||||
|
||||
// the albedo texture
|
||||
uniform sampler2D originalTexture;
|
||||
|
||||
// the interpolated normal
|
||||
in vec3 interpolatedNormal;
|
||||
in vec2 varTexcoord;
|
||||
in vec4 varColor;
|
||||
in vec4 _worldPosition;
|
||||
|
||||
struct PolyLineUniforms {
|
||||
vec3 color;
|
||||
};
|
||||
|
||||
uniform polyLineBuffer {
|
||||
PolyLineUniforms polyline;
|
||||
};
|
||||
|
||||
void main(void) {
|
||||
vec3 fadeEmissive;
|
||||
FadeObjectParams fadeParams;
|
||||
|
||||
<$fetchFadeObjectParams(fadeParams)$>
|
||||
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
|
||||
|
||||
vec4 texel = texture(originalTexture, varTexcoord);
|
||||
int frontCondition = 1 -int(gl_FrontFacing) * 2;
|
||||
vec3 color = varColor.rgb;
|
||||
packDeferredFragmentTranslucent(
|
||||
interpolatedNormal * frontCondition,
|
||||
texel.a * varColor.a,
|
||||
polyline.color * texel.rgb + fadeEmissive,
|
||||
vec3(0.01, 0.01, 0.01),
|
||||
10.0);
|
||||
}
|
43
libraries/entities-renderer/src/paintStroke_fade.slv
Normal file
|
@ -0,0 +1,43 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// paintStroke_fade.slv
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Olivier Prat on 19/07/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 gpu/Inputs.slh@>
|
||||
<@include gpu/Color.slh@>
|
||||
<@include gpu/Transform.slh@>
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
// the interpolated normal
|
||||
out vec3 interpolatedNormal;
|
||||
|
||||
//the diffuse texture
|
||||
out vec2 varTexcoord;
|
||||
|
||||
out vec4 varColor;
|
||||
out vec4 _worldPosition;
|
||||
|
||||
void main(void) {
|
||||
|
||||
varTexcoord = inTexCoord0.st;
|
||||
|
||||
// pass along the diffuse color
|
||||
varColor = colorToLinearRGBA(inColor);
|
||||
|
||||
|
||||
// standard transform
|
||||
TransformCamera cam = getTransformCamera();
|
||||
TransformObject obj = getTransformObject();
|
||||
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
|
||||
<$transformModelToEyeDir(cam, obj, inNormal.xyz, interpolatedNormal)$>
|
||||
<$transformModelToWorldPos(obj, inPosition, _worldPosition)$>
|
||||
}
|
64
libraries/entities-renderer/src/polyvox_fade.slf
Normal file
|
@ -0,0 +1,64 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
// polyvox_fade.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Olivier Prat on 2017-06-08
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
<@include model/Material.slh@>
|
||||
<@include DeferredBufferWrite.slh@>
|
||||
|
||||
<@include Fade.slh@>
|
||||
|
||||
in vec3 _normal;
|
||||
in vec4 _position;
|
||||
in vec4 _worldPosition;
|
||||
in vec4 _worldFadePosition;
|
||||
|
||||
uniform sampler2D xMap;
|
||||
uniform sampler2D yMap;
|
||||
uniform sampler2D zMap;
|
||||
uniform vec3 voxelVolumeSize;
|
||||
|
||||
// Declare after all samplers to prevent sampler location mix up with voxel shading (sampler locations are hardcoded in RenderablePolyVoxEntityItem)
|
||||
<$declareFadeFragment()$>
|
||||
|
||||
void main(void) {
|
||||
vec3 emissive;
|
||||
FadeObjectParams fadeParams;
|
||||
|
||||
<$fetchFadeObjectParams(fadeParams)$>
|
||||
applyFade(fadeParams, _worldFadePosition.xyz, emissive);
|
||||
|
||||
vec3 worldNormal = cross(dFdy(_worldPosition.xyz), dFdx(_worldPosition.xyz));
|
||||
worldNormal = normalize(worldNormal);
|
||||
|
||||
float inPositionX = (_worldPosition.x - 0.5) / voxelVolumeSize.x;
|
||||
float inPositionY = (_worldPosition.y - 0.5) / voxelVolumeSize.y;
|
||||
float inPositionZ = (_worldPosition.z - 0.5) / voxelVolumeSize.z;
|
||||
|
||||
vec4 xyDiffuse = texture(xMap, vec2(-inPositionX, -inPositionY));
|
||||
vec4 xzDiffuse = texture(yMap, vec2(-inPositionX, inPositionZ));
|
||||
vec4 yzDiffuse = texture(zMap, vec2(inPositionZ, -inPositionY));
|
||||
|
||||
vec3 xyDiffuseScaled = xyDiffuse.rgb * abs(worldNormal.z);
|
||||
vec3 xzDiffuseScaled = xzDiffuse.rgb * abs(worldNormal.y);
|
||||
vec3 yzDiffuseScaled = yzDiffuse.rgb * abs(worldNormal.x);
|
||||
vec4 diffuse = vec4(xyDiffuseScaled + xzDiffuseScaled + yzDiffuseScaled, 1.0);
|
||||
|
||||
packDeferredFragment(
|
||||
_normal,
|
||||
1.0,
|
||||
vec3(diffuse),
|
||||
DEFAULT_ROUGHNESS,
|
||||
DEFAULT_METALLIC,
|
||||
DEFAULT_EMISSIVE+emissive,
|
||||
DEFAULT_OCCLUSION,
|
||||
DEFAULT_SCATTERING);
|
||||
}
|
33
libraries/entities-renderer/src/polyvox_fade.slv
Normal file
|
@ -0,0 +1,33 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
// polyvox_fade.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Seth Alves on 2015-8-3
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
<@include gpu/Inputs.slh@>
|
||||
|
||||
<@include gpu/Transform.slh@>
|
||||
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
out vec4 _position;
|
||||
out vec4 _worldPosition;
|
||||
out vec4 _worldFadePosition;
|
||||
out vec3 _normal;
|
||||
|
||||
void main(void) {
|
||||
// standard transform
|
||||
TransformCamera cam = getTransformCamera();
|
||||
TransformObject obj = getTransformObject();
|
||||
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$>
|
||||
<$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$>
|
||||
<$transformModelToWorldPos(obj, inPosition, _worldFadePosition)$>
|
||||
_worldPosition = inPosition;
|
||||
}
|
|
@ -455,7 +455,7 @@ void GLBackend::do_glUniform1i(const Batch& batch, size_t paramOffset) {
|
|||
}
|
||||
updatePipeline();
|
||||
|
||||
glUniform1f(
|
||||
glUniform1i(
|
||||
GET_UNIFORM_LOCATION(batch._params[paramOffset + 1]._int),
|
||||
batch._params[paramOffset + 0]._int);
|
||||
(void)CHECK_GL_ERROR();
|
||||
|
|
|
@ -485,9 +485,15 @@ void GLBackend::makeProgramBindings(ShaderObject& shaderObject) {
|
|||
glBindAttribLocation(glprogram, gpu::Stream::TANGENT, "inTangent");
|
||||
}
|
||||
|
||||
loc = glGetAttribLocation(glprogram, "inTexCoord1");
|
||||
if (loc >= 0 && loc != gpu::Stream::TEXCOORD1) {
|
||||
glBindAttribLocation(glprogram, gpu::Stream::TEXCOORD1, "inTexCoord1");
|
||||
char attribName[] = "inTexCoordn";
|
||||
for (auto i = 0; i < 4; i++) {
|
||||
auto streamId = gpu::Stream::TEXCOORD1 + i;
|
||||
|
||||
attribName[strlen(attribName) - 1] = '1' + i;
|
||||
loc = glGetAttribLocation(glprogram, attribName);
|
||||
if (loc >= 0 && loc != streamId) {
|
||||
glBindAttribLocation(glprogram, streamId, attribName);
|
||||
}
|
||||
}
|
||||
|
||||
loc = glGetAttribLocation(glprogram, "inSkinClusterIndex");
|
||||
|
|
|
@ -18,4 +18,7 @@ layout(location = 4) in vec4 inTangent;
|
|||
layout(location = 5) in ivec4 inSkinClusterIndex;
|
||||
layout(location = 6) in vec4 inSkinClusterWeight;
|
||||
layout(location = 7) in vec4 inTexCoord1;
|
||||
layout(location = 8) in vec4 inTexCoord2;
|
||||
layout(location = 9) in vec4 inTexCoord3;
|
||||
layout(location = 10) in vec4 inTexCoord4;
|
||||
<@endif@>
|
||||
|
|
|
@ -36,8 +36,14 @@ const ElementArray& getDefaultElements() {
|
|||
//SKIN_CLUSTER_WEIGHT = 6,
|
||||
Element::VEC4F_XYZW,
|
||||
//TEXCOORD1 = 7,
|
||||
Element::VEC2F_UV
|
||||
}};
|
||||
Element::VEC2F_UV,
|
||||
//TEXCOORD2 = 7,
|
||||
Element::VEC4F_XYZW,
|
||||
//TEXCOORD3 = 7,
|
||||
Element::VEC4F_XYZW,
|
||||
//TEXCOORD4 = 7,
|
||||
Element::VEC4F_XYZW
|
||||
}};
|
||||
return defaultElements;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,8 +38,11 @@ public:
|
|||
SKIN_CLUSTER_INDEX = 5,
|
||||
SKIN_CLUSTER_WEIGHT = 6,
|
||||
TEXCOORD1 = 7,
|
||||
NUM_INPUT_SLOTS = TEXCOORD1 + 1,
|
||||
TEXCOORD2 = 8,
|
||||
TEXCOORD3 = 9,
|
||||
TEXCOORD4 = 10,
|
||||
|
||||
NUM_INPUT_SLOTS,
|
||||
|
||||
DRAW_CALL_INFO = 15, // Reserve last input slot for draw call infos
|
||||
};
|
||||
|
|
169
libraries/render-utils/src/Fade.slh
Normal file
|
@ -0,0 +1,169 @@
|
|||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// Created by Olivier Prat on 04/12/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
|
||||
//
|
||||
<@if not FADE_SLH@>
|
||||
<@def FADE_SLH@>
|
||||
|
||||
<@func declareFadeFragmentCommon()@>
|
||||
|
||||
|
||||
#define CATEGORY_COUNT 5
|
||||
|
||||
<@include Fade_shared.slh@>
|
||||
|
||||
layout(std140) uniform fadeParametersBuffer {
|
||||
FadeParameters fadeParameters[CATEGORY_COUNT];
|
||||
};
|
||||
uniform sampler2D fadeMaskMap;
|
||||
|
||||
struct FadeObjectParams {
|
||||
int category;
|
||||
float threshold;
|
||||
vec3 noiseOffset;
|
||||
vec3 baseOffset;
|
||||
vec3 baseInvSize;
|
||||
};
|
||||
|
||||
vec2 hash2D(vec3 position) {
|
||||
return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;
|
||||
}
|
||||
|
||||
float noise3D(vec3 position) {
|
||||
float n = textureLod(fadeMaskMap, hash2D(position), 0).r;
|
||||
return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture
|
||||
}
|
||||
|
||||
float evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {
|
||||
// Do tri-linear interpolation
|
||||
vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;
|
||||
vec3 noisePositionFloored = floor(noisePosition);
|
||||
vec3 noisePositionFraction = fract(noisePosition);
|
||||
|
||||
noisePositionFraction = noisePositionFraction*noisePositionFraction*(3 - 2*noisePositionFraction);
|
||||
|
||||
float noiseLowXLowYLowZ = noise3D(noisePositionFloored);
|
||||
float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));
|
||||
float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));
|
||||
float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));
|
||||
float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));
|
||||
float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));
|
||||
float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));
|
||||
float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));
|
||||
vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);
|
||||
vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);
|
||||
vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);
|
||||
vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);
|
||||
|
||||
float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);
|
||||
noise -= 0.5; // Center on value 0
|
||||
return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;
|
||||
}
|
||||
|
||||
float evalFadeBaseGradient(FadeObjectParams params, vec3 position) {
|
||||
float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);
|
||||
gradient = gradient-0.5; // Center on value 0.5
|
||||
gradient *= fadeParameters[params.category]._baseLevel;
|
||||
return gradient;
|
||||
}
|
||||
|
||||
float evalFadeGradient(FadeObjectParams params, vec3 position) {
|
||||
float baseGradient = evalFadeBaseGradient(params, position);
|
||||
float noiseGradient = evalFadeNoiseGradient(params, position);
|
||||
float gradient = noiseGradient+baseGradient+0.5;
|
||||
|
||||
return gradient;
|
||||
}
|
||||
|
||||
float evalFadeAlpha(FadeObjectParams params, vec3 position) {
|
||||
return evalFadeGradient(params, position)-params.threshold;
|
||||
}
|
||||
|
||||
void applyFadeClip(FadeObjectParams params, vec3 position) {
|
||||
if (evalFadeAlpha(params, position) < 0) {
|
||||
discard;
|
||||
}
|
||||
}
|
||||
|
||||
void applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {
|
||||
float alpha = evalFadeAlpha(params, position);
|
||||
if (fadeParameters[params.category]._isInverted!=0) {
|
||||
alpha = -alpha;
|
||||
}
|
||||
|
||||
if (alpha < 0) {
|
||||
discard;
|
||||
}
|
||||
|
||||
float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;
|
||||
float edgeAlpha = 1.0-clamp(edgeMask, 0, 1);
|
||||
|
||||
edgeMask = step(edgeMask, 1.f);
|
||||
edgeAlpha *= edgeAlpha; // Square to have a nice ease out
|
||||
vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);
|
||||
emissive = color.rgb * edgeMask * color.a;
|
||||
}
|
||||
|
||||
<@endfunc@>
|
||||
|
||||
<@func declareFadeFragmentUniform()@>
|
||||
|
||||
uniform int fadeCategory;
|
||||
uniform vec3 fadeNoiseOffset;
|
||||
uniform vec3 fadeBaseOffset;
|
||||
uniform vec3 fadeBaseInvSize;
|
||||
uniform float fadeThreshold;
|
||||
|
||||
<@endfunc@>
|
||||
|
||||
<@func fetchFadeObjectParams(fadeParams)@>
|
||||
<$fadeParams$>.category = fadeCategory;
|
||||
<$fadeParams$>.threshold = fadeThreshold;
|
||||
<$fadeParams$>.noiseOffset = fadeNoiseOffset;
|
||||
<$fadeParams$>.baseOffset = fadeBaseOffset;
|
||||
<$fadeParams$>.baseInvSize = fadeBaseInvSize;
|
||||
<@endfunc@>
|
||||
|
||||
<@func declareFadeFragmentVertexInput()@>
|
||||
|
||||
in vec4 _fadeData1;
|
||||
in vec4 _fadeData2;
|
||||
in vec4 _fadeData3;
|
||||
|
||||
<@endfunc@>
|
||||
|
||||
<@func fetchFadeObjectParamsInstanced(fadeParams)@>
|
||||
<$fadeParams$>.category = int(_fadeData1.w);
|
||||
<$fadeParams$>.threshold = _fadeData2.w;
|
||||
<$fadeParams$>.noiseOffset = _fadeData1.xyz;
|
||||
<$fadeParams$>.baseOffset = _fadeData2.xyz;
|
||||
<$fadeParams$>.baseInvSize = _fadeData3.xyz;
|
||||
<@endfunc@>
|
||||
|
||||
<@func declareFadeFragment()@>
|
||||
<$declareFadeFragmentCommon()$>
|
||||
<$declareFadeFragmentUniform()$>
|
||||
<@endfunc@>
|
||||
|
||||
<@func declareFadeFragmentInstanced()@>
|
||||
<$declareFadeFragmentCommon()$>
|
||||
<$declareFadeFragmentVertexInput()$>
|
||||
<@endfunc@>
|
||||
|
||||
<@func declareFadeVertexInstanced()@>
|
||||
out vec4 _fadeData1;
|
||||
out vec4 _fadeData2;
|
||||
out vec4 _fadeData3;
|
||||
<@endfunc@>
|
||||
|
||||
<@func passThroughFadeObjectParams()@>
|
||||
_fadeData1 = inTexCoord2;
|
||||
_fadeData2 = inTexCoord3;
|
||||
_fadeData3 = inTexCoord4;
|
||||
<@endfunc@>
|
||||
|
||||
<@endif@>
|
104
libraries/render-utils/src/FadeEffect.cpp
Normal file
|
@ -0,0 +1,104 @@
|
|||
//
|
||||
// FadeEffect.cpp
|
||||
|
||||
// Created by Olivier Prat on 17/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 "FadeEffect.h"
|
||||
#include "FadeEffectJobs.h"
|
||||
#include "TextureCache.h"
|
||||
|
||||
#include "render/TransitionStage.h"
|
||||
|
||||
#include <PathUtils.h>
|
||||
|
||||
FadeEffect::FadeEffect() {
|
||||
auto texturePath = PathUtils::resourcesPath() + "images/fadeMask.png";
|
||||
_maskMap = DependencyManager::get<TextureCache>()->getImageTexture(texturePath, image::TextureUsage::STRICT_TEXTURE);
|
||||
}
|
||||
|
||||
void FadeEffect::build(render::Task::TaskConcept& task, const task::Varying& editableItems) {
|
||||
auto editedFadeCategory = task.addJob<FadeJob>("Fade");
|
||||
auto& fadeJob = task._jobs.back();
|
||||
_configurations = fadeJob.get<FadeJob>().getConfigurationBuffer();
|
||||
|
||||
const auto fadeEditInput = FadeEditJob::Input(editableItems, editedFadeCategory).asVarying();
|
||||
task.addJob<FadeEditJob>("FadeEdit", fadeEditInput);
|
||||
}
|
||||
|
||||
render::ShapePipeline::BatchSetter FadeEffect::getBatchSetter() const {
|
||||
return [this](const render::ShapePipeline& shapePipeline, gpu::Batch& batch, render::Args*) {
|
||||
auto program = shapePipeline.pipeline->getProgram();
|
||||
auto maskMapLocation = program->getTextures().findLocation("fadeMaskMap");
|
||||
auto bufferLocation = program->getUniformBuffers().findLocation("fadeParametersBuffer");
|
||||
batch.setResourceTexture(maskMapLocation, _maskMap);
|
||||
batch.setUniformBuffer(bufferLocation, _configurations);
|
||||
};
|
||||
}
|
||||
|
||||
render::ShapePipeline::ItemSetter FadeEffect::getItemUniformSetter() const {
|
||||
return [](const render::ShapePipeline& shapePipeline, render::Args* args, const render::Item& item) {
|
||||
if (!render::TransitionStage::isIndexInvalid(item.getTransitionId())) {
|
||||
auto scene = args->_scene;
|
||||
auto batch = args->_batch;
|
||||
auto transitionStage = scene->getStage<render::TransitionStage>(render::TransitionStage::getName());
|
||||
auto& transitionState = transitionStage->getTransition(item.getTransitionId());
|
||||
auto program = shapePipeline.pipeline->getProgram();
|
||||
auto& uniforms = program->getUniforms();
|
||||
auto fadeNoiseOffsetLocation = uniforms.findLocation("fadeNoiseOffset");
|
||||
auto fadeBaseOffsetLocation = uniforms.findLocation("fadeBaseOffset");
|
||||
auto fadeBaseInvSizeLocation = uniforms.findLocation("fadeBaseInvSize");
|
||||
auto fadeThresholdLocation = uniforms.findLocation("fadeThreshold");
|
||||
auto fadeCategoryLocation = uniforms.findLocation("fadeCategory");
|
||||
|
||||
if (fadeNoiseOffsetLocation >= 0 || fadeBaseInvSizeLocation >= 0 || fadeBaseOffsetLocation >= 0 || fadeThresholdLocation >= 0 || fadeCategoryLocation >= 0) {
|
||||
const auto fadeCategory = FadeJob::transitionToCategory[transitionState.eventType];
|
||||
|
||||
batch->_glUniform1i(fadeCategoryLocation, fadeCategory);
|
||||
batch->_glUniform1f(fadeThresholdLocation, transitionState.threshold);
|
||||
batch->_glUniform3f(fadeNoiseOffsetLocation, transitionState.noiseOffset.x, transitionState.noiseOffset.y, transitionState.noiseOffset.z);
|
||||
batch->_glUniform3f(fadeBaseOffsetLocation, transitionState.baseOffset.x, transitionState.baseOffset.y, transitionState.baseOffset.z);
|
||||
batch->_glUniform3f(fadeBaseInvSizeLocation, transitionState.baseInvSize.x, transitionState.baseInvSize.y, transitionState.baseInvSize.z);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
render::ShapePipeline::ItemSetter FadeEffect::getItemStoredSetter() {
|
||||
return [this](const render::ShapePipeline& shapePipeline, render::Args* args, const render::Item& item) {
|
||||
if (!render::TransitionStage::isIndexInvalid(item.getTransitionId())) {
|
||||
auto scene = args->_scene;
|
||||
auto transitionStage = scene->getStage<render::TransitionStage>(render::TransitionStage::getName());
|
||||
auto& transitionState = transitionStage->getTransition(item.getTransitionId());
|
||||
const auto fadeCategory = FadeJob::transitionToCategory[transitionState.eventType];
|
||||
|
||||
_lastCategory = fadeCategory;
|
||||
_lastThreshold = transitionState.threshold;
|
||||
_lastNoiseOffset = transitionState.noiseOffset;
|
||||
_lastBaseOffset = transitionState.baseOffset;
|
||||
_lastBaseInvSize = transitionState.baseInvSize;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void FadeEffect::packToAttributes(const int category, const float threshold, const glm::vec3& noiseOffset,
|
||||
const glm::vec3& baseOffset, const glm::vec3& baseInvSize,
|
||||
glm::vec4& packedData1, glm::vec4& packedData2, glm::vec4& packedData3) {
|
||||
packedData1.x = noiseOffset.x;
|
||||
packedData1.y = noiseOffset.y;
|
||||
packedData1.z = noiseOffset.z;
|
||||
packedData1.w = (float)(category+0.1f); // GLSL hack so that casting back from float to int in fragment shader returns the correct value.
|
||||
|
||||
packedData2.x = baseOffset.x;
|
||||
packedData2.y = baseOffset.y;
|
||||
packedData2.z = baseOffset.z;
|
||||
packedData2.w = threshold;
|
||||
|
||||
packedData3.x = baseInvSize.x;
|
||||
packedData3.y = baseInvSize.y;
|
||||
packedData3.z = baseInvSize.z;
|
||||
packedData3.w = 0.f;
|
||||
}
|
54
libraries/render-utils/src/FadeEffect.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
//
|
||||
// FadeEffect.h
|
||||
|
||||
// Created by Olivier Prat on 17/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
|
||||
//
|
||||
|
||||
#ifndef hifi_render_utils_FadeEffect_h
|
||||
#define hifi_render_utils_FadeEffect_h
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include <render/Engine.h>
|
||||
|
||||
class FadeEffect : public Dependency {
|
||||
SINGLETON_DEPENDENCY;
|
||||
|
||||
public:
|
||||
|
||||
void build(render::Task::TaskConcept& task, const task::Varying& editableItems);
|
||||
|
||||
render::ShapePipeline::BatchSetter getBatchSetter() const;
|
||||
render::ShapePipeline::ItemSetter getItemUniformSetter() const;
|
||||
render::ShapePipeline::ItemSetter getItemStoredSetter();
|
||||
|
||||
int getLastCategory() const { return _lastCategory; }
|
||||
float getLastThreshold() const { return _lastThreshold; }
|
||||
const glm::vec3& getLastNoiseOffset() const { return _lastNoiseOffset; }
|
||||
const glm::vec3& getLastBaseOffset() const { return _lastBaseOffset; }
|
||||
const glm::vec3& getLastBaseInvSize() const { return _lastBaseInvSize; }
|
||||
|
||||
static void packToAttributes(const int category, const float threshold, const glm::vec3& noiseOffset,
|
||||
const glm::vec3& baseOffset, const glm::vec3& baseInvSize,
|
||||
glm::vec4& packedData1, glm::vec4& packedData2, glm::vec4& packedData3);
|
||||
|
||||
private:
|
||||
|
||||
gpu::BufferView _configurations;
|
||||
gpu::TexturePointer _maskMap;
|
||||
|
||||
// The last fade set through the stored item setter
|
||||
int _lastCategory { 0 };
|
||||
float _lastThreshold { 0.f };
|
||||
glm::vec3 _lastNoiseOffset { 0.f, 0.f, 0.f };
|
||||
glm::vec3 _lastBaseOffset { 0.f, 0.f, 0.f };
|
||||
glm::vec3 _lastBaseInvSize { 1.f, 1.f, 1.f };
|
||||
|
||||
explicit FadeEffect();
|
||||
virtual ~FadeEffect() { }
|
||||
|
||||
};
|
||||
#endif // hifi_render_utils_FadeEffect_h
|
733
libraries/render-utils/src/FadeEffectJobs.cpp
Normal file
|
@ -0,0 +1,733 @@
|
|||
//
|
||||
// FadeEffectJobs.cpp
|
||||
|
||||
// Created by Olivier Prat on 07/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 "FadeEffectJobs.h"
|
||||
#include "render/Logging.h"
|
||||
#include "render/TransitionStage.h"
|
||||
|
||||
#include <NumericalConstants.h>
|
||||
#include <Interpolate.h>
|
||||
#include <gpu/Context.h>
|
||||
|
||||
#include <QJsonArray>
|
||||
|
||||
#include <PathUtils.h>
|
||||
|
||||
#define FADE_MIN_SCALE 0.001
|
||||
#define FADE_MAX_SCALE 10000.0
|
||||
#define FADE_MAX_SPEED 50.f
|
||||
|
||||
inline float parameterToValuePow(float parameter, const double minValue, const double maxOverMinValue) {
|
||||
return (float)(minValue * pow(maxOverMinValue, double(parameter)));
|
||||
}
|
||||
|
||||
inline float valueToParameterPow(float value, const double minValue, const double maxOverMinValue) {
|
||||
return (float)(log(double(value) / minValue) / log(maxOverMinValue));
|
||||
}
|
||||
|
||||
void FadeEditJob::configure(const Config& config) {
|
||||
_isEditEnabled = config.editFade;
|
||||
}
|
||||
|
||||
void FadeEditJob::run(const render::RenderContextPointer& renderContext, const FadeEditJob::Input& inputs) {
|
||||
auto scene = renderContext->_scene;
|
||||
|
||||
if (_isEditEnabled) {
|
||||
float minIsectDistance = std::numeric_limits<float>::max();
|
||||
auto& itemBounds = inputs.get0();
|
||||
auto editedItem = findNearestItem(renderContext, itemBounds, minIsectDistance);
|
||||
render::Transaction transaction;
|
||||
bool hasTransaction{ false };
|
||||
|
||||
if (editedItem != _editedItem && render::Item::isValidID(_editedItem)) {
|
||||
// Remove transition from previously edited item as we've changed edited item
|
||||
hasTransaction = true;
|
||||
transaction.removeTransitionFromItem(_editedItem);
|
||||
}
|
||||
_editedItem = editedItem;
|
||||
|
||||
if (render::Item::isValidID(_editedItem)) {
|
||||
static const render::Transition::Type categoryToTransition[FADE_CATEGORY_COUNT] = {
|
||||
render::Transition::ELEMENT_ENTER_DOMAIN,
|
||||
render::Transition::BUBBLE_ISECT_OWNER,
|
||||
render::Transition::BUBBLE_ISECT_TRESPASSER,
|
||||
render::Transition::USER_ENTER_DOMAIN,
|
||||
render::Transition::AVATAR_CHANGE
|
||||
};
|
||||
|
||||
auto transitionType = categoryToTransition[inputs.get1()];
|
||||
|
||||
transaction.queryTransitionOnItem(_editedItem, [transitionType, scene](render::ItemID id, const render::Transition* transition) {
|
||||
if (transition == nullptr || transition->isFinished || transition->eventType!=transitionType) {
|
||||
// Relaunch transition
|
||||
render::Transaction transaction;
|
||||
transaction.addTransitionToItem(id, transitionType);
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
});
|
||||
hasTransaction = true;
|
||||
}
|
||||
|
||||
if (hasTransaction) {
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
}
|
||||
else if (render::Item::isValidID(_editedItem)) {
|
||||
// Remove transition from previously edited item as we've disabled fade edition
|
||||
render::Transaction transaction;
|
||||
transaction.removeTransitionFromItem(_editedItem);
|
||||
scene->enqueueTransaction(transaction);
|
||||
_editedItem = render::Item::INVALID_ITEM_ID;
|
||||
}
|
||||
}
|
||||
|
||||
render::ItemID FadeEditJob::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::ItemID nearestItem = render::Item::INVALID_ITEM_ID;
|
||||
const float minDistance = 1.f;
|
||||
const float maxDistance = 50.f;
|
||||
|
||||
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);
|
||||
if (item.getKey().isWorldSpace() && isectDistance>minDistance && isectDistance < minIsectDistance && isectDistance<maxDistance) {
|
||||
nearestItem = itemBound.id;
|
||||
minIsectDistance = isectDistance;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nearestItem;
|
||||
}
|
||||
|
||||
FadeConfig::FadeConfig()
|
||||
{
|
||||
events[FADE_ELEMENT_ENTER_LEAVE_DOMAIN].noiseSize = glm::vec3{ 0.75f, 0.75f, 0.75f };
|
||||
events[FADE_ELEMENT_ENTER_LEAVE_DOMAIN].noiseLevel = 1.f;
|
||||
events[FADE_ELEMENT_ENTER_LEAVE_DOMAIN].noiseSpeed = glm::vec3{ 0.0f, 0.0f, 0.0f };
|
||||
events[FADE_ELEMENT_ENTER_LEAVE_DOMAIN].timing = FadeConfig::LINEAR;
|
||||
events[FADE_ELEMENT_ENTER_LEAVE_DOMAIN].baseSize = glm::vec3{ 1.0f, 1.0f, 1.0f };
|
||||
events[FADE_ELEMENT_ENTER_LEAVE_DOMAIN].baseLevel = 0.f;
|
||||
events[FADE_ELEMENT_ENTER_LEAVE_DOMAIN].isInverted = false;
|
||||
events[FADE_ELEMENT_ENTER_LEAVE_DOMAIN].duration = 4.f;
|
||||
events[FADE_ELEMENT_ENTER_LEAVE_DOMAIN].edgeWidth = 0.1f;
|
||||
events[FADE_ELEMENT_ENTER_LEAVE_DOMAIN].edgeInnerColor = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.0f };
|
||||
events[FADE_ELEMENT_ENTER_LEAVE_DOMAIN].edgeOuterColor = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 1.0f };
|
||||
|
||||
events[FADE_BUBBLE_ISECT_OWNER].noiseSize = glm::vec3{ 1.5f, 1.0f / 25.f, 0.5f };
|
||||
events[FADE_BUBBLE_ISECT_OWNER].noiseLevel = 0.37f;
|
||||
events[FADE_BUBBLE_ISECT_OWNER].noiseSpeed = glm::vec3{ 1.0f, 0.2f, 1.0f };
|
||||
events[FADE_BUBBLE_ISECT_OWNER].timing = FadeConfig::LINEAR;
|
||||
events[FADE_BUBBLE_ISECT_OWNER].baseSize = glm::vec3{ 2.0f, 2.0f, 2.0f };
|
||||
events[FADE_BUBBLE_ISECT_OWNER].baseLevel = 1.f;
|
||||
events[FADE_BUBBLE_ISECT_OWNER].isInverted = false;
|
||||
events[FADE_BUBBLE_ISECT_OWNER].duration = 4.f;
|
||||
events[FADE_BUBBLE_ISECT_OWNER].edgeWidth = 0.02f;
|
||||
events[FADE_BUBBLE_ISECT_OWNER].edgeInnerColor = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f };
|
||||
events[FADE_BUBBLE_ISECT_OWNER].edgeOuterColor = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 2.0f };
|
||||
|
||||
events[FADE_BUBBLE_ISECT_TRESPASSER].noiseSize = glm::vec3{ 0.5f, 1.0f / 25.f, 0.5f };
|
||||
events[FADE_BUBBLE_ISECT_TRESPASSER].noiseLevel = 1.f;
|
||||
events[FADE_BUBBLE_ISECT_TRESPASSER].noiseSpeed = glm::vec3{ 1.0f, -5.f, 1.0f };
|
||||
events[FADE_BUBBLE_ISECT_TRESPASSER].timing = FadeConfig::LINEAR;
|
||||
events[FADE_BUBBLE_ISECT_TRESPASSER].baseSize = glm::vec3{ 2.0f, 2.0f, 2.0f };
|
||||
events[FADE_BUBBLE_ISECT_TRESPASSER].baseLevel = 0.f;
|
||||
events[FADE_BUBBLE_ISECT_TRESPASSER].isInverted = false;
|
||||
events[FADE_BUBBLE_ISECT_TRESPASSER].duration = 4.f;
|
||||
events[FADE_BUBBLE_ISECT_TRESPASSER].edgeWidth = 0.025f;
|
||||
events[FADE_BUBBLE_ISECT_TRESPASSER].edgeInnerColor = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f };
|
||||
events[FADE_BUBBLE_ISECT_TRESPASSER].edgeOuterColor = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 2.0f };
|
||||
|
||||
events[FADE_USER_ENTER_LEAVE_DOMAIN].noiseSize = glm::vec3{ 10.f, 0.01f, 10.0f };
|
||||
events[FADE_USER_ENTER_LEAVE_DOMAIN].noiseLevel = 0.3f;
|
||||
events[FADE_USER_ENTER_LEAVE_DOMAIN].noiseSpeed = glm::vec3{ 0.0f, -5.0f, 0.0f };
|
||||
events[FADE_USER_ENTER_LEAVE_DOMAIN].timing = FadeConfig::LINEAR;
|
||||
events[FADE_USER_ENTER_LEAVE_DOMAIN].baseSize = glm::vec3{ 10000.f, 1.0f, 10000.0f };
|
||||
events[FADE_USER_ENTER_LEAVE_DOMAIN].baseLevel = 1.f;
|
||||
events[FADE_USER_ENTER_LEAVE_DOMAIN].isInverted = true;
|
||||
events[FADE_USER_ENTER_LEAVE_DOMAIN].duration = 2.f;
|
||||
events[FADE_USER_ENTER_LEAVE_DOMAIN].edgeWidth = 0.229f;
|
||||
events[FADE_USER_ENTER_LEAVE_DOMAIN].edgeInnerColor = glm::vec4{ 1.f, 0.63f, 0.13f, 0.5f };
|
||||
events[FADE_USER_ENTER_LEAVE_DOMAIN].edgeOuterColor = glm::vec4{ 1.f, 1.f, 1.f, 1.0f };
|
||||
|
||||
events[FADE_AVATAR_CHANGE].noiseSize = glm::vec3{ 0.4f, 0.4f, 0.4f };
|
||||
events[FADE_AVATAR_CHANGE].noiseLevel = 1.f;
|
||||
events[FADE_AVATAR_CHANGE].noiseSpeed = glm::vec3{ 0.0f, 0.0f, 0.0f };
|
||||
events[FADE_AVATAR_CHANGE].timing = FadeConfig::LINEAR;
|
||||
events[FADE_AVATAR_CHANGE].baseSize = glm::vec3{ 0.4f, 0.4f, 0.4f };
|
||||
events[FADE_AVATAR_CHANGE].baseLevel = 1.f;
|
||||
events[FADE_AVATAR_CHANGE].isInverted = false;
|
||||
events[FADE_AVATAR_CHANGE].duration = 3.f;
|
||||
events[FADE_AVATAR_CHANGE].edgeWidth = 0.05f;
|
||||
events[FADE_AVATAR_CHANGE].edgeInnerColor = glm::vec4{ 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
events[FADE_AVATAR_CHANGE].edgeOuterColor = glm::vec4{ 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
}
|
||||
|
||||
void FadeConfig::setEditedCategory(int value) {
|
||||
assert(value < FADE_CATEGORY_COUNT);
|
||||
editedCategory = std::min<int>(FADE_CATEGORY_COUNT, value);
|
||||
emit dirtyCategory();
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
void FadeConfig::setDuration(float value) {
|
||||
events[editedCategory].duration = value;
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
float FadeConfig::getDuration() const {
|
||||
return events[editedCategory].duration;
|
||||
}
|
||||
|
||||
void FadeConfig::setBaseSizeX(float value) {
|
||||
events[editedCategory].baseSize.x = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE/ FADE_MIN_SCALE);
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
float FadeConfig::getBaseSizeX() const {
|
||||
return valueToParameterPow(events[editedCategory].baseSize.x, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
||||
}
|
||||
|
||||
void FadeConfig::setBaseSizeY(float value) {
|
||||
events[editedCategory].baseSize.y = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
float FadeConfig::getBaseSizeY() const {
|
||||
return valueToParameterPow(events[editedCategory].baseSize.y, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
||||
}
|
||||
|
||||
void FadeConfig::setBaseSizeZ(float value) {
|
||||
events[editedCategory].baseSize.z = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
float FadeConfig::getBaseSizeZ() const {
|
||||
return valueToParameterPow(events[editedCategory].baseSize.z, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
||||
}
|
||||
|
||||
void FadeConfig::setBaseLevel(float value) {
|
||||
events[editedCategory].baseLevel = value;
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
void FadeConfig::setInverted(bool value) {
|
||||
events[editedCategory].isInverted = value;
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
bool FadeConfig::isInverted() const {
|
||||
return events[editedCategory].isInverted;
|
||||
}
|
||||
|
||||
void FadeConfig::setNoiseSizeX(float value) {
|
||||
events[editedCategory].noiseSize.x = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
float FadeConfig::getNoiseSizeX() const {
|
||||
return valueToParameterPow(events[editedCategory].noiseSize.x, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
||||
}
|
||||
|
||||
void FadeConfig::setNoiseSizeY(float value) {
|
||||
events[editedCategory].noiseSize.y = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
float FadeConfig::getNoiseSizeY() const {
|
||||
return valueToParameterPow(events[editedCategory].noiseSize.y, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
||||
}
|
||||
|
||||
void FadeConfig::setNoiseSizeZ(float value) {
|
||||
events[editedCategory].noiseSize.z = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
float FadeConfig::getNoiseSizeZ() const {
|
||||
return valueToParameterPow(events[editedCategory].noiseSize.z, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
||||
}
|
||||
|
||||
void FadeConfig::setNoiseLevel(float value) {
|
||||
events[editedCategory].noiseLevel = value;
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
void FadeConfig::setNoiseSpeedX(float value) {
|
||||
events[editedCategory].noiseSpeed.x = powf(value, 3.f)*FADE_MAX_SPEED;
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
float FadeConfig::getNoiseSpeedX() const {
|
||||
return powf(events[editedCategory].noiseSpeed.x / FADE_MAX_SPEED, 1.f / 3.f);
|
||||
}
|
||||
|
||||
void FadeConfig::setNoiseSpeedY(float value) {
|
||||
events[editedCategory].noiseSpeed.y = powf(value, 3.f)*FADE_MAX_SPEED;
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
float FadeConfig::getNoiseSpeedY() const {
|
||||
return powf(events[editedCategory].noiseSpeed.y / FADE_MAX_SPEED, 1.f / 3.f);
|
||||
}
|
||||
|
||||
void FadeConfig::setNoiseSpeedZ(float value) {
|
||||
events[editedCategory].noiseSpeed.z = powf(value, 3.f)*FADE_MAX_SPEED;
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
float FadeConfig::getNoiseSpeedZ() const {
|
||||
return powf(events[editedCategory].noiseSpeed.z / FADE_MAX_SPEED, 1.f / 3.f);
|
||||
}
|
||||
|
||||
void FadeConfig::setEdgeWidth(float value) {
|
||||
events[editedCategory].edgeWidth = value * value;
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
float FadeConfig::getEdgeWidth() const {
|
||||
return sqrtf(events[editedCategory].edgeWidth);
|
||||
}
|
||||
|
||||
void FadeConfig::setEdgeInnerColorR(float value) {
|
||||
events[editedCategory].edgeInnerColor.r = value;
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
void FadeConfig::setEdgeInnerColorG(float value) {
|
||||
events[editedCategory].edgeInnerColor.g = value;
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
void FadeConfig::setEdgeInnerColorB(float value) {
|
||||
events[editedCategory].edgeInnerColor.b = value;
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
void FadeConfig::setEdgeInnerIntensity(float value) {
|
||||
events[editedCategory].edgeInnerColor.a = value;
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
void FadeConfig::setEdgeOuterColorR(float value) {
|
||||
events[editedCategory].edgeOuterColor.r = value;
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
void FadeConfig::setEdgeOuterColorG(float value) {
|
||||
events[editedCategory].edgeOuterColor.g = value;
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
void FadeConfig::setEdgeOuterColorB(float value) {
|
||||
events[editedCategory].edgeOuterColor.b = value;
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
void FadeConfig::setEdgeOuterIntensity(float value) {
|
||||
events[editedCategory].edgeOuterColor.a = value;
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
void FadeConfig::setTiming(int value) {
|
||||
assert(value < TIMING_COUNT);
|
||||
events[editedCategory].timing = value;
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
QString FadeConfig::eventNames[FADE_CATEGORY_COUNT] = {
|
||||
"element_enter_leave_domain",
|
||||
"bubble_isect_owner",
|
||||
"bubble_isect_trespasser",
|
||||
"user_enter_leave_domain",
|
||||
"avatar_change",
|
||||
};
|
||||
|
||||
void FadeConfig::save() const {
|
||||
assert(editedCategory < FADE_CATEGORY_COUNT);
|
||||
QJsonObject lProperties;
|
||||
const QString configFile = "config/" + eventNames[editedCategory] + ".json";
|
||||
QUrl path(PathUtils::resourcesPath() + configFile);
|
||||
QFile file(path.toString());
|
||||
if (!file.open(QFile::WriteOnly | QFile::Text)) {
|
||||
qWarning() << "Fade event configuration file " << path << " cannot be opened";
|
||||
}
|
||||
else {
|
||||
const auto& event = events[editedCategory];
|
||||
|
||||
lProperties["edgeInnerColor"] = QJsonArray{ event.edgeInnerColor.r, event.edgeInnerColor.g, event.edgeInnerColor.b, event.edgeInnerColor.a };
|
||||
lProperties["edgeOuterColor"] = QJsonArray{ event.edgeOuterColor.r, event.edgeOuterColor.g, event.edgeOuterColor.b, event.edgeOuterColor.a };
|
||||
lProperties["noiseSize"] = QJsonArray{ event.noiseSize.x, event.noiseSize.y, event.noiseSize.z };
|
||||
lProperties["noiseSpeed"] = QJsonArray{ event.noiseSpeed.x, event.noiseSpeed.y, event.noiseSpeed.z };
|
||||
lProperties["baseSize"] = QJsonArray{ event.baseSize.x, event.baseSize.y, event.baseSize.z };
|
||||
lProperties["noiseLevel"] = event.noiseLevel;
|
||||
lProperties["baseLevel"] = event.baseLevel;
|
||||
lProperties["duration"] = event.duration;
|
||||
lProperties["edgeWidth"] = event.edgeWidth;
|
||||
lProperties["timing"] = event.timing;
|
||||
lProperties["isInverted"] = event.isInverted;
|
||||
|
||||
file.write( QJsonDocument(lProperties).toJson() );
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
void FadeConfig::load() {
|
||||
const QString configFile = "config/" + eventNames[editedCategory] + ".json";
|
||||
|
||||
QUrl path(PathUtils::resourcesPath() + configFile);
|
||||
QFile file(path.toString());
|
||||
if (!file.exists()) {
|
||||
qWarning() << "Fade event configuration file " << path << " does not exist";
|
||||
}
|
||||
else if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
qWarning() << "Fade event configuration file " << path << " cannot be opened";
|
||||
}
|
||||
else {
|
||||
QString fileData = file.readAll();
|
||||
file.close();
|
||||
QJsonParseError error;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(fileData.toUtf8(), &error);
|
||||
if (error.error == error.NoError) {
|
||||
QJsonObject jsonObject = doc.object();
|
||||
QJsonValue value;
|
||||
auto& event = events[editedCategory];
|
||||
|
||||
qCDebug(renderlogging) << "Fade event configuration file" << path << "loaded";
|
||||
|
||||
value = jsonObject["edgeInnerColor"];
|
||||
if (value.isArray()) {
|
||||
QJsonArray data = value.toArray();
|
||||
|
||||
if (data.size() < 4) {
|
||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'edgeInnerColor' field. Expected array of size 4";
|
||||
}
|
||||
else {
|
||||
event.edgeInnerColor.r = (float)data.at(0).toDouble();
|
||||
event.edgeInnerColor.g = (float)data.at(1).toDouble();
|
||||
event.edgeInnerColor.b = (float)data.at(2).toDouble();
|
||||
event.edgeInnerColor.a = (float)data.at(3).toDouble();
|
||||
}
|
||||
}
|
||||
else {
|
||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'edgeInnerColor' field. Expected array of size 4";
|
||||
}
|
||||
|
||||
value = jsonObject["edgeOuterColor"];
|
||||
if (value.isArray()) {
|
||||
QJsonArray data = value.toArray();
|
||||
|
||||
if (data.size() < 4) {
|
||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'edgeOuterColor' field. Expected array of size 4";
|
||||
}
|
||||
else {
|
||||
event.edgeOuterColor.r = (float)data.at(0).toDouble();
|
||||
event.edgeOuterColor.g = (float)data.at(1).toDouble();
|
||||
event.edgeOuterColor.b = (float)data.at(2).toDouble();
|
||||
event.edgeOuterColor.a = (float)data.at(3).toDouble();
|
||||
}
|
||||
}
|
||||
else {
|
||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'edgeOuterColor' field. Expected array of size 4";
|
||||
}
|
||||
|
||||
value = jsonObject["noiseSize"];
|
||||
if (value.isArray()) {
|
||||
QJsonArray data = value.toArray();
|
||||
|
||||
if (data.size() < 3) {
|
||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'noiseSize' field. Expected array of size 3";
|
||||
}
|
||||
else {
|
||||
event.noiseSize.x = (float)data.at(0).toDouble();
|
||||
event.noiseSize.y = (float)data.at(1).toDouble();
|
||||
event.noiseSize.z = (float)data.at(2).toDouble();
|
||||
}
|
||||
}
|
||||
else {
|
||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'noiseSize' field. Expected array of size 3";
|
||||
}
|
||||
|
||||
value = jsonObject["noiseSpeed"];
|
||||
if (value.isArray()) {
|
||||
QJsonArray data = value.toArray();
|
||||
|
||||
if (data.size() < 3) {
|
||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'noiseSpeed' field. Expected array of size 3";
|
||||
}
|
||||
else {
|
||||
event.noiseSpeed.x = (float)data.at(0).toDouble();
|
||||
event.noiseSpeed.y = (float)data.at(1).toDouble();
|
||||
event.noiseSpeed.z = (float)data.at(2).toDouble();
|
||||
}
|
||||
}
|
||||
else {
|
||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'noiseSpeed' field. Expected array of size 3";
|
||||
}
|
||||
|
||||
value = jsonObject["baseSize"];
|
||||
if (value.isArray()) {
|
||||
QJsonArray data = value.toArray();
|
||||
|
||||
if (data.size() < 3) {
|
||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'baseSize' field. Expected array of size 3";
|
||||
}
|
||||
else {
|
||||
event.baseSize.x = (float)data.at(0).toDouble();
|
||||
event.baseSize.y = (float)data.at(1).toDouble();
|
||||
event.baseSize.z = (float)data.at(2).toDouble();
|
||||
}
|
||||
}
|
||||
else {
|
||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'baseSize' field. Expected array of size 3";
|
||||
}
|
||||
|
||||
value = jsonObject["noiseLevel"];
|
||||
if (value.isDouble()) {
|
||||
event.noiseLevel = (float)value.toDouble();
|
||||
}
|
||||
else {
|
||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'noiseLevel' field. Expected float value";
|
||||
}
|
||||
|
||||
value = jsonObject["baseLevel"];
|
||||
if (value.isDouble()) {
|
||||
event.baseLevel = (float)value.toDouble();
|
||||
}
|
||||
else {
|
||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'baseLevel' field. Expected float value";
|
||||
}
|
||||
|
||||
value = jsonObject["duration"];
|
||||
if (value.isDouble()) {
|
||||
event.duration = (float)value.toDouble();
|
||||
}
|
||||
else {
|
||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'duration' field. Expected float value";
|
||||
}
|
||||
|
||||
value = jsonObject["edgeWidth"];
|
||||
if (value.isDouble()) {
|
||||
event.edgeWidth = std::min(1.f, std::max(0.f, (float)value.toDouble()));
|
||||
}
|
||||
else {
|
||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'edgeWidth' field. Expected float value";
|
||||
}
|
||||
|
||||
value = jsonObject["timing"];
|
||||
if (value.isDouble()) {
|
||||
event.timing = std::max(0, std::min(TIMING_COUNT - 1, value.toInt()));
|
||||
}
|
||||
else {
|
||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'timing' field. Expected integer value";
|
||||
}
|
||||
|
||||
value = jsonObject["isInverted"];
|
||||
if (value.isBool()) {
|
||||
event.isInverted = value.toBool();
|
||||
}
|
||||
else {
|
||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'isInverted' field. Expected boolean value";
|
||||
}
|
||||
|
||||
emit dirty();
|
||||
}
|
||||
else {
|
||||
qWarning() << "Fade event configuration file" << path << "failed to load:" <<
|
||||
error.errorString() << "at offset" << error.offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FadeJob::FadeJob() {
|
||||
_previousTime = usecTimestampNow();
|
||||
}
|
||||
|
||||
void FadeJob::configure(const Config& config) {
|
||||
auto& configurations = _configurations.edit();
|
||||
|
||||
for (auto i = 0; i < FADE_CATEGORY_COUNT; i++) {
|
||||
auto& eventParameters = configurations.parameters[i];
|
||||
const auto& eventConfig = config.events[i];
|
||||
|
||||
eventParameters._baseLevel = eventConfig.baseLevel;
|
||||
eventParameters._noiseInvSizeAndLevel.x = 1.f / eventConfig.noiseSize.x;
|
||||
eventParameters._noiseInvSizeAndLevel.y = 1.f / eventConfig.noiseSize.y;
|
||||
eventParameters._noiseInvSizeAndLevel.z = 1.f / eventConfig.noiseSize.z;
|
||||
eventParameters._noiseInvSizeAndLevel.w = eventConfig.noiseLevel;
|
||||
eventParameters._isInverted = eventConfig.isInverted & 1;
|
||||
eventParameters._edgeWidthInvWidth.x = eventConfig.edgeWidth;
|
||||
eventParameters._edgeWidthInvWidth.y = 1.f / eventParameters._edgeWidthInvWidth.x;
|
||||
eventParameters._innerEdgeColor = eventConfig.edgeInnerColor;
|
||||
eventParameters._outerEdgeColor = eventConfig.edgeOuterColor;
|
||||
_thresholdScale[i] = 1.f + (eventParameters._edgeWidthInvWidth.x + std::max(0.f, (eventConfig.noiseLevel + eventConfig.baseLevel)*0.5f - 0.5f));
|
||||
}
|
||||
}
|
||||
|
||||
void FadeJob::run(const render::RenderContextPointer& renderContext, FadeJob::Output& output) {
|
||||
Config* jobConfig = static_cast<Config*>(renderContext->jobConfig.get());
|
||||
auto scene = renderContext->args->_scene;
|
||||
auto transitionStage = scene->getStage<render::TransitionStage>(render::TransitionStage::getName());
|
||||
uint64_t now = usecTimestampNow();
|
||||
const double deltaTime = (int64_t(now) - int64_t(_previousTime)) / double(USECS_PER_SECOND);
|
||||
render::Transaction transaction;
|
||||
bool isFirstItem = true;
|
||||
bool hasTransaction = false;
|
||||
|
||||
output = (FadeCategory) jobConfig->editedCategory;
|
||||
|
||||
// And now update fade effect
|
||||
for (auto transitionId : *transitionStage) {
|
||||
auto& state = transitionStage->editTransition(transitionId);
|
||||
#ifdef DEBUG
|
||||
auto& item = scene->getItem(state.itemId);
|
||||
assert(item.getTransitionId() == transitionId);
|
||||
#endif
|
||||
if (update(*jobConfig, scene, transaction, state, deltaTime)) {
|
||||
hasTransaction = true;
|
||||
}
|
||||
if (isFirstItem) {
|
||||
jobConfig->setProperty("threshold", state.threshold);
|
||||
isFirstItem = false;
|
||||
}
|
||||
}
|
||||
_previousTime = now;
|
||||
if (hasTransaction) {
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
}
|
||||
|
||||
const FadeCategory FadeJob::transitionToCategory[render::Transition::TYPE_COUNT] = {
|
||||
FADE_ELEMENT_ENTER_LEAVE_DOMAIN,
|
||||
FADE_ELEMENT_ENTER_LEAVE_DOMAIN,
|
||||
FADE_BUBBLE_ISECT_OWNER,
|
||||
FADE_BUBBLE_ISECT_TRESPASSER,
|
||||
FADE_USER_ENTER_LEAVE_DOMAIN,
|
||||
FADE_USER_ENTER_LEAVE_DOMAIN,
|
||||
FADE_AVATAR_CHANGE
|
||||
};
|
||||
|
||||
bool FadeJob::update(const Config& config, const render::ScenePointer& scene, render::Transaction& transaction, render::Transition& transition, const double deltaTime) const {
|
||||
const auto fadeCategory = transitionToCategory[transition.eventType];
|
||||
auto& eventConfig = config.events[fadeCategory];
|
||||
auto item = scene->getItemSafe(transition.itemId);
|
||||
const double eventDuration = (double)eventConfig.duration;
|
||||
const FadeConfig::Timing timing = (FadeConfig::Timing) eventConfig.timing;
|
||||
|
||||
if (item.exist()) {
|
||||
auto aabb = item.getBound();
|
||||
if (render::Item::isValidID(transition.boundItemId)) {
|
||||
auto boundItem = scene->getItemSafe(transition.boundItemId);
|
||||
if (boundItem.exist()) {
|
||||
aabb = boundItem.getBound();
|
||||
}
|
||||
}
|
||||
auto& dimensions = aabb.getDimensions();
|
||||
|
||||
assert(timing < FadeConfig::TIMING_COUNT);
|
||||
|
||||
transition.noiseOffset = aabb.calcCenter();
|
||||
transition.baseInvSize.x = 1.f / eventConfig.baseSize.x;
|
||||
transition.baseInvSize.y = 1.f / eventConfig.baseSize.y;
|
||||
transition.baseInvSize.z = 1.f / eventConfig.baseSize.z;
|
||||
|
||||
switch (transition.eventType) {
|
||||
case render::Transition::ELEMENT_ENTER_DOMAIN:
|
||||
case render::Transition::ELEMENT_LEAVE_DOMAIN:
|
||||
{
|
||||
transition.threshold = computeElementEnterRatio(transition.time, eventDuration, timing);
|
||||
transition.baseOffset = transition.noiseOffset;
|
||||
transition.baseInvSize.x = 1.f / dimensions.x;
|
||||
transition.baseInvSize.y = 1.f / dimensions.y;
|
||||
transition.baseInvSize.z = 1.f / dimensions.z;
|
||||
transition.isFinished += (transition.threshold >= 1.f) & 1;
|
||||
if (transition.eventType == render::Transition::ELEMENT_ENTER_DOMAIN) {
|
||||
transition.threshold = 1.f - transition.threshold;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case render::Transition::BUBBLE_ISECT_OWNER:
|
||||
{
|
||||
transition.threshold = 0.5f;
|
||||
transition.baseOffset = transition.noiseOffset;
|
||||
}
|
||||
break;
|
||||
|
||||
case render::Transition::BUBBLE_ISECT_TRESPASSER:
|
||||
{
|
||||
transition.threshold = 0.5f;
|
||||
transition.baseOffset = transition.noiseOffset;
|
||||
}
|
||||
break;
|
||||
|
||||
case render::Transition::USER_ENTER_DOMAIN:
|
||||
case render::Transition::USER_LEAVE_DOMAIN:
|
||||
{
|
||||
transition.threshold = computeElementEnterRatio(transition.time, eventDuration, timing);
|
||||
transition.baseOffset = transition.noiseOffset - dimensions.y / 2.f;
|
||||
transition.baseInvSize.y = 1.f / dimensions.y;
|
||||
transition.isFinished += (transition.threshold >= 1.f) & 1;
|
||||
if (transition.eventType == render::Transition::USER_LEAVE_DOMAIN) {
|
||||
transition.threshold = 1.f - transition.threshold;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case render::Transition::AVATAR_CHANGE:
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
transition.noiseOffset += eventConfig.noiseSpeed * (float)transition.time;
|
||||
if (config.manualFade) {
|
||||
transition.threshold = config.manualThreshold;
|
||||
}
|
||||
transition.threshold = std::max(0.f, std::min(1.f, transition.threshold));
|
||||
transition.threshold = (transition.threshold - 0.5f)*_thresholdScale[fadeCategory] + 0.5f;
|
||||
transition.time += deltaTime;
|
||||
|
||||
// If the transition is finished for more than a number of frames (here 1), garbage collect it.
|
||||
if (transition.isFinished > 1) {
|
||||
transaction.removeTransitionFromItem(transition.itemId);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
float FadeJob::computeElementEnterRatio(double time, const double period, FadeConfig::Timing timing) {
|
||||
assert(period > 0.0);
|
||||
float fadeAlpha = 1.0f;
|
||||
const double INV_FADE_PERIOD = 1.0 / period;
|
||||
double fraction = time * INV_FADE_PERIOD;
|
||||
fraction = std::max(fraction, 0.0);
|
||||
if (fraction < 1.0) {
|
||||
switch (timing) {
|
||||
default:
|
||||
fadeAlpha = (float)fraction;
|
||||
break;
|
||||
case FadeConfig::EASE_IN:
|
||||
fadeAlpha = (float)(fraction*fraction*fraction);
|
||||
break;
|
||||
case FadeConfig::EASE_OUT:
|
||||
fadeAlpha = 1.f - (float)fraction;
|
||||
fadeAlpha = 1.f- fadeAlpha*fadeAlpha*fadeAlpha;
|
||||
break;
|
||||
case FadeConfig::EASE_IN_OUT:
|
||||
fadeAlpha = (float)(fraction*fraction*fraction*(fraction*(fraction * 6 - 15) + 10));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return fadeAlpha;
|
||||
}
|
248
libraries/render-utils/src/FadeEffectJobs.h
Normal file
|
@ -0,0 +1,248 @@
|
|||
//
|
||||
// FadeEffectJobs.h
|
||||
|
||||
// Created by Olivier Prat on 07/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
|
||||
//
|
||||
|
||||
#ifndef hifi_render_utils_FadeEffectJobs_h
|
||||
#define hifi_render_utils_FadeEffectJobs_h
|
||||
|
||||
#include "FadeEffect.h"
|
||||
|
||||
#include <gpu/Pipeline.h>
|
||||
#include <render/ShapePipeline.h>
|
||||
#include <render/RenderFetchCullSortTask.h>
|
||||
#include <render/Transition.h>
|
||||
|
||||
enum FadeCategory {
|
||||
FADE_ELEMENT_ENTER_LEAVE_DOMAIN = 0,
|
||||
FADE_BUBBLE_ISECT_OWNER,
|
||||
FADE_BUBBLE_ISECT_TRESPASSER,
|
||||
FADE_USER_ENTER_LEAVE_DOMAIN,
|
||||
FADE_AVATAR_CHANGE,
|
||||
|
||||
// Don't forget to modify Fade.slh to reflect the change in number of categories
|
||||
FADE_CATEGORY_COUNT,
|
||||
};
|
||||
|
||||
class FadeEditConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool editFade MEMBER editFade NOTIFY dirty)
|
||||
|
||||
public:
|
||||
|
||||
bool editFade{ false };
|
||||
|
||||
signals:
|
||||
|
||||
void dirty();
|
||||
};
|
||||
|
||||
class FadeConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int editedCategory MEMBER editedCategory WRITE setEditedCategory NOTIFY dirtyCategory)
|
||||
Q_PROPERTY(float duration READ getDuration WRITE setDuration NOTIFY dirty)
|
||||
Q_PROPERTY(float baseSizeX READ getBaseSizeX WRITE setBaseSizeX NOTIFY dirty)
|
||||
Q_PROPERTY(float baseSizeY READ getBaseSizeY WRITE setBaseSizeY NOTIFY dirty)
|
||||
Q_PROPERTY(float baseSizeZ READ getBaseSizeZ WRITE setBaseSizeZ NOTIFY dirty)
|
||||
Q_PROPERTY(float baseLevel READ getBaseLevel WRITE setBaseLevel NOTIFY dirty)
|
||||
Q_PROPERTY(bool _isInverted READ isInverted WRITE setInverted NOTIFY dirty)
|
||||
Q_PROPERTY(float noiseSizeX READ getNoiseSizeX WRITE setNoiseSizeX NOTIFY dirty)
|
||||
Q_PROPERTY(float noiseSizeY READ getNoiseSizeY WRITE setNoiseSizeY NOTIFY dirty)
|
||||
Q_PROPERTY(float noiseSizeZ READ getNoiseSizeZ WRITE setNoiseSizeZ NOTIFY dirty)
|
||||
Q_PROPERTY(float noiseLevel READ getNoiseLevel WRITE setNoiseLevel NOTIFY dirty)
|
||||
Q_PROPERTY(float edgeWidth READ getEdgeWidth WRITE setEdgeWidth NOTIFY dirty)
|
||||
Q_PROPERTY(float edgeInnerColorR READ getEdgeInnerColorR WRITE setEdgeInnerColorR NOTIFY dirty)
|
||||
Q_PROPERTY(float edgeInnerColorG READ getEdgeInnerColorG WRITE setEdgeInnerColorG NOTIFY dirty)
|
||||
Q_PROPERTY(float edgeInnerColorB READ getEdgeInnerColorB WRITE setEdgeInnerColorB NOTIFY dirty)
|
||||
Q_PROPERTY(float edgeInnerIntensity READ getEdgeInnerIntensity WRITE setEdgeInnerIntensity NOTIFY dirty)
|
||||
Q_PROPERTY(float edgeOuterColorR READ getEdgeOuterColorR WRITE setEdgeOuterColorR NOTIFY dirty)
|
||||
Q_PROPERTY(float edgeOuterColorG READ getEdgeOuterColorG WRITE setEdgeOuterColorG NOTIFY dirty)
|
||||
Q_PROPERTY(float edgeOuterColorB READ getEdgeOuterColorB WRITE setEdgeOuterColorB NOTIFY dirty)
|
||||
Q_PROPERTY(float edgeOuterIntensity READ getEdgeOuterIntensity WRITE setEdgeOuterIntensity NOTIFY dirty)
|
||||
Q_PROPERTY(int timing READ getTiming WRITE setTiming NOTIFY dirty)
|
||||
Q_PROPERTY(float noiseSpeedX READ getNoiseSpeedX WRITE setNoiseSpeedX NOTIFY dirty)
|
||||
Q_PROPERTY(float noiseSpeedY READ getNoiseSpeedY WRITE setNoiseSpeedY NOTIFY dirty)
|
||||
Q_PROPERTY(float noiseSpeedZ READ getNoiseSpeedZ WRITE setNoiseSpeedZ NOTIFY dirty)
|
||||
Q_PROPERTY(float threshold MEMBER threshold NOTIFY dirty)
|
||||
Q_PROPERTY(bool manualFade MEMBER manualFade NOTIFY dirty)
|
||||
Q_PROPERTY(float manualThreshold MEMBER manualThreshold NOTIFY dirty)
|
||||
|
||||
public:
|
||||
|
||||
enum Timing {
|
||||
LINEAR,
|
||||
EASE_IN,
|
||||
EASE_OUT,
|
||||
EASE_IN_OUT,
|
||||
|
||||
TIMING_COUNT
|
||||
};
|
||||
|
||||
FadeConfig();
|
||||
|
||||
void setEditedCategory(int value);
|
||||
|
||||
void setDuration(float value);
|
||||
float getDuration() const;
|
||||
|
||||
void setBaseSizeX(float value);
|
||||
float getBaseSizeX() const;
|
||||
|
||||
void setBaseSizeY(float value);
|
||||
float getBaseSizeY() const;
|
||||
|
||||
void setBaseSizeZ(float value);
|
||||
float getBaseSizeZ() const;
|
||||
|
||||
void setBaseLevel(float value);
|
||||
float getBaseLevel() const { return events[editedCategory].baseLevel; }
|
||||
|
||||
void setInverted(bool value);
|
||||
bool isInverted() const;
|
||||
|
||||
void setNoiseSizeX(float value);
|
||||
float getNoiseSizeX() const;
|
||||
|
||||
void setNoiseSizeY(float value);
|
||||
float getNoiseSizeY() const;
|
||||
|
||||
void setNoiseSizeZ(float value);
|
||||
float getNoiseSizeZ() const;
|
||||
|
||||
void setNoiseLevel(float value);
|
||||
float getNoiseLevel() const { return events[editedCategory].noiseLevel; }
|
||||
|
||||
void setNoiseSpeedX(float value);
|
||||
float getNoiseSpeedX() const;
|
||||
|
||||
void setNoiseSpeedY(float value);
|
||||
float getNoiseSpeedY() const;
|
||||
|
||||
void setNoiseSpeedZ(float value);
|
||||
float getNoiseSpeedZ() const;
|
||||
|
||||
void setEdgeWidth(float value);
|
||||
float getEdgeWidth() const;
|
||||
|
||||
void setEdgeInnerColorR(float value);
|
||||
float getEdgeInnerColorR() const { return events[editedCategory].edgeInnerColor.r; }
|
||||
|
||||
void setEdgeInnerColorG(float value);
|
||||
float getEdgeInnerColorG() const { return events[editedCategory].edgeInnerColor.g; }
|
||||
|
||||
void setEdgeInnerColorB(float value);
|
||||
float getEdgeInnerColorB() const { return events[editedCategory].edgeInnerColor.b; }
|
||||
|
||||
void setEdgeInnerIntensity(float value);
|
||||
float getEdgeInnerIntensity() const { return events[editedCategory].edgeInnerColor.a; }
|
||||
|
||||
void setEdgeOuterColorR(float value);
|
||||
float getEdgeOuterColorR() const { return events[editedCategory].edgeOuterColor.r; }
|
||||
|
||||
void setEdgeOuterColorG(float value);
|
||||
float getEdgeOuterColorG() const { return events[editedCategory].edgeOuterColor.g; }
|
||||
|
||||
void setEdgeOuterColorB(float value);
|
||||
float getEdgeOuterColorB() const { return events[editedCategory].edgeOuterColor.b; }
|
||||
|
||||
void setEdgeOuterIntensity(float value);
|
||||
float getEdgeOuterIntensity() const { return events[editedCategory].edgeOuterColor.a; }
|
||||
|
||||
void setTiming(int value);
|
||||
int getTiming() const { return events[editedCategory].timing; }
|
||||
|
||||
struct Event {
|
||||
glm::vec4 edgeInnerColor;
|
||||
glm::vec4 edgeOuterColor;
|
||||
glm::vec3 noiseSize;
|
||||
glm::vec3 noiseSpeed;
|
||||
glm::vec3 baseSize;
|
||||
float noiseLevel;
|
||||
float baseLevel;
|
||||
float duration;
|
||||
float edgeWidth;
|
||||
int timing;
|
||||
bool isInverted;
|
||||
};
|
||||
|
||||
Event events[FADE_CATEGORY_COUNT];
|
||||
int editedCategory{ FADE_ELEMENT_ENTER_LEAVE_DOMAIN };
|
||||
float threshold{ 0.f };
|
||||
float manualThreshold{ 0.f };
|
||||
bool manualFade{ false };
|
||||
|
||||
Q_INVOKABLE void save() const;
|
||||
Q_INVOKABLE void load();
|
||||
|
||||
static QString eventNames[FADE_CATEGORY_COUNT];
|
||||
|
||||
signals:
|
||||
|
||||
void dirty();
|
||||
void dirtyCategory();
|
||||
|
||||
};
|
||||
|
||||
class FadeEditJob {
|
||||
|
||||
public:
|
||||
|
||||
using Config = FadeEditConfig;
|
||||
using Input = render::VaryingSet2<render::ItemBounds, FadeCategory>;
|
||||
using JobModel = render::Job::ModelI<FadeEditJob, Input, Config>;
|
||||
|
||||
FadeEditJob() {}
|
||||
|
||||
void configure(const Config& config);
|
||||
void run(const render::RenderContextPointer& renderContext, const FadeEditJob::Input& inputs);
|
||||
|
||||
private:
|
||||
|
||||
bool _isEditEnabled{ false };
|
||||
render::ItemID _editedItem{ render::Item::INVALID_ITEM_ID };
|
||||
|
||||
render::ItemID findNearestItem(const render::RenderContextPointer& renderContext, const render::ItemBounds& inputs, float& minIsectDistance) const;
|
||||
};
|
||||
|
||||
class FadeJob {
|
||||
|
||||
public:
|
||||
|
||||
static const FadeCategory transitionToCategory[render::Transition::TYPE_COUNT];
|
||||
|
||||
using Config = FadeConfig;
|
||||
using Output = FadeCategory;
|
||||
using JobModel = render::Job::ModelO<FadeJob, Output, Config>;
|
||||
|
||||
FadeJob();
|
||||
|
||||
void configure(const Config& config);
|
||||
void run(const render::RenderContextPointer& renderContext, FadeJob::Output& output);
|
||||
|
||||
gpu::BufferView getConfigurationBuffer() const { return _configurations; }
|
||||
|
||||
private:
|
||||
|
||||
#include "Fade_shared.slh"
|
||||
|
||||
struct FadeConfiguration
|
||||
{
|
||||
FadeParameters parameters[FADE_CATEGORY_COUNT];
|
||||
};
|
||||
using FadeConfigurationBuffer = gpu::StructBuffer<FadeConfiguration>;
|
||||
|
||||
FadeConfigurationBuffer _configurations;
|
||||
float _thresholdScale[FADE_CATEGORY_COUNT];
|
||||
uint64_t _previousTime{ 0 };
|
||||
|
||||
bool update(const Config& config, const render::ScenePointer& scene, render::Transaction& transaction, render::Transition& transition, const double deltaTime) const;
|
||||
static float computeElementEnterRatio(double time, const double period, FadeConfig::Timing timing);
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_render_utils_FadeEffectJobs_h
|
27
libraries/render-utils/src/Fade_shared.slh
Normal file
|
@ -0,0 +1,27 @@
|
|||
// glsl / C++ compatible source as interface for FadeEffect
|
||||
#ifdef __cplusplus
|
||||
# define VEC4 glm::vec4
|
||||
# define VEC2 glm::vec2
|
||||
# define FLOAT32 glm::float32
|
||||
# define INT32 glm::int32
|
||||
#else
|
||||
# define VEC4 vec4
|
||||
# define VEC2 vec2
|
||||
# define FLOAT32 float
|
||||
# define INT32 int
|
||||
#endif
|
||||
|
||||
struct FadeParameters
|
||||
{
|
||||
VEC4 _noiseInvSizeAndLevel;
|
||||
VEC4 _innerEdgeColor;
|
||||
VEC4 _outerEdgeColor;
|
||||
VEC2 _edgeWidthInvWidth;
|
||||
FLOAT32 _baseLevel;
|
||||
INT32 _isInverted;
|
||||
};
|
||||
|
||||
// <@if 1@>
|
||||
// Trigger Scribe include
|
||||
// <@endif@> <!def that !>
|
||||
//
|
|
@ -25,6 +25,7 @@
|
|||
#include "TextureCache.h"
|
||||
#include "RenderUtilsLogging.h"
|
||||
#include "StencilMaskPass.h"
|
||||
#include "FadeEffect.h"
|
||||
|
||||
#include "gpu/StandardShaderLib.h"
|
||||
|
||||
|
@ -37,6 +38,9 @@
|
|||
#include "simple_vert.h"
|
||||
#include "simple_textured_frag.h"
|
||||
#include "simple_textured_unlit_frag.h"
|
||||
#include "simple_fade_vert.h"
|
||||
#include "simple_textured_fade_frag.h"
|
||||
#include "simple_textured_unlit_fade_frag.h"
|
||||
#include "simple_opaque_web_browser_frag.h"
|
||||
#include "simple_opaque_web_browser_overlay_frag.h"
|
||||
#include "simple_transparent_web_browser_frag.h"
|
||||
|
@ -56,9 +60,11 @@ static const int VERTICES_PER_TRIANGLE = 3;
|
|||
static const gpu::Element POSITION_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ };
|
||||
static const gpu::Element NORMAL_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ };
|
||||
static const gpu::Element COLOR_ELEMENT { gpu::VEC4, gpu::NUINT8, gpu::RGBA };
|
||||
static const gpu::Element TEXCOORD4_ELEMENT { gpu::VEC4, gpu::FLOAT, gpu::XYZW };
|
||||
|
||||
static gpu::Stream::FormatPointer SOLID_STREAM_FORMAT;
|
||||
static gpu::Stream::FormatPointer INSTANCED_SOLID_STREAM_FORMAT;
|
||||
static gpu::Stream::FormatPointer INSTANCED_SOLID_FADE_STREAM_FORMAT;
|
||||
|
||||
static const uint SHAPE_VERTEX_STRIDE = sizeof(glm::vec3) * 2; // vertices and normals
|
||||
static const uint SHAPE_NORMALS_OFFSET = sizeof(glm::vec3);
|
||||
|
@ -447,34 +453,64 @@ gpu::Stream::FormatPointer& getInstancedSolidStreamFormat() {
|
|||
return INSTANCED_SOLID_STREAM_FORMAT;
|
||||
}
|
||||
|
||||
gpu::Stream::FormatPointer& getInstancedSolidFadeStreamFormat() {
|
||||
if (!INSTANCED_SOLID_FADE_STREAM_FORMAT) {
|
||||
INSTANCED_SOLID_FADE_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone
|
||||
INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT);
|
||||
INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT);
|
||||
INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
|
||||
INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD2, gpu::Stream::TEXCOORD2, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
|
||||
INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD3, gpu::Stream::TEXCOORD3, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
|
||||
INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD4, gpu::Stream::TEXCOORD4, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
|
||||
}
|
||||
return INSTANCED_SOLID_FADE_STREAM_FORMAT;
|
||||
}
|
||||
|
||||
QHash<SimpleProgramKey, gpu::PipelinePointer> GeometryCache::_simplePrograms;
|
||||
|
||||
gpu::ShaderPointer GeometryCache::_simpleShader;
|
||||
gpu::ShaderPointer GeometryCache::_unlitShader;
|
||||
gpu::ShaderPointer GeometryCache::_simpleFadeShader;
|
||||
gpu::ShaderPointer GeometryCache::_unlitFadeShader;
|
||||
|
||||
render::ShapePipelinePointer GeometryCache::_simpleOpaquePipeline;
|
||||
render::ShapePipelinePointer GeometryCache::_simpleTransparentPipeline;
|
||||
render::ShapePipelinePointer GeometryCache::_simpleOpaqueFadePipeline;
|
||||
render::ShapePipelinePointer GeometryCache::_simpleTransparentFadePipeline;
|
||||
render::ShapePipelinePointer GeometryCache::_simpleWirePipeline;
|
||||
|
||||
uint8_t GeometryCache::CUSTOM_PIPELINE_NUMBER = 0;
|
||||
|
||||
render::ShapePipelinePointer GeometryCache::shapePipelineFactory(const render::ShapePlumber& plumber, const render::ShapeKey& key) {
|
||||
initializeShapePipelines();
|
||||
|
||||
if (key.isWireframe()) {
|
||||
return _simpleWirePipeline;
|
||||
}
|
||||
|
||||
if (key.isFaded()) {
|
||||
if (key.isTranslucent()) {
|
||||
return _simpleTransparentFadePipeline;
|
||||
}
|
||||
else {
|
||||
return _simpleOpaqueFadePipeline;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (key.isTranslucent()) {
|
||||
return _simpleTransparentPipeline;
|
||||
}
|
||||
else {
|
||||
return _simpleOpaquePipeline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GeometryCache::GeometryCache() :
|
||||
_nextID(0) {
|
||||
// Let's register its special shapePipeline factory:
|
||||
registerShapePipeline();
|
||||
buildShapes();
|
||||
GeometryCache::_simpleOpaquePipeline =
|
||||
std::make_shared<render::ShapePipeline>(getSimplePipeline(false, false, true, false), nullptr,
|
||||
[](const render::ShapePipeline&, gpu::Batch& batch, RenderArgs* args) {
|
||||
// Set the defaults needed for a simple program
|
||||
batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO,
|
||||
DependencyManager::get<TextureCache>()->getWhiteTexture());
|
||||
},
|
||||
nullptr
|
||||
);
|
||||
GeometryCache::_simpleTransparentPipeline =
|
||||
std::make_shared<render::ShapePipeline>(getSimplePipeline(false, true, true, false), nullptr,
|
||||
[](const render::ShapePipeline&, gpu::Batch& batch, RenderArgs* args) {
|
||||
// Set the defaults needed for a simple program
|
||||
batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO,
|
||||
DependencyManager::get<TextureCache>()->getWhiteTexture());
|
||||
},
|
||||
nullptr
|
||||
);
|
||||
GeometryCache::_simpleWirePipeline =
|
||||
std::make_shared<render::ShapePipeline>(getSimplePipeline(false, false, true, true), nullptr,
|
||||
[](const render::ShapePipeline&, gpu::Batch& batch, RenderArgs* args) {}, nullptr);
|
||||
}
|
||||
|
||||
GeometryCache::~GeometryCache() {
|
||||
|
@ -514,9 +550,46 @@ void GeometryCache::releaseID(int id) {
|
|||
_registeredGridBuffers.remove(id);
|
||||
}
|
||||
|
||||
void setupBatchInstance(gpu::Batch& batch, gpu::BufferPointer colorBuffer) {
|
||||
gpu::BufferView colorView(colorBuffer, COLOR_ELEMENT);
|
||||
batch.setInputBuffer(gpu::Stream::COLOR, colorView);
|
||||
void GeometryCache::initializeShapePipelines() {
|
||||
if (!_simpleOpaquePipeline) {
|
||||
_simpleOpaquePipeline = getShapePipeline(false, false, true, false);
|
||||
_simpleTransparentPipeline = getShapePipeline(false, true, true, false);
|
||||
_simpleOpaqueFadePipeline = getFadingShapePipeline(false, false, false, false, false);
|
||||
_simpleTransparentFadePipeline = getFadingShapePipeline(false, true, false, false, false);
|
||||
_simpleWirePipeline = getShapePipeline(false, false, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
render::ShapePipelinePointer GeometryCache::getShapePipeline(bool textured, bool transparent, bool culled,
|
||||
bool unlit, bool depthBias) {
|
||||
|
||||
return std::make_shared<render::ShapePipeline>(getSimplePipeline(textured, transparent, culled, unlit, depthBias, false), nullptr,
|
||||
[](const render::ShapePipeline& , gpu::Batch& batch, render::Args*) {
|
||||
batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, DependencyManager::get<TextureCache>()->getWhiteTexture());
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
render::ShapePipelinePointer GeometryCache::getFadingShapePipeline(bool textured, bool transparent, bool culled,
|
||||
bool unlit, bool depthBias) {
|
||||
auto fadeEffect = DependencyManager::get<FadeEffect>();
|
||||
auto fadeBatchSetter = fadeEffect->getBatchSetter();
|
||||
auto fadeItemSetter = fadeEffect->getItemStoredSetter();
|
||||
return std::make_shared<render::ShapePipeline>(getSimplePipeline(textured, transparent, culled, unlit, depthBias, true), nullptr,
|
||||
[fadeBatchSetter, fadeItemSetter](const render::ShapePipeline& shapePipeline, gpu::Batch& batch, render::Args* args) {
|
||||
batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, DependencyManager::get<TextureCache>()->getWhiteTexture());
|
||||
fadeBatchSetter(shapePipeline, batch, args);
|
||||
},
|
||||
fadeItemSetter
|
||||
);
|
||||
}
|
||||
|
||||
render::ShapePipelinePointer GeometryCache::getOpaqueShapePipeline(bool isFading) {
|
||||
return isFading ? _simpleOpaqueFadePipeline : _simpleOpaquePipeline;
|
||||
}
|
||||
|
||||
render::ShapePipelinePointer GeometryCache::getTransparentShapePipeline(bool isFading) {
|
||||
return isFading ? _simpleTransparentFadePipeline : _simpleTransparentPipeline;
|
||||
}
|
||||
|
||||
void GeometryCache::renderShape(gpu::Batch& batch, Shape shape) {
|
||||
|
@ -529,6 +602,11 @@ void GeometryCache::renderWireShape(gpu::Batch& batch, Shape shape) {
|
|||
_shapes[shape].drawWire(batch);
|
||||
}
|
||||
|
||||
void setupBatchInstance(gpu::Batch& batch, gpu::BufferPointer colorBuffer) {
|
||||
gpu::BufferView colorView(colorBuffer, COLOR_ELEMENT);
|
||||
batch.setInputBuffer(gpu::Stream::COLOR, colorView);
|
||||
}
|
||||
|
||||
void GeometryCache::renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer) {
|
||||
batch.setInputFormat(getInstancedSolidStreamFormat());
|
||||
setupBatchInstance(batch, colorBuffer);
|
||||
|
@ -541,6 +619,32 @@ void GeometryCache::renderWireShapeInstances(gpu::Batch& batch, Shape shape, siz
|
|||
_shapes[shape].drawWireInstances(batch, count);
|
||||
}
|
||||
|
||||
void setupBatchFadeInstance(gpu::Batch& batch, gpu::BufferPointer colorBuffer,
|
||||
gpu::BufferPointer fadeBuffer1, gpu::BufferPointer fadeBuffer2, gpu::BufferPointer fadeBuffer3) {
|
||||
gpu::BufferView colorView(colorBuffer, COLOR_ELEMENT);
|
||||
gpu::BufferView texCoord2View(fadeBuffer1, TEXCOORD4_ELEMENT);
|
||||
gpu::BufferView texCoord3View(fadeBuffer2, TEXCOORD4_ELEMENT);
|
||||
gpu::BufferView texCoord4View(fadeBuffer3, TEXCOORD4_ELEMENT);
|
||||
batch.setInputBuffer(gpu::Stream::COLOR, colorView);
|
||||
batch.setInputBuffer(gpu::Stream::TEXCOORD2, texCoord2View);
|
||||
batch.setInputBuffer(gpu::Stream::TEXCOORD3, texCoord3View);
|
||||
batch.setInputBuffer(gpu::Stream::TEXCOORD4, texCoord4View);
|
||||
}
|
||||
|
||||
void GeometryCache::renderFadeShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer,
|
||||
gpu::BufferPointer& fadeBuffer1, gpu::BufferPointer& fadeBuffer2, gpu::BufferPointer& fadeBuffer3) {
|
||||
batch.setInputFormat(getInstancedSolidFadeStreamFormat());
|
||||
setupBatchFadeInstance(batch, colorBuffer, fadeBuffer1, fadeBuffer2, fadeBuffer3);
|
||||
_shapes[shape].drawInstances(batch, count);
|
||||
}
|
||||
|
||||
void GeometryCache::renderWireFadeShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer,
|
||||
gpu::BufferPointer& fadeBuffer1, gpu::BufferPointer& fadeBuffer2, gpu::BufferPointer& fadeBuffer3) {
|
||||
batch.setInputFormat(getInstancedSolidFadeStreamFormat());
|
||||
setupBatchFadeInstance(batch, colorBuffer, fadeBuffer1, fadeBuffer2, fadeBuffer3);
|
||||
_shapes[shape].drawWireInstances(batch, count);
|
||||
}
|
||||
|
||||
void GeometryCache::renderCube(gpu::Batch& batch) {
|
||||
renderShape(batch, Cube);
|
||||
}
|
||||
|
@ -1770,6 +1874,7 @@ public:
|
|||
IS_CULLED_FLAG,
|
||||
IS_UNLIT_FLAG,
|
||||
HAS_DEPTH_BIAS_FLAG,
|
||||
IS_FADING_FLAG,
|
||||
|
||||
NUM_FLAGS,
|
||||
};
|
||||
|
@ -1780,6 +1885,7 @@ public:
|
|||
IS_CULLED = (1 << IS_CULLED_FLAG),
|
||||
IS_UNLIT = (1 << IS_UNLIT_FLAG),
|
||||
HAS_DEPTH_BIAS = (1 << HAS_DEPTH_BIAS_FLAG),
|
||||
IS_FADING = (1 << IS_FADING_FLAG),
|
||||
};
|
||||
typedef unsigned short Flags;
|
||||
|
||||
|
@ -1790,6 +1896,7 @@ public:
|
|||
bool isCulled() const { return isFlag(IS_CULLED); }
|
||||
bool isUnlit() const { return isFlag(IS_UNLIT); }
|
||||
bool hasDepthBias() const { return isFlag(HAS_DEPTH_BIAS); }
|
||||
bool isFading() const { return isFlag(IS_FADING); }
|
||||
|
||||
Flags _flags = 0;
|
||||
short _spare = 0;
|
||||
|
@ -1798,9 +1905,9 @@ public:
|
|||
|
||||
|
||||
SimpleProgramKey(bool textured = false, bool transparent = false, bool culled = true,
|
||||
bool unlit = false, bool depthBias = false) {
|
||||
bool unlit = false, bool depthBias = false, bool fading = false) {
|
||||
_flags = (textured ? IS_TEXTURED : 0) | (transparent ? IS_TRANSPARENT : 0) | (culled ? IS_CULLED : 0) |
|
||||
(unlit ? IS_UNLIT : 0) | (depthBias ? HAS_DEPTH_BIAS : 0);
|
||||
(unlit ? IS_UNLIT : 0) | (depthBias ? HAS_DEPTH_BIAS : 0) | (fading ? IS_FADING : 0);
|
||||
}
|
||||
|
||||
SimpleProgramKey(int bitmask) : _flags(bitmask) {}
|
||||
|
@ -1879,23 +1986,8 @@ void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool tra
|
|||
}
|
||||
}
|
||||
|
||||
gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transparent, bool culled, bool unlit, bool depthBiased) {
|
||||
SimpleProgramKey config { textured, transparent, culled, unlit, depthBiased };
|
||||
|
||||
// Compile the shaders
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [&]() {
|
||||
auto VS = gpu::Shader::createVertex(std::string(simple_vert));
|
||||
auto PS = gpu::Shader::createPixel(std::string(simple_textured_frag));
|
||||
auto PSUnlit = gpu::Shader::createPixel(std::string(simple_textured_unlit_frag));
|
||||
|
||||
_simpleShader = gpu::Shader::createProgram(VS, PS);
|
||||
_unlitShader = gpu::Shader::createProgram(VS, PSUnlit);
|
||||
|
||||
gpu::Shader::BindingSet slotBindings;
|
||||
gpu::Shader::makeProgram(*_simpleShader, slotBindings);
|
||||
gpu::Shader::makeProgram(*_unlitShader, slotBindings);
|
||||
});
|
||||
gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transparent, bool culled, bool unlit, bool depthBiased, bool fading) {
|
||||
SimpleProgramKey config { textured, transparent, culled, unlit, depthBiased, fading };
|
||||
|
||||
// If the pipeline already exists, return it
|
||||
auto it = _simplePrograms.find(config);
|
||||
|
@ -1903,6 +1995,40 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp
|
|||
return it.value();
|
||||
}
|
||||
|
||||
// Compile the shaders
|
||||
if (!fading) {
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [&]() {
|
||||
auto VS = gpu::Shader::createVertex(std::string(simple_vert));
|
||||
auto PS = gpu::Shader::createPixel(std::string(simple_textured_frag));
|
||||
auto PSUnlit = gpu::Shader::createPixel(std::string(simple_textured_unlit_frag));
|
||||
|
||||
_simpleShader = gpu::Shader::createProgram(VS, PS);
|
||||
_unlitShader = gpu::Shader::createProgram(VS, PSUnlit);
|
||||
|
||||
gpu::Shader::BindingSet slotBindings;
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("originalTexture"), render::ShapePipeline::Slot::MAP::ALBEDO));
|
||||
gpu::Shader::makeProgram(*_simpleShader, slotBindings);
|
||||
gpu::Shader::makeProgram(*_unlitShader, slotBindings);
|
||||
});
|
||||
} else {
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [&]() {
|
||||
auto VS = gpu::Shader::createVertex(std::string(simple_fade_vert));
|
||||
auto PS = gpu::Shader::createPixel(std::string(simple_textured_fade_frag));
|
||||
auto PSUnlit = gpu::Shader::createPixel(std::string(simple_textured_unlit_fade_frag));
|
||||
|
||||
_simpleFadeShader = gpu::Shader::createProgram(VS, PS);
|
||||
_unlitFadeShader = gpu::Shader::createProgram(VS, PSUnlit);
|
||||
|
||||
gpu::Shader::BindingSet slotBindings;
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("originalTexture"), render::ShapePipeline::Slot::MAP::ALBEDO));
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), render::ShapePipeline::Slot::MAP::FADE_MASK));
|
||||
gpu::Shader::makeProgram(*_simpleFadeShader, slotBindings);
|
||||
gpu::Shader::makeProgram(*_unlitFadeShader, slotBindings);
|
||||
});
|
||||
}
|
||||
|
||||
// If the pipeline did not exist, make it
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
if (config.isCulled()) {
|
||||
|
@ -1921,11 +2047,12 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp
|
|||
|
||||
if (config.isTransparent()) {
|
||||
PrepareStencil::testMask(*state);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
PrepareStencil::testMaskDrawShape(*state);
|
||||
}
|
||||
|
||||
gpu::ShaderPointer program = (config.isUnlit()) ? _unlitShader : _simpleShader;
|
||||
gpu::ShaderPointer program = (config.isUnlit()) ? (config.isFading() ? _unlitFadeShader : _unlitShader) : (config.isFading() ? _simpleFadeShader : _simpleShader);
|
||||
gpu::PipelinePointer pipeline = gpu::Pipeline::create(program, state);
|
||||
_simplePrograms.insert(config, pipeline);
|
||||
return pipeline;
|
||||
|
@ -1960,26 +2087,93 @@ void renderInstances(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color
|
|||
|
||||
if (isWire) {
|
||||
DependencyManager::get<GeometryCache>()->renderWireShapeInstances(batch, shape, data.count(), data.buffers[INSTANCE_COLOR_BUFFER]);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
DependencyManager::get<GeometryCache>()->renderShapeInstances(batch, shape, data.count(), data.buffers[INSTANCE_COLOR_BUFFER]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static const size_t INSTANCE_FADE_BUFFER1 = 1;
|
||||
static const size_t INSTANCE_FADE_BUFFER2 = 2;
|
||||
static const size_t INSTANCE_FADE_BUFFER3 = 3;
|
||||
|
||||
void renderFadeInstances(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, int fadeCategory, float fadeThreshold,
|
||||
const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize, bool isWire,
|
||||
const render::ShapePipelinePointer& pipeline, GeometryCache::Shape shape) {
|
||||
// Add pipeline to name
|
||||
std::string instanceName = (isWire ? "wire_shapes_" : "solid_shapes_") + std::to_string(shape) + "_" + std::to_string(std::hash<render::ShapePipelinePointer>()(pipeline));
|
||||
|
||||
// Add color to named buffer
|
||||
{
|
||||
gpu::BufferPointer instanceColorBuffer = batch.getNamedBuffer(instanceName, INSTANCE_COLOR_BUFFER);
|
||||
auto compactColor = toCompactColor(color);
|
||||
instanceColorBuffer->append(compactColor);
|
||||
}
|
||||
// Add fade parameters to named buffers
|
||||
{
|
||||
gpu::BufferPointer fadeBuffer1 = batch.getNamedBuffer(instanceName, INSTANCE_FADE_BUFFER1);
|
||||
gpu::BufferPointer fadeBuffer2 = batch.getNamedBuffer(instanceName, INSTANCE_FADE_BUFFER2);
|
||||
gpu::BufferPointer fadeBuffer3 = batch.getNamedBuffer(instanceName, INSTANCE_FADE_BUFFER3);
|
||||
// Pack parameters in 3 vec4s
|
||||
glm::vec4 fadeData1;
|
||||
glm::vec4 fadeData2;
|
||||
glm::vec4 fadeData3;
|
||||
FadeEffect::packToAttributes(fadeCategory, fadeThreshold, fadeNoiseOffset, fadeBaseOffset, fadeBaseInvSize,
|
||||
fadeData1, fadeData2, fadeData3);
|
||||
fadeBuffer1->append(fadeData1);
|
||||
fadeBuffer2->append(fadeData2);
|
||||
fadeBuffer3->append(fadeData3);
|
||||
}
|
||||
|
||||
// Add call to named buffer
|
||||
batch.setupNamedCalls(instanceName, [args, isWire, pipeline, shape](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
|
||||
auto& buffers = data.buffers;
|
||||
batch.setPipeline(pipeline->pipeline);
|
||||
pipeline->prepare(batch, args);
|
||||
|
||||
if (isWire) {
|
||||
DependencyManager::get<GeometryCache>()->renderWireFadeShapeInstances(batch, shape, data.count(),
|
||||
buffers[INSTANCE_COLOR_BUFFER], buffers[INSTANCE_FADE_BUFFER1], buffers[INSTANCE_FADE_BUFFER2], buffers[INSTANCE_FADE_BUFFER3]);
|
||||
}
|
||||
else {
|
||||
DependencyManager::get<GeometryCache>()->renderFadeShapeInstances(batch, shape, data.count(),
|
||||
buffers[INSTANCE_COLOR_BUFFER], buffers[INSTANCE_FADE_BUFFER1], buffers[INSTANCE_FADE_BUFFER2], buffers[INSTANCE_FADE_BUFFER3]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void GeometryCache::renderSolidShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {
|
||||
assert(pipeline != nullptr);
|
||||
renderInstances(args, batch, color, false, pipeline, shape);
|
||||
}
|
||||
|
||||
void GeometryCache::renderWireShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {
|
||||
assert(pipeline != nullptr);
|
||||
renderInstances(args, batch, color, true, pipeline, shape);
|
||||
}
|
||||
|
||||
void GeometryCache::renderSolidFadeShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color,
|
||||
int fadeCategory, float fadeThreshold, const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize,
|
||||
const render::ShapePipelinePointer& pipeline) {
|
||||
assert(pipeline != nullptr);
|
||||
renderFadeInstances(args, batch, color, fadeCategory, fadeThreshold, fadeNoiseOffset, fadeBaseOffset, fadeBaseInvSize, false, pipeline, shape);
|
||||
}
|
||||
|
||||
void GeometryCache::renderWireFadeShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color,
|
||||
int fadeCategory, float fadeThreshold, const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize,
|
||||
const render::ShapePipelinePointer& pipeline) {
|
||||
assert(pipeline != nullptr);
|
||||
renderFadeInstances(args, batch, color, fadeCategory, fadeThreshold, fadeNoiseOffset, fadeBaseOffset, fadeBaseInvSize, true, pipeline, shape);
|
||||
}
|
||||
|
||||
void GeometryCache::renderSolidSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {
|
||||
assert(pipeline != nullptr);
|
||||
renderInstances(args, batch, color, false, pipeline, GeometryCache::Sphere);
|
||||
}
|
||||
|
||||
void GeometryCache::renderWireSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {
|
||||
assert(pipeline != nullptr);
|
||||
renderInstances(args, batch, color, true, pipeline, GeometryCache::Sphere);
|
||||
}
|
||||
|
||||
|
@ -1987,7 +2181,9 @@ void GeometryCache::renderWireSphereInstance(RenderArgs* args, gpu::Batch& batch
|
|||
// available shape types, both solid and wireframes
|
||||
//#define DEBUG_SHAPES
|
||||
|
||||
|
||||
void GeometryCache::renderSolidCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {
|
||||
assert(pipeline != nullptr);
|
||||
#ifdef DEBUG_SHAPES
|
||||
static auto startTime = usecTimestampNow();
|
||||
renderInstances(INSTANCE_NAME, batch, color, pipeline, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
|
||||
|
@ -2027,5 +2223,6 @@ void GeometryCache::renderSolidCubeInstance(RenderArgs* args, gpu::Batch& batch,
|
|||
|
||||
void GeometryCache::renderWireCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {
|
||||
static const std::string INSTANCE_NAME = __FUNCTION__;
|
||||
assert(pipeline != nullptr);
|
||||
renderInstances(args, batch, color, true, pipeline, GeometryCache::Cube);
|
||||
}
|
||||
|
|
|
@ -147,6 +147,14 @@ public:
|
|||
NUM_SHAPES,
|
||||
};
|
||||
|
||||
static uint8_t CUSTOM_PIPELINE_NUMBER;
|
||||
static render::ShapePipelinePointer shapePipelineFactory(const render::ShapePlumber& plumber, const render::ShapeKey& key);
|
||||
static void registerShapePipeline() {
|
||||
if (!CUSTOM_PIPELINE_NUMBER) {
|
||||
CUSTOM_PIPELINE_NUMBER = render::ShapePipeline::registerCustomShapePipelineFactory(shapePipelineFactory);
|
||||
}
|
||||
}
|
||||
|
||||
int allocateID() { return _nextID++; }
|
||||
void releaseID(int id);
|
||||
static const int UNKNOWN_ID;
|
||||
|
@ -155,8 +163,8 @@ public:
|
|||
void bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool transparent = false, bool culled = true,
|
||||
bool unlit = false, bool depthBias = false);
|
||||
// Get the pipeline to render static geometry
|
||||
gpu::PipelinePointer getSimplePipeline(bool textured = false, bool transparent = false, bool culled = true,
|
||||
bool unlit = false, bool depthBias = false);
|
||||
static gpu::PipelinePointer getSimplePipeline(bool textured = false, bool transparent = false, bool culled = true,
|
||||
bool unlit = false, bool depthBias = false, bool fading = false);
|
||||
|
||||
void bindOpaqueWebBrowserProgram(gpu::Batch& batch, bool isAA);
|
||||
gpu::PipelinePointer getOpaqueWebBrowserProgram(bool isAA);
|
||||
|
@ -164,14 +172,26 @@ public:
|
|||
void bindTransparentWebBrowserProgram(gpu::Batch& batch, bool isAA);
|
||||
gpu::PipelinePointer getTransparentWebBrowserProgram(bool isAA);
|
||||
|
||||
render::ShapePipelinePointer getOpaqueShapePipeline() { return GeometryCache::_simpleOpaquePipeline; }
|
||||
render::ShapePipelinePointer getTransparentShapePipeline() { return GeometryCache::_simpleTransparentPipeline; }
|
||||
render::ShapePipelinePointer getWireShapePipeline() { return GeometryCache::_simpleWirePipeline; }
|
||||
static void initializeShapePipelines();
|
||||
|
||||
render::ShapePipelinePointer getOpaqueShapePipeline() { assert(_simpleOpaquePipeline != nullptr); return _simpleOpaquePipeline; }
|
||||
render::ShapePipelinePointer getTransparentShapePipeline() { assert(_simpleTransparentPipeline != nullptr); return _simpleTransparentPipeline; }
|
||||
render::ShapePipelinePointer getOpaqueFadeShapePipeline() { assert(_simpleOpaqueFadePipeline != nullptr); return _simpleOpaqueFadePipeline; }
|
||||
render::ShapePipelinePointer getTransparentFadeShapePipeline() { assert(_simpleTransparentFadePipeline != nullptr); return _simpleTransparentFadePipeline; }
|
||||
render::ShapePipelinePointer getOpaqueShapePipeline(bool isFading);
|
||||
render::ShapePipelinePointer getTransparentShapePipeline(bool isFading);
|
||||
render::ShapePipelinePointer getWireShapePipeline() { assert(_simpleWirePipeline != nullptr); return GeometryCache::_simpleWirePipeline; }
|
||||
|
||||
|
||||
// Static (instanced) geometry
|
||||
void renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer);
|
||||
void renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer);
|
||||
|
||||
void renderFadeShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer,
|
||||
gpu::BufferPointer& fadeBuffer1, gpu::BufferPointer& fadeBuffer2, gpu::BufferPointer& fadeBuffer3);
|
||||
void renderWireFadeShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer,
|
||||
gpu::BufferPointer& fadeBuffer1, gpu::BufferPointer& fadeBuffer2, gpu::BufferPointer& fadeBuffer3);
|
||||
|
||||
void renderSolidShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec4& color = glm::vec4(1),
|
||||
const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline);
|
||||
void renderSolidShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec3& color,
|
||||
|
@ -186,6 +206,13 @@ public:
|
|||
renderWireShapeInstance(args, batch, shape, glm::vec4(color, 1.0f), pipeline);
|
||||
}
|
||||
|
||||
void renderSolidFadeShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec4& color, int fadeCategory, float fadeThreshold,
|
||||
const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize,
|
||||
const render::ShapePipelinePointer& pipeline);
|
||||
void renderWireFadeShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec4& color, int fadeCategory, float fadeThreshold,
|
||||
const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize,
|
||||
const render::ShapePipelinePointer& pipeline);
|
||||
|
||||
void renderSolidSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color,
|
||||
const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline);
|
||||
void renderSolidSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec3& color,
|
||||
|
@ -416,15 +443,20 @@ private:
|
|||
QHash<int, Vec2FloatPairPair> _lastRegisteredGridBuffer;
|
||||
QHash<int, GridBuffer> _registeredGridBuffers;
|
||||
|
||||
gpu::ShaderPointer _simpleShader;
|
||||
gpu::ShaderPointer _unlitShader;
|
||||
static gpu::ShaderPointer _simpleShader;
|
||||
static gpu::ShaderPointer _unlitShader;
|
||||
static gpu::ShaderPointer _simpleFadeShader;
|
||||
static gpu::ShaderPointer _unlitFadeShader;
|
||||
static render::ShapePipelinePointer _simpleOpaquePipeline;
|
||||
static render::ShapePipelinePointer _simpleTransparentPipeline;
|
||||
static render::ShapePipelinePointer _simpleOpaqueFadePipeline;
|
||||
static render::ShapePipelinePointer _simpleTransparentFadePipeline;
|
||||
static render::ShapePipelinePointer _simpleOpaqueOverlayPipeline;
|
||||
static render::ShapePipelinePointer _simpleTransparentOverlayPipeline;
|
||||
static render::ShapePipelinePointer _simpleWirePipeline;
|
||||
gpu::PipelinePointer _glowLinePipeline;
|
||||
QHash<SimpleProgramKey, gpu::PipelinePointer> _simplePrograms;
|
||||
|
||||
static QHash<SimpleProgramKey, gpu::PipelinePointer> _simplePrograms;
|
||||
|
||||
gpu::ShaderPointer _simpleOpaqueWebBrowserShader;
|
||||
gpu::PipelinePointer _simpleOpaqueWebBrowserPipeline;
|
||||
|
@ -435,6 +467,11 @@ private:
|
|||
gpu::PipelinePointer _simpleOpaqueWebBrowserOverlayPipeline;
|
||||
gpu::ShaderPointer _simpleTransparentWebBrowserOverlayShader;
|
||||
gpu::PipelinePointer _simpleTransparentWebBrowserOverlayPipeline;
|
||||
|
||||
static render::ShapePipelinePointer getShapePipeline(bool textured = false, bool transparent = false, bool culled = true,
|
||||
bool unlit = false, bool depthBias = false);
|
||||
static render::ShapePipelinePointer getFadingShapePipeline(bool textured = false, bool transparent = false, bool culled = true,
|
||||
bool unlit = false, bool depthBias = false);
|
||||
};
|
||||
|
||||
#endif // hifi_GeometryCache_h
|
||||
|
|
|
@ -318,6 +318,7 @@ template <> const ShapeKey shapeGetShapeKey(const ModelMeshPartPayload::Pointer&
|
|||
template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args) {
|
||||
return payload->render(args);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int _meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform) :
|
||||
|
@ -327,6 +328,7 @@ ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int _meshIndex, i
|
|||
assert(model && model->isLoaded());
|
||||
_model = model;
|
||||
auto& modelMesh = model->getGeometry()->getMeshes().at(_meshIndex);
|
||||
|
||||
updateMeshPart(modelMesh, partIndex);
|
||||
|
||||
updateTransform(transform, offsetTransform);
|
||||
|
@ -390,10 +392,6 @@ ItemKey ModelMeshPartPayload::getKey() const {
|
|||
builder.withTransparent();
|
||||
}
|
||||
}
|
||||
|
||||
if (_fadeState != FADE_COMPLETE) {
|
||||
builder.withTransparent();
|
||||
}
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
@ -465,7 +463,7 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const {
|
|||
ShapeKey::Builder builder;
|
||||
builder.withMaterial();
|
||||
|
||||
if (isTranslucent || _fadeState != FADE_COMPLETE) {
|
||||
if (isTranslucent) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
if (hasTangents) {
|
||||
|
@ -510,9 +508,8 @@ void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) {
|
|||
}
|
||||
}
|
||||
|
||||
if (_fadeState != FADE_COMPLETE) {
|
||||
batch._glColor4f(1.0f, 1.0f, 1.0f, computeFadeAlpha());
|
||||
} else if (!_hasColorAttrib) {
|
||||
// TODO: Get rid of that extra call
|
||||
if (!_hasColorAttrib) {
|
||||
batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
@ -525,45 +522,17 @@ void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline:
|
|||
batch.setModelTransform(_transform);
|
||||
}
|
||||
|
||||
float ModelMeshPartPayload::computeFadeAlpha() {
|
||||
if (_fadeState == FADE_WAITING_TO_START) {
|
||||
return 0.0f;
|
||||
}
|
||||
float fadeAlpha = 1.0f;
|
||||
const float INV_FADE_PERIOD = 1.0f / (float)(1 * USECS_PER_SECOND);
|
||||
float fraction = (float)(usecTimestampNow() - _fadeStartTime) * INV_FADE_PERIOD;
|
||||
if (fraction < 1.0f) {
|
||||
fadeAlpha = Interpolate::simpleNonLinearBlend(fraction);
|
||||
}
|
||||
if (fadeAlpha >= 1.0f) {
|
||||
_fadeState = FADE_COMPLETE;
|
||||
// when fade-in completes we flag model for one last "render item update"
|
||||
ModelPointer model = _model.lock();
|
||||
if (model) {
|
||||
model->setRenderItemsNeedUpdate();
|
||||
}
|
||||
return 1.0f;
|
||||
}
|
||||
return Interpolate::simpleNonLinearBlend(fadeAlpha);
|
||||
}
|
||||
|
||||
void ModelMeshPartPayload::render(RenderArgs* args) {
|
||||
PerformanceTimer perfTimer("ModelMeshPartPayload::render");
|
||||
|
||||
ModelPointer model = _model.lock();
|
||||
if (!model || !model->addedToScene() || !model->isVisible()) {
|
||||
if (!model || !model->isAddedToScene() || !model->isVisible()) {
|
||||
return; // bail asap
|
||||
}
|
||||
|
||||
if (_fadeState == FADE_WAITING_TO_START) {
|
||||
if (_state == WAITING_TO_START) {
|
||||
if (model->isLoaded()) {
|
||||
// FIXME as far as I can tell this is the ONLY reason render-util depends on entities.
|
||||
if (EntityItem::getEntitiesShouldFadeFunction()()) {
|
||||
_fadeStartTime = usecTimestampNow();
|
||||
_fadeState = FADE_IN_PROGRESS;
|
||||
} else {
|
||||
_fadeState = FADE_COMPLETE;
|
||||
}
|
||||
_state = STARTED;
|
||||
model->setRenderItemsNeedUpdate();
|
||||
} else {
|
||||
return;
|
||||
|
|
|
@ -23,10 +23,6 @@
|
|||
|
||||
#include "Model.h"
|
||||
|
||||
const uint8_t FADE_WAITING_TO_START = 0;
|
||||
const uint8_t FADE_IN_PROGRESS = 1;
|
||||
const uint8_t FADE_COMPLETE = 2;
|
||||
|
||||
class Model;
|
||||
|
||||
class MeshPartPayload {
|
||||
|
@ -95,8 +91,6 @@ public:
|
|||
const Transform& boundTransform,
|
||||
const gpu::BufferPointer& buffer);
|
||||
|
||||
float computeFadeAlpha();
|
||||
|
||||
// Render Item interface
|
||||
render::ItemKey getKey() const override;
|
||||
int getLayer() const;
|
||||
|
@ -122,8 +116,13 @@ public:
|
|||
bool _materialNeedsUpdate { true };
|
||||
|
||||
private:
|
||||
quint64 _fadeStartTime { 0 };
|
||||
uint8_t _fadeState { FADE_WAITING_TO_START };
|
||||
|
||||
enum State : uint8_t {
|
||||
WAITING_TO_START = 0,
|
||||
STARTED = 1,
|
||||
};
|
||||
|
||||
mutable State _state { WAITING_TO_START } ;
|
||||
};
|
||||
|
||||
namespace render {
|
||||
|
|
|
@ -116,6 +116,7 @@ public:
|
|||
const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& normals);
|
||||
|
||||
bool isLoaded() const { return (bool)_renderGeometry && _renderGeometry->isGeometryLoaded(); }
|
||||
bool isAddedToScene() const { return _addedToScene; }
|
||||
|
||||
void setIsWireframe(bool isWireframe) { _isWireframe = isWireframe; }
|
||||
bool isWireframe() const { return _isWireframe; }
|
||||
|
@ -267,7 +268,6 @@ signals:
|
|||
void setCollisionModelURLFinished(bool success);
|
||||
|
||||
protected:
|
||||
bool addedToScene() const { return _addedToScene; }
|
||||
|
||||
void setBlendshapeCoefficients(const QVector<float>& coefficients) { _blendshapeCoefficients = coefficients; }
|
||||
const QVector<float>& getBlendshapeCoefficients() const { return _blendshapeCoefficients; }
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "FramebufferCache.h"
|
||||
#include "TextureCache.h"
|
||||
#include "ZoneRenderer.h"
|
||||
#include "FadeEffect.h"
|
||||
|
||||
#include "AmbientOcclusionEffect.h"
|
||||
#include "AntialiasingEffect.h"
|
||||
|
@ -45,24 +46,35 @@
|
|||
|
||||
using namespace render;
|
||||
extern void initOverlay3DPipelines(render::ShapePlumber& plumber, bool depthTest = false);
|
||||
extern void initDeferredPipelines(render::ShapePlumber& plumber);
|
||||
extern void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter);
|
||||
|
||||
RenderDeferredTask::RenderDeferredTask() {
|
||||
DependencyManager::set<FadeEffect>();
|
||||
}
|
||||
|
||||
void RenderDeferredTask::configure(const Config& config)
|
||||
{
|
||||
}
|
||||
|
||||
void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output) {
|
||||
auto items = input.get<Input>();
|
||||
const auto& items = input.get<Input>();
|
||||
auto fadeEffect = DependencyManager::get<FadeEffect>();
|
||||
|
||||
// Prepare the ShapePipelines
|
||||
ShapePlumberPointer shapePlumber = std::make_shared<ShapePlumber>();
|
||||
initDeferredPipelines(*shapePlumber);
|
||||
initDeferredPipelines(*shapePlumber, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter());
|
||||
|
||||
// Extract opaques / transparents / lights / metas / overlays / background
|
||||
const auto opaques = items[RenderFetchCullSortTask::OPAQUE_SHAPE];
|
||||
const auto transparents = items[RenderFetchCullSortTask::TRANSPARENT_SHAPE];
|
||||
const auto lights = items[RenderFetchCullSortTask::LIGHT];
|
||||
const auto metas = items[RenderFetchCullSortTask::META];
|
||||
const auto overlayOpaques = items[RenderFetchCullSortTask::OVERLAY_OPAQUE_SHAPE];
|
||||
const auto overlayTransparents = items[RenderFetchCullSortTask::OVERLAY_TRANSPARENT_SHAPE];
|
||||
const auto background = items[RenderFetchCullSortTask::BACKGROUND];
|
||||
const auto spatialSelection = items[RenderFetchCullSortTask::SPATIAL_SELECTION];
|
||||
const auto& opaques = items.get0()[RenderFetchCullSortTask::OPAQUE_SHAPE];
|
||||
const auto& transparents = items.get0()[RenderFetchCullSortTask::TRANSPARENT_SHAPE];
|
||||
const auto& lights = items.get0()[RenderFetchCullSortTask::LIGHT];
|
||||
const auto& metas = items.get0()[RenderFetchCullSortTask::META];
|
||||
const auto& overlayOpaques = items.get0()[RenderFetchCullSortTask::OVERLAY_OPAQUE_SHAPE];
|
||||
const auto& overlayTransparents = items.get0()[RenderFetchCullSortTask::OVERLAY_TRANSPARENT_SHAPE];
|
||||
//const auto& background = items.get0()[RenderFetchCullSortTask::BACKGROUND];
|
||||
const auto& spatialSelection = items[1];
|
||||
|
||||
fadeEffect->build(task, opaques);
|
||||
|
||||
// Filter the non antialiaased overlays
|
||||
const int LAYER_NO_AA = 3;
|
||||
|
@ -77,7 +89,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
|
||||
const auto opaqueRangeTimer = task.addJob<BeginGPURangeTimer>("BeginOpaqueRangeTimer", "DrawOpaques");
|
||||
|
||||
const auto prepareDeferredInputs = PrepareDeferred::Inputs(primaryFramebuffer, lightingModel).hasVarying();
|
||||
const auto prepareDeferredInputs = PrepareDeferred::Inputs(primaryFramebuffer, lightingModel).asVarying();
|
||||
const auto prepareDeferredOutputs = task.addJob<PrepareDeferred>("PrepareDeferred", prepareDeferredInputs);
|
||||
const auto deferredFramebuffer = prepareDeferredOutputs.getN<PrepareDeferred::Outputs>(0);
|
||||
const auto lightingFramebuffer = prepareDeferredOutputs.getN<PrepareDeferred::Outputs>(1);
|
||||
|
@ -86,7 +98,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
task.addJob<PrepareStencil>("PrepareStencil", primaryFramebuffer);
|
||||
|
||||
// Render opaque objects in DeferredBuffer
|
||||
const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel).hasVarying();
|
||||
const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel).asVarying();
|
||||
task.addJob<DrawStateSortDeferred>("DrawOpaqueDeferred", opaqueInputs, shapePlumber);
|
||||
|
||||
task.addJob<EndGPURangeTimer>("OpaqueRangeTimer", opaqueRangeTimer);
|
||||
|
@ -95,12 +107,12 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
// Opaque all rendered
|
||||
|
||||
// Linear Depth Pass
|
||||
const auto linearDepthPassInputs = LinearDepthPass::Inputs(deferredFrameTransform, deferredFramebuffer).hasVarying();
|
||||
const auto linearDepthPassInputs = LinearDepthPass::Inputs(deferredFrameTransform, deferredFramebuffer).asVarying();
|
||||
const auto linearDepthPassOutputs = task.addJob<LinearDepthPass>("LinearDepth", linearDepthPassInputs);
|
||||
const auto linearDepthTarget = linearDepthPassOutputs.getN<LinearDepthPass::Outputs>(0);
|
||||
|
||||
// Curvature pass
|
||||
const auto surfaceGeometryPassInputs = SurfaceGeometryPass::Inputs(deferredFrameTransform, deferredFramebuffer, linearDepthTarget).hasVarying();
|
||||
const auto surfaceGeometryPassInputs = SurfaceGeometryPass::Inputs(deferredFrameTransform, deferredFramebuffer, linearDepthTarget).asVarying();
|
||||
const auto surfaceGeometryPassOutputs = task.addJob<SurfaceGeometryPass>("SurfaceGeometry", surfaceGeometryPassInputs);
|
||||
const auto surfaceGeometryFramebuffer = surfaceGeometryPassOutputs.getN<SurfaceGeometryPass::Outputs>(0);
|
||||
const auto curvatureFramebuffer = surfaceGeometryPassOutputs.getN<SurfaceGeometryPass::Outputs>(1);
|
||||
|
@ -111,7 +123,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
const auto scatteringResource = task.addJob<SubsurfaceScattering>("Scattering");
|
||||
|
||||
// AO job
|
||||
const auto ambientOcclusionInputs = AmbientOcclusionEffect::Inputs(deferredFrameTransform, deferredFramebuffer, linearDepthTarget).hasVarying();
|
||||
const auto ambientOcclusionInputs = AmbientOcclusionEffect::Inputs(deferredFrameTransform, deferredFramebuffer, linearDepthTarget).asVarying();
|
||||
const auto ambientOcclusionOutputs = task.addJob<AmbientOcclusionEffect>("AmbientOcclusion", ambientOcclusionInputs);
|
||||
const auto ambientOcclusionFramebuffer = ambientOcclusionOutputs.getN<AmbientOcclusionEffect::Outputs>(0);
|
||||
const auto ambientOcclusionUniforms = ambientOcclusionOutputs.getN<AmbientOcclusionEffect::Outputs>(1);
|
||||
|
@ -125,13 +137,13 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
|
||||
// Light Clustering
|
||||
// Create the cluster grid of lights, cpu job for now
|
||||
const auto lightClusteringPassInputs = LightClusteringPass::Inputs(deferredFrameTransform, lightingModel, linearDepthTarget).hasVarying();
|
||||
const auto lightClusteringPassInputs = LightClusteringPass::Inputs(deferredFrameTransform, lightingModel, linearDepthTarget).asVarying();
|
||||
const auto lightClusters = task.addJob<LightClusteringPass>("LightClustering", lightClusteringPassInputs);
|
||||
|
||||
|
||||
// DeferredBuffer is complete, now let's shade it into the LightingBuffer
|
||||
const auto deferredLightingInputs = RenderDeferred::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel,
|
||||
surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, scatteringResource, lightClusters).hasVarying();
|
||||
surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, scatteringResource, lightClusters).asVarying();
|
||||
|
||||
task.addJob<RenderDeferred>("RenderDeferred", deferredLightingInputs);
|
||||
|
||||
|
@ -139,12 +151,12 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
task.addJob<DrawBackgroundStage>("DrawBackgroundDeferred", lightingModel);
|
||||
|
||||
// Render transparent objects forward in LightingBuffer
|
||||
const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel).hasVarying();
|
||||
const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel).asVarying();
|
||||
task.addJob<DrawDeferred>("DrawTransparentDeferred", transparentsInputs, shapePlumber);
|
||||
|
||||
// LIght Cluster Grid Debuging job
|
||||
{
|
||||
const auto debugLightClustersInputs = DebugLightClusters::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, linearDepthTarget, lightClusters).hasVarying();
|
||||
const auto debugLightClustersInputs = DebugLightClusters::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, linearDepthTarget, lightClusters).asVarying();
|
||||
task.addJob<DebugLightClusters>("DebugLightClusters", debugLightClustersInputs);
|
||||
}
|
||||
|
||||
|
@ -164,8 +176,8 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
}
|
||||
|
||||
// Overlays
|
||||
const auto overlayOpaquesInputs = DrawOverlay3D::Inputs(overlayOpaques, lightingModel).hasVarying();
|
||||
const auto overlayTransparentsInputs = DrawOverlay3D::Inputs(overlayTransparents, lightingModel).hasVarying();
|
||||
const auto overlayOpaquesInputs = DrawOverlay3D::Inputs(overlayOpaques, lightingModel).asVarying();
|
||||
const auto overlayTransparentsInputs = DrawOverlay3D::Inputs(overlayTransparents, lightingModel).asVarying();
|
||||
task.addJob<DrawOverlay3D>("DrawOverlay3DOpaque", overlayOpaquesInputs, true);
|
||||
task.addJob<DrawOverlay3D>("DrawOverlay3DTransparent", overlayTransparentsInputs, false);
|
||||
|
||||
|
@ -181,10 +193,10 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
task.addJob<DebugDeferredBuffer>("DebugDeferredBuffer", debugFramebuffers);
|
||||
|
||||
const auto debugSubsurfaceScatteringInputs = DebugSubsurfaceScattering::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel,
|
||||
surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, scatteringResource).hasVarying();
|
||||
surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, scatteringResource).asVarying();
|
||||
task.addJob<DebugSubsurfaceScattering>("DebugScattering", debugSubsurfaceScatteringInputs);
|
||||
|
||||
const auto debugAmbientOcclusionInputs = DebugAmbientOcclusion::Inputs(deferredFrameTransform, deferredFramebuffer, linearDepthTarget, ambientOcclusionUniforms).hasVarying();
|
||||
const auto debugAmbientOcclusionInputs = DebugAmbientOcclusion::Inputs(deferredFrameTransform, deferredFramebuffer, linearDepthTarget, ambientOcclusionUniforms).asVarying();
|
||||
task.addJob<DebugAmbientOcclusion>("DebugAmbientOcclusion", debugAmbientOcclusionInputs);
|
||||
|
||||
// Scene Octree Debugging job
|
||||
|
@ -209,7 +221,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
task.addJob<Antialiasing>("Antialiasing", primaryFramebuffer);
|
||||
|
||||
// Draw 2DWeb non AA
|
||||
const auto nonAAOverlaysInputs = DrawOverlay3D::Inputs(nonAAOverlays, lightingModel).hasVarying();
|
||||
const auto nonAAOverlaysInputs = DrawOverlay3D::Inputs(nonAAOverlays, lightingModel).asVarying();
|
||||
task.addJob<DrawOverlay3D>("Draw2DWebSurfaces", nonAAOverlaysInputs, false);
|
||||
|
||||
task.addJob<EndGPURangeTimer>("ToneAndPostRangeTimer", toneAndPostRangeTimer);
|
||||
|
@ -269,6 +281,7 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs&
|
|||
if (lightingModel->isWireframeEnabled()) {
|
||||
keyBuilder.withWireframe();
|
||||
}
|
||||
|
||||
ShapeKey globalKey = keyBuilder.build();
|
||||
args->_globalShapeKey = globalKey._flags.to_ulong();
|
||||
|
||||
|
@ -310,11 +323,12 @@ void DrawStateSortDeferred::run(const RenderContextPointer& renderContext, const
|
|||
// Setup lighting model for all items;
|
||||
batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer());
|
||||
|
||||
// From the lighting model define a global shapKey ORED with individiual keys
|
||||
// From the lighting model define a global shapeKey ORED with individiual keys
|
||||
ShapeKey::Builder keyBuilder;
|
||||
if (lightingModel->isWireframeEnabled()) {
|
||||
keyBuilder.withWireframe();
|
||||
}
|
||||
|
||||
ShapeKey globalKey = keyBuilder.build();
|
||||
args->_globalShapeKey = globalKey._flags.to_ulong();
|
||||
|
||||
|
|
|
@ -44,12 +44,11 @@ public:
|
|||
protected:
|
||||
};
|
||||
|
||||
|
||||
class DrawConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY newStats)
|
||||
|
||||
Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty)
|
||||
|
||||
public:
|
||||
|
||||
int getNumDrawn() { return _numDrawn; }
|
||||
|
@ -163,14 +162,34 @@ public:
|
|||
void run(const render::RenderContextPointer& renderContext, const gpu::FramebufferPointer& srcFramebuffer);
|
||||
};
|
||||
|
||||
class RenderDeferredTaskConfig : public render::Task::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(float fadeScale MEMBER fadeScale NOTIFY dirty)
|
||||
Q_PROPERTY(float fadeDuration MEMBER fadeDuration NOTIFY dirty)
|
||||
Q_PROPERTY(bool debugFade MEMBER debugFade NOTIFY dirty)
|
||||
Q_PROPERTY(float debugFadePercent MEMBER debugFadePercent NOTIFY dirty)
|
||||
public:
|
||||
float fadeScale{ 0.5f };
|
||||
float fadeDuration{ 3.0f };
|
||||
float debugFadePercent{ 0.f };
|
||||
bool debugFade{ false };
|
||||
|
||||
signals:
|
||||
void dirty();
|
||||
|
||||
};
|
||||
|
||||
class RenderDeferredTask {
|
||||
public:
|
||||
using Input = RenderFetchCullSortTask::Output;
|
||||
using JobModel = render::Task::ModelI<RenderDeferredTask, Input>;
|
||||
using Config = RenderDeferredTaskConfig;
|
||||
using JobModel = render::Task::ModelI<RenderDeferredTask, Input, Config>;
|
||||
|
||||
RenderDeferredTask() {}
|
||||
RenderDeferredTask();
|
||||
|
||||
void configure(const Config& config);
|
||||
void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs);
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_RenderDeferredTask_h
|
||||
|
|
|
@ -36,14 +36,14 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend
|
|||
initForwardPipelines(*shapePlumber);
|
||||
|
||||
// Extract opaques / transparents / lights / metas / overlays / background
|
||||
const auto opaques = items[RenderFetchCullSortTask::OPAQUE_SHAPE];
|
||||
const auto transparents = items[RenderFetchCullSortTask::TRANSPARENT_SHAPE];
|
||||
const auto lights = items[RenderFetchCullSortTask::LIGHT];
|
||||
const auto metas = items[RenderFetchCullSortTask::META];
|
||||
const auto overlayOpaques = items[RenderFetchCullSortTask::OVERLAY_OPAQUE_SHAPE];
|
||||
const auto overlayTransparents = items[RenderFetchCullSortTask::OVERLAY_TRANSPARENT_SHAPE];
|
||||
const auto background = items[RenderFetchCullSortTask::BACKGROUND];
|
||||
const auto spatialSelection = items[RenderFetchCullSortTask::SPATIAL_SELECTION];
|
||||
const auto& opaques = items.get0()[RenderFetchCullSortTask::OPAQUE_SHAPE];
|
||||
// const auto& transparents = items.get0()[RenderFetchCullSortTask::TRANSPARENT_SHAPE];
|
||||
// const auto& lights = items.get0()[RenderFetchCullSortTask::LIGHT];
|
||||
// const auto& metas = items.get0()[RenderFetchCullSortTask::META];
|
||||
// const auto& overlayOpaques = items.get0()[RenderFetchCullSortTask::OVERLAY_OPAQUE_SHAPE];
|
||||
// const auto& overlayTransparents = items.get0()[RenderFetchCullSortTask::OVERLAY_TRANSPARENT_SHAPE];
|
||||
const auto& background = items.get0()[RenderFetchCullSortTask::BACKGROUND];
|
||||
// const auto& spatialSelection = items[1];
|
||||
|
||||
const auto framebuffer = task.addJob<PrepareFramebuffer>("PrepareFramebuffer");
|
||||
|
||||
|
|
|
@ -29,12 +29,25 @@
|
|||
#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"
|
||||
#include "simple_textured_frag.h"
|
||||
#include "simple_textured_unlit_frag.h"
|
||||
#include "simple_transparent_textured_frag.h"
|
||||
#include "simple_transparent_textured_unlit_frag.h"
|
||||
|
||||
#include "simple_fade_vert.h"
|
||||
#include "simple_textured_fade_frag.h"
|
||||
#include "simple_textured_unlit_fade_frag.h"
|
||||
#include "simple_transparent_textured_fade_frag.h"
|
||||
#include "simple_transparent_textured_unlit_fade_frag.h"
|
||||
|
||||
#include "model_frag.h"
|
||||
#include "model_unlit_frag.h"
|
||||
#include "model_shadow_frag.h"
|
||||
|
@ -42,6 +55,16 @@
|
|||
#include "model_normal_specular_map_frag.h"
|
||||
#include "model_specular_map_frag.h"
|
||||
|
||||
#include "model_fade_vert.h"
|
||||
#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"
|
||||
#include "model_specular_map_fade_frag.h"
|
||||
|
||||
#include "forward_model_frag.h"
|
||||
#include "forward_model_unlit_frag.h"
|
||||
#include "forward_model_normal_map_frag.h"
|
||||
|
@ -55,6 +78,13 @@
|
|||
#include "model_translucent_frag.h"
|
||||
#include "model_translucent_unlit_frag.h"
|
||||
|
||||
#include "model_lightmap_fade_frag.h"
|
||||
#include "model_lightmap_normal_map_fade_frag.h"
|
||||
#include "model_lightmap_normal_specular_map_fade_frag.h"
|
||||
#include "model_lightmap_specular_map_fade_frag.h"
|
||||
#include "model_translucent_fade_frag.h"
|
||||
#include "model_translucent_unlit_fade_frag.h"
|
||||
|
||||
#include "overlay3D_vert.h"
|
||||
#include "overlay3D_frag.h"
|
||||
#include "overlay3D_model_frag.h"
|
||||
|
@ -70,11 +100,12 @@ using namespace render;
|
|||
using namespace std::placeholders;
|
||||
|
||||
void initOverlay3DPipelines(ShapePlumber& plumber, bool depthTest = false);
|
||||
void initDeferredPipelines(ShapePlumber& plumber);
|
||||
void initDeferredPipelines(ShapePlumber& plumber, const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter);
|
||||
void initForwardPipelines(ShapePlumber& plumber);
|
||||
|
||||
void addPlumberPipeline(ShapePlumber& plumber,
|
||||
const ShapeKey& key, const gpu::ShaderPointer& vertex, const gpu::ShaderPointer& pixel);
|
||||
const ShapeKey& key, const gpu::ShaderPointer& vertex, const gpu::ShaderPointer& pixel,
|
||||
const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter);
|
||||
|
||||
void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderArgs* args);
|
||||
void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderArgs* args);
|
||||
|
@ -144,7 +175,7 @@ void initOverlay3DPipelines(ShapePlumber& plumber, bool depthTest) {
|
|||
}
|
||||
}
|
||||
|
||||
void initDeferredPipelines(render::ShapePlumber& plumber) {
|
||||
void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter) {
|
||||
// Vertex shaders
|
||||
auto simpleVertex = gpu::Shader::createVertex(std::string(simple_vert));
|
||||
auto modelVertex = gpu::Shader::createVertex(std::string(model_vert));
|
||||
|
@ -155,6 +186,16 @@ void initDeferredPipelines(render::ShapePlumber& plumber) {
|
|||
auto skinModelVertex = gpu::Shader::createVertex(std::string(skin_model_vert));
|
||||
auto skinModelNormalMapVertex = gpu::Shader::createVertex(std::string(skin_model_normal_map_vert));
|
||||
auto skinModelShadowVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert));
|
||||
auto modelLightmapFadeVertex = gpu::Shader::createVertex(std::string(model_lightmap_fade_vert));
|
||||
auto modelLightmapNormalMapFadeVertex = gpu::Shader::createVertex(std::string(model_lightmap_normal_map_fade_vert));
|
||||
auto skinModelFadeVertex = gpu::Shader::createVertex(std::string(skin_model_fade_vert));
|
||||
auto skinModelNormalMapFadeVertex = gpu::Shader::createVertex(std::string(skin_model_normal_map_fade_vert));
|
||||
|
||||
auto modelFadeVertex = gpu::Shader::createVertex(std::string(model_fade_vert));
|
||||
auto modelNormalMapFadeVertex = gpu::Shader::createVertex(std::string(model_normal_map_fade_vert));
|
||||
auto simpleFadeVertex = gpu::Shader::createVertex(std::string(simple_fade_vert));
|
||||
auto modelShadowFadeVertex = gpu::Shader::createVertex(std::string(model_shadow_fade_vert));
|
||||
auto skinModelShadowFadeVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_fade_vert));
|
||||
|
||||
// Pixel shaders
|
||||
auto simplePixel = gpu::Shader::createPixel(std::string(simple_textured_frag));
|
||||
|
@ -173,104 +214,220 @@ void initDeferredPipelines(render::ShapePlumber& plumber) {
|
|||
auto modelLightmapNormalMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_map_frag));
|
||||
auto modelLightmapSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_specular_map_frag));
|
||||
auto modelLightmapNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_specular_map_frag));
|
||||
auto modelLightmapFadePixel = gpu::Shader::createPixel(std::string(model_lightmap_fade_frag));
|
||||
auto modelLightmapNormalMapFadePixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_map_fade_frag));
|
||||
auto modelLightmapSpecularMapFadePixel = gpu::Shader::createPixel(std::string(model_lightmap_specular_map_fade_frag));
|
||||
auto modelLightmapNormalSpecularMapFadePixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_specular_map_fade_frag));
|
||||
|
||||
auto modelFadePixel = gpu::Shader::createPixel(std::string(model_fade_frag));
|
||||
auto modelUnlitFadePixel = gpu::Shader::createPixel(std::string(model_unlit_fade_frag));
|
||||
auto modelNormalMapFadePixel = gpu::Shader::createPixel(std::string(model_normal_map_fade_frag));
|
||||
auto modelSpecularMapFadePixel = gpu::Shader::createPixel(std::string(model_specular_map_fade_frag));
|
||||
auto modelNormalSpecularMapFadePixel = gpu::Shader::createPixel(std::string(model_normal_specular_map_fade_frag));
|
||||
auto modelShadowFadePixel = gpu::Shader::createPixel(std::string(model_shadow_fade_frag));
|
||||
auto modelTranslucentFadePixel = gpu::Shader::createPixel(std::string(model_translucent_fade_frag));
|
||||
auto modelTranslucentUnlitFadePixel = gpu::Shader::createPixel(std::string(model_translucent_unlit_fade_frag));
|
||||
auto simpleFadePixel = gpu::Shader::createPixel(std::string(simple_textured_fade_frag));
|
||||
auto simpleUnlitFadePixel = gpu::Shader::createPixel(std::string(simple_textured_unlit_fade_frag));
|
||||
auto simpleTranslucentFadePixel = gpu::Shader::createPixel(std::string(simple_transparent_textured_fade_frag));
|
||||
auto simpleTranslucentUnlitFadePixel = gpu::Shader::createPixel(std::string(simple_transparent_textured_unlit_fade_frag));
|
||||
|
||||
using Key = render::ShapeKey;
|
||||
auto addPipeline = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3);
|
||||
auto addPipeline = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3, _4, _5);
|
||||
// TODO: Refactor this to use a filter
|
||||
// Opaques
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial(),
|
||||
modelVertex, modelPixel);
|
||||
modelVertex, modelPixel, nullptr, nullptr);
|
||||
addPipeline(
|
||||
Key::Builder(),
|
||||
simpleVertex, simplePixel);
|
||||
simpleVertex, simplePixel, nullptr, nullptr);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withUnlit(),
|
||||
modelVertex, modelUnlitPixel);
|
||||
modelVertex, modelUnlitPixel, nullptr, nullptr);
|
||||
addPipeline(
|
||||
Key::Builder().withUnlit(),
|
||||
simpleVertex, simpleUnlitPixel);
|
||||
simpleVertex, simpleUnlitPixel, nullptr, nullptr);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withTangents(),
|
||||
modelNormalMapVertex, modelNormalMapPixel);
|
||||
modelNormalMapVertex, modelNormalMapPixel, nullptr, nullptr);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withSpecular(),
|
||||
modelVertex, modelSpecularMapPixel);
|
||||
modelVertex, modelSpecularMapPixel, nullptr, nullptr);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withTangents().withSpecular(),
|
||||
modelNormalMapVertex, modelNormalSpecularMapPixel);
|
||||
modelNormalMapVertex, modelNormalSpecularMapPixel, nullptr, nullptr);
|
||||
// Same thing but with Fade on
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withFade(),
|
||||
modelFadeVertex, modelFadePixel, batchSetter, itemSetter);
|
||||
addPipeline(
|
||||
Key::Builder().withFade(),
|
||||
simpleFadeVertex, simpleFadePixel, batchSetter, itemSetter);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withUnlit().withFade(),
|
||||
modelFadeVertex, modelUnlitFadePixel, batchSetter, itemSetter);
|
||||
addPipeline(
|
||||
Key::Builder().withUnlit().withFade(),
|
||||
simpleFadeVertex, simpleUnlitFadePixel, batchSetter, itemSetter);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withTangents().withFade(),
|
||||
modelNormalMapFadeVertex, modelNormalMapFadePixel, batchSetter, itemSetter);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withSpecular().withFade(),
|
||||
modelFadeVertex, modelSpecularMapFadePixel, batchSetter, itemSetter);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withTangents().withSpecular().withFade(),
|
||||
modelNormalMapFadeVertex, modelNormalSpecularMapFadePixel, batchSetter, itemSetter);
|
||||
|
||||
// Translucents
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withTranslucent(),
|
||||
modelVertex, modelTranslucentPixel);
|
||||
modelVertex, modelTranslucentPixel, nullptr, nullptr);
|
||||
addPipeline(
|
||||
Key::Builder().withTranslucent(),
|
||||
simpleVertex, simpleTranslucentPixel);
|
||||
simpleVertex, simpleTranslucentPixel, nullptr, nullptr);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withTranslucent().withUnlit(),
|
||||
modelVertex, modelTranslucentUnlitPixel);
|
||||
modelVertex, modelTranslucentUnlitPixel, nullptr, nullptr);
|
||||
addPipeline(
|
||||
Key::Builder().withTranslucent().withUnlit(),
|
||||
simpleVertex, simpleTranslucentUnlitPixel);
|
||||
simpleVertex, simpleTranslucentUnlitPixel, nullptr, nullptr);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withTranslucent().withTangents(),
|
||||
modelNormalMapVertex, modelTranslucentPixel);
|
||||
modelNormalMapVertex, modelTranslucentPixel, nullptr, nullptr);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withTranslucent().withSpecular(),
|
||||
modelVertex, modelTranslucentPixel);
|
||||
modelVertex, modelTranslucentPixel, nullptr, nullptr);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withTranslucent().withTangents().withSpecular(),
|
||||
modelNormalMapVertex, modelTranslucentPixel);
|
||||
modelNormalMapVertex, modelTranslucentPixel, nullptr, nullptr);
|
||||
addPipeline(
|
||||
// FIXME: Ignore lightmap for translucents meshpart
|
||||
Key::Builder().withMaterial().withTranslucent().withLightmap(),
|
||||
modelVertex, modelTranslucentPixel);
|
||||
modelVertex, modelTranslucentPixel, nullptr, nullptr);
|
||||
// Same thing but with Fade on
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withTranslucent().withFade(),
|
||||
modelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter);
|
||||
addPipeline(
|
||||
Key::Builder().withTranslucent().withFade(),
|
||||
simpleFadeVertex, simpleTranslucentFadePixel, batchSetter, itemSetter);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withTranslucent().withUnlit().withFade(),
|
||||
modelFadeVertex, modelTranslucentUnlitFadePixel, batchSetter, itemSetter);
|
||||
addPipeline(
|
||||
Key::Builder().withTranslucent().withUnlit().withFade(),
|
||||
simpleFadeVertex, simpleTranslucentUnlitFadePixel, batchSetter, itemSetter);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withTranslucent().withTangents().withFade(),
|
||||
modelNormalMapFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withTranslucent().withSpecular().withFade(),
|
||||
modelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withTranslucent().withTangents().withSpecular().withFade(),
|
||||
modelNormalMapFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter);
|
||||
addPipeline(
|
||||
// FIXME: Ignore lightmap for translucents meshpart
|
||||
Key::Builder().withMaterial().withTranslucent().withLightmap().withFade(),
|
||||
modelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter);
|
||||
|
||||
// Lightmapped
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withLightmap(),
|
||||
modelLightmapVertex, modelLightmapPixel);
|
||||
modelLightmapVertex, modelLightmapPixel, nullptr, nullptr);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withLightmap().withTangents(),
|
||||
modelLightmapNormalMapVertex, modelLightmapNormalMapPixel);
|
||||
modelLightmapNormalMapVertex, modelLightmapNormalMapPixel, nullptr, nullptr);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withLightmap().withSpecular(),
|
||||
modelLightmapVertex, modelLightmapSpecularMapPixel);
|
||||
modelLightmapVertex, modelLightmapSpecularMapPixel, nullptr, nullptr);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withLightmap().withTangents().withSpecular(),
|
||||
modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel);
|
||||
modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel, nullptr, nullptr);
|
||||
// Same thing but with Fade on
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withLightmap().withFade(),
|
||||
modelLightmapFadeVertex, modelLightmapFadePixel, batchSetter, itemSetter);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withLightmap().withTangents().withFade(),
|
||||
modelLightmapNormalMapFadeVertex, modelLightmapNormalMapFadePixel, batchSetter, itemSetter);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withLightmap().withSpecular().withFade(),
|
||||
modelLightmapFadeVertex, modelLightmapSpecularMapFadePixel, batchSetter, itemSetter);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withLightmap().withTangents().withSpecular().withFade(),
|
||||
modelLightmapNormalMapFadeVertex, modelLightmapNormalSpecularMapFadePixel, batchSetter, itemSetter);
|
||||
|
||||
// Skinned
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withSkinned(),
|
||||
skinModelVertex, modelPixel);
|
||||
skinModelVertex, modelPixel, nullptr, nullptr);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withSkinned().withTangents(),
|
||||
skinModelNormalMapVertex, modelNormalMapPixel);
|
||||
skinModelNormalMapVertex, modelNormalMapPixel, nullptr, nullptr);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withSkinned().withSpecular(),
|
||||
skinModelVertex, modelSpecularMapPixel);
|
||||
skinModelVertex, modelSpecularMapPixel, nullptr, nullptr);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withSkinned().withTangents().withSpecular(),
|
||||
skinModelNormalMapVertex, modelNormalSpecularMapPixel);
|
||||
skinModelNormalMapVertex, modelNormalSpecularMapPixel, nullptr, nullptr);
|
||||
// Same thing but with Fade on
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withSkinned().withFade(),
|
||||
skinModelFadeVertex, modelFadePixel, batchSetter, itemSetter);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withSkinned().withTangents().withFade(),
|
||||
skinModelNormalMapFadeVertex, modelNormalMapFadePixel, batchSetter, itemSetter);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withSkinned().withSpecular().withFade(),
|
||||
skinModelFadeVertex, modelSpecularMapFadePixel, batchSetter, itemSetter);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withSkinned().withTangents().withSpecular().withFade(),
|
||||
skinModelNormalMapFadeVertex, modelNormalSpecularMapFadePixel, batchSetter, itemSetter);
|
||||
|
||||
// Skinned and Translucent
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withSkinned().withTranslucent(),
|
||||
skinModelVertex, modelTranslucentPixel);
|
||||
skinModelVertex, modelTranslucentPixel, nullptr, nullptr);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents(),
|
||||
skinModelNormalMapVertex, modelTranslucentPixel);
|
||||
skinModelNormalMapVertex, modelTranslucentPixel, nullptr, nullptr);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withSkinned().withTranslucent().withSpecular(),
|
||||
skinModelVertex, modelTranslucentPixel);
|
||||
skinModelVertex, modelTranslucentPixel, nullptr, nullptr);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withSpecular(),
|
||||
skinModelNormalMapVertex, modelTranslucentPixel);
|
||||
skinModelNormalMapVertex, modelTranslucentPixel, nullptr, nullptr);
|
||||
// Same thing but with Fade on
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withSkinned().withTranslucent().withFade(),
|
||||
skinModelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withFade(),
|
||||
skinModelNormalMapFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withSkinned().withTranslucent().withSpecular().withFade(),
|
||||
skinModelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withSpecular().withFade(),
|
||||
skinModelNormalMapFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter);
|
||||
|
||||
// Depth-only
|
||||
addPipeline(
|
||||
Key::Builder().withDepthOnly(),
|
||||
modelShadowVertex, modelShadowPixel);
|
||||
modelShadowVertex, modelShadowPixel, nullptr, nullptr);
|
||||
addPipeline(
|
||||
Key::Builder().withSkinned().withDepthOnly(),
|
||||
skinModelShadowVertex, modelShadowPixel);
|
||||
skinModelShadowVertex, modelShadowPixel, nullptr, nullptr);
|
||||
// Same thing but with Fade on
|
||||
addPipeline(
|
||||
Key::Builder().withDepthOnly().withFade(),
|
||||
modelShadowFadeVertex, modelShadowFadePixel, batchSetter, itemSetter);
|
||||
addPipeline(
|
||||
Key::Builder().withSkinned().withDepthOnly().withFade(),
|
||||
skinModelShadowFadeVertex, modelShadowFadePixel, batchSetter, itemSetter);
|
||||
}
|
||||
|
||||
void initForwardPipelines(render::ShapePlumber& plumber) {
|
||||
|
@ -288,7 +445,7 @@ void initForwardPipelines(render::ShapePlumber& plumber) {
|
|||
auto modelNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(forward_model_normal_specular_map_frag));
|
||||
|
||||
using Key = render::ShapeKey;
|
||||
auto addPipeline = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3);
|
||||
auto addPipeline = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3, nullptr, nullptr);
|
||||
// Opaques
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial(),
|
||||
|
@ -321,7 +478,8 @@ void initForwardPipelines(render::ShapePlumber& plumber) {
|
|||
}
|
||||
|
||||
void addPlumberPipeline(ShapePlumber& plumber,
|
||||
const ShapeKey& key, const gpu::ShaderPointer& vertex, const gpu::ShaderPointer& pixel) {
|
||||
const ShapeKey& key, const gpu::ShaderPointer& vertex, const gpu::ShaderPointer& pixel,
|
||||
const render::ShapePipeline::BatchSetter& extraBatchSetter, const render::ShapePipeline::ItemSetter& itemSetter) {
|
||||
// These key-values' pipelines are added by this functor in addition to the key passed
|
||||
assert(!key.isWireframe());
|
||||
assert(!key.isDepthBiased());
|
||||
|
@ -358,8 +516,18 @@ void addPlumberPipeline(ShapePlumber& plumber,
|
|||
state->setDepthBiasSlopeScale(1.0f);
|
||||
}
|
||||
|
||||
plumber.addPipeline(builder.build(), program, state,
|
||||
key.isTranslucent() ? &lightBatchSetter : &batchSetter);
|
||||
auto baseBatchSetter = key.isTranslucent() ? &lightBatchSetter : &batchSetter;
|
||||
render::ShapePipeline::BatchSetter finalBatchSetter;
|
||||
if (extraBatchSetter) {
|
||||
finalBatchSetter = [baseBatchSetter, extraBatchSetter](const ShapePipeline& pipeline, gpu::Batch& batch, render::Args* args) {
|
||||
baseBatchSetter(pipeline, batch, args);
|
||||
extraBatchSetter(pipeline, batch, args);
|
||||
};
|
||||
}
|
||||
else {
|
||||
finalBatchSetter = baseBatchSetter;
|
||||
}
|
||||
plumber.addPipeline(builder.build(), program, state, finalBatchSetter, itemSetter);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,12 @@
|
|||
#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;
|
||||
|
||||
void RenderShadowMap::run(const render::RenderContextPointer& renderContext,
|
||||
|
@ -46,6 +52,8 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext,
|
|||
const auto& fbo = shadow->framebuffer;
|
||||
|
||||
RenderArgs* args = renderContext->args;
|
||||
ShapeKey::Builder defaultKeyBuilder;
|
||||
|
||||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||
args->_batch = &batch;
|
||||
batch.enableStereo(false);
|
||||
|
@ -62,8 +70,8 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext,
|
|||
batch.setProjectionTransform(shadow->getProjection());
|
||||
batch.setViewTransform(shadow->getView(), false);
|
||||
|
||||
auto shadowPipeline = _shapePlumber->pickPipeline(args, ShapeKey());
|
||||
auto shadowSkinnedPipeline = _shapePlumber->pickPipeline(args, ShapeKey::Builder().withSkinned());
|
||||
auto shadowPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder);
|
||||
auto shadowSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned());
|
||||
|
||||
std::vector<ShapeKey> skinnedShapeKeys{};
|
||||
|
||||
|
@ -104,15 +112,29 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende
|
|||
auto modelPixel = gpu::Shader::createPixel(std::string(model_shadow_frag));
|
||||
gpu::ShaderPointer modelProgram = gpu::Shader::createProgram(modelVertex, modelPixel);
|
||||
shapePlumber->addPipeline(
|
||||
ShapeKey::Filter::Builder().withoutSkinned(),
|
||||
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(),
|
||||
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);
|
||||
}
|
||||
|
||||
const auto cachedMode = task.addJob<RenderShadowSetup>("ShadowSetup");
|
||||
|
|
|
@ -13,11 +13,13 @@
|
|||
#include <render/SceneTask.h>
|
||||
#include "LightStage.h"
|
||||
#include "BackgroundStage.h"
|
||||
#include <render/TransitionStage.h>
|
||||
#include "DeferredLightingEffect.h"
|
||||
|
||||
void UpdateSceneTask::build(JobModel& task, const render::Varying& input, render::Varying& output) {
|
||||
task.addJob<LightStageSetup>("LightStageSetup");
|
||||
task.addJob<BackgroundStageSetup>("BackgroundStageSetup");
|
||||
task.addJob<render::TransitionStageSetup>("TransitionStageSetup");
|
||||
|
||||
task.addJob<DefaultLightingSetup>("DefaultLightingSetup");
|
||||
|
||||
|
|
70
libraries/render-utils/src/model_fade.slf
Normal file
|
@ -0,0 +1,70 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
// model_fade.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Olivier Prat on 04/19/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 DeferredBufferWrite.slh@>
|
||||
|
||||
<@include model/Material.slh@>
|
||||
|
||||
<@include MaterialTextures.slh@>
|
||||
<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$>
|
||||
|
||||
<@include Fade.slh@>
|
||||
<$declareFadeFragment()$>
|
||||
|
||||
in vec4 _position;
|
||||
in vec4 _worldPosition;
|
||||
in vec3 _normal;
|
||||
in vec3 _color;
|
||||
in vec2 _texCoord0;
|
||||
in vec2 _texCoord1;
|
||||
|
||||
|
||||
void main(void) {
|
||||
vec3 fadeEmissive;
|
||||
FadeObjectParams fadeParams;
|
||||
|
||||
<$fetchFadeObjectParams(fadeParams)$>
|
||||
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
|
||||
|
||||
Material mat = getMaterial();
|
||||
int matKey = getMaterialKey(mat);
|
||||
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$>
|
||||
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$>
|
||||
|
||||
float opacity = 1.0;
|
||||
<$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
|
||||
<$discardTransparent(opacity)$>;
|
||||
|
||||
vec3 albedo = getMaterialAlbedo(mat);
|
||||
<$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
|
||||
albedo *= _color;
|
||||
|
||||
float roughness = getMaterialRoughness(mat);
|
||||
<$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>;
|
||||
|
||||
vec3 emissive = getMaterialEmissive(mat);
|
||||
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
|
||||
emissive += fadeEmissive;
|
||||
|
||||
float scattering = getMaterialScattering(mat);
|
||||
|
||||
packDeferredFragment(
|
||||
normalize(_normal.xyz),
|
||||
opacity,
|
||||
albedo,
|
||||
roughness,
|
||||
getMaterialMetallic(mat),
|
||||
emissive,
|
||||
occlusionTex,
|
||||
scattering);
|
||||
}
|
44
libraries/render-utils/src/model_fade.slv
Normal file
|
@ -0,0 +1,44 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
// model_fade.slv
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Olivier Prat on 04/24/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 gpu/Inputs.slh@>
|
||||
<@include gpu/Color.slh@>
|
||||
<@include gpu/Transform.slh@>
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
<@include MaterialTextures.slh@>
|
||||
<$declareMaterialTexMapArrayBuffer()$>
|
||||
|
||||
out float _alpha;
|
||||
out vec2 _texCoord0;
|
||||
out vec2 _texCoord1;
|
||||
out vec4 _position;
|
||||
out vec4 _worldPosition;
|
||||
out vec3 _normal;
|
||||
out vec3 _color;
|
||||
|
||||
void main(void) {
|
||||
_color = colorToLinearRGB(inColor.xyz);
|
||||
_alpha = inColor.w;
|
||||
|
||||
TexMapArray texMapArray = getTexMapArray();
|
||||
<$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord0)$>
|
||||
<$evalTexMapArrayTexcoord1(texMapArray, inTexCoord0, _texCoord1)$>
|
||||
|
||||
// standard transform
|
||||
TransformCamera cam = getTransformCamera();
|
||||
TransformObject obj = getTransformObject();
|
||||
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$>
|
||||
<$transformModelToWorldPos(obj, inPosition, _worldPosition)$>
|
||||
<$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$>
|
||||
}
|
54
libraries/render-utils/src/model_lightmap_fade.slf
Normal file
|
@ -0,0 +1,54 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// model_lightmap_fade.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Olivier Prat on 06/05/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 DeferredBufferWrite.slh@>
|
||||
|
||||
<@include model/Material.slh@>
|
||||
|
||||
<@include MaterialTextures.slh@>
|
||||
<$declareMaterialTextures(ALBEDO, ROUGHNESS)$>
|
||||
<$declareMaterialLightmap()$>
|
||||
|
||||
<@include Fade.slh@>
|
||||
<$declareFadeFragment()$>
|
||||
|
||||
in vec4 _position;
|
||||
in vec2 _texCoord0;
|
||||
in vec2 _texCoord1;
|
||||
in vec3 _normal;
|
||||
in vec3 _color;
|
||||
in vec4 _worldPosition;
|
||||
|
||||
void main(void) {
|
||||
vec3 fadeEmissive;
|
||||
FadeObjectParams fadeParams;
|
||||
|
||||
<$fetchFadeObjectParams(fadeParams)$>
|
||||
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
|
||||
|
||||
Material mat = getMaterial();
|
||||
int matKey = getMaterialKey(mat);
|
||||
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness)$>
|
||||
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$>
|
||||
|
||||
|
||||
packDeferredFragmentLightmap(
|
||||
normalize(_normal),
|
||||
evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
|
||||
getMaterialAlbedo(mat) * albedo.rgb * _color,
|
||||
getMaterialRoughness(mat) * roughness,
|
||||
getMaterialMetallic(mat),
|
||||
getMaterialFresnel(mat),
|
||||
lightmapVal+fadeEmissive);
|
||||
}
|
46
libraries/render-utils/src/model_lightmap_fade.slv
Normal file
|
@ -0,0 +1,46 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// model_lightmap_fade.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Olivier Prat on 06/05/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 gpu/Inputs.slh@>
|
||||
<@include gpu/Color.slh@>
|
||||
<@include gpu/Transform.slh@>
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
<@include MaterialTextures.slh@>
|
||||
<$declareMaterialTexMapArrayBuffer()$>
|
||||
|
||||
out vec4 _position;
|
||||
out vec2 _texCoord0;
|
||||
out vec2 _texCoord1;
|
||||
out vec3 _normal;
|
||||
out vec3 _color;
|
||||
out vec4 _worldPosition;
|
||||
|
||||
void main(void) {
|
||||
// pass along the color in linear space
|
||||
_color = colorToLinearRGB(inColor.xyz);
|
||||
|
||||
// and the texture coordinates
|
||||
TexMapArray texMapArray = getTexMapArray();
|
||||
<$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord0)$>
|
||||
<$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _texCoord1)$>
|
||||
|
||||
// standard transform
|
||||
TransformCamera cam = getTransformCamera();
|
||||
TransformObject obj = getTransformObject();
|
||||
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$>
|
||||
<$transformModelToWorldPos(obj, inPosition, _worldPosition)$>
|
||||
<$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$>
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// model_lightmap_normal_map_fade.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Olivier Prat on 06/05/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 DeferredBufferWrite.slh@>
|
||||
|
||||
<@include model/Material.slh@>
|
||||
|
||||
<@include MaterialTextures.slh@>
|
||||
<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL)$>
|
||||
<$declareMaterialLightmap()$>
|
||||
|
||||
<@include Fade.slh@>
|
||||
<$declareFadeFragment()$>
|
||||
|
||||
in vec4 _position;
|
||||
in vec2 _texCoord0;
|
||||
in vec2 _texCoord1;
|
||||
in vec3 _normal;
|
||||
in vec3 _tangent;
|
||||
in vec3 _color;
|
||||
in vec4 _worldPosition;
|
||||
|
||||
void main(void) {
|
||||
vec3 fadeEmissive;
|
||||
FadeObjectParams fadeParams;
|
||||
|
||||
<$fetchFadeObjectParams(fadeParams)$>
|
||||
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
|
||||
|
||||
Material mat = getMaterial();
|
||||
int matKey = getMaterialKey(mat);
|
||||
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, normalTexel)$>
|
||||
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$>
|
||||
|
||||
vec3 viewNormal;
|
||||
<$tangentToViewSpaceLOD(_position, normalTexel, _normal, _tangent, viewNormal)$>
|
||||
|
||||
packDeferredFragmentLightmap(
|
||||
normalize(viewNormal.xyz),
|
||||
evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
|
||||
getMaterialAlbedo(mat) * albedo.rgb * _color,
|
||||
getMaterialRoughness(mat),
|
||||
getMaterialMetallic(mat),
|
||||
getMaterialFresnel(mat),
|
||||
lightmapVal+fadeEmissive);
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// model_lightmap_normal_map_fade.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Olivier Prat on 06/05/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 gpu/Inputs.slh@>
|
||||
<@include gpu/Color.slh@>
|
||||
<@include gpu/Transform.slh@>
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
<@include MaterialTextures.slh@>
|
||||
<$declareMaterialTexMapArrayBuffer()$>
|
||||
|
||||
out vec4 _position;
|
||||
out vec2 _texCoord0;
|
||||
out vec2 _texCoord1;
|
||||
out vec3 _normal;
|
||||
out vec3 _tangent;
|
||||
out vec3 _color;
|
||||
out vec4 _worldPosition;
|
||||
|
||||
void main(void) {
|
||||
// pass along the color in linear space
|
||||
_color = colorToLinearRGB(inColor.xyz);
|
||||
|
||||
TexMapArray texMapArray = getTexMapArray();
|
||||
<$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord0)$>
|
||||
<$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _texCoord1)$>
|
||||
|
||||
// standard transform
|
||||
TransformCamera cam = getTransformCamera();
|
||||
TransformObject obj = getTransformObject();
|
||||
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$>
|
||||
<$transformModelToWorldPos(obj, inPosition, _worldPosition)$>
|
||||
<$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$>
|
||||
<$transformModelToWorldDir(cam, obj, inTangent.xyz, _tangent)$>
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// model_lightmap_normal_specular_map_fade.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Olivier Prat on 06/05/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 DeferredBufferWrite.slh@>
|
||||
|
||||
<@include model/Material.slh@>
|
||||
|
||||
<@include MaterialTextures.slh@>
|
||||
<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC)$>
|
||||
<$declareMaterialLightmap()$>
|
||||
|
||||
<@include Fade.slh@>
|
||||
<$declareFadeFragment()$>
|
||||
|
||||
in vec4 _position;
|
||||
in vec2 _texCoord0;
|
||||
in vec2 _texCoord1;
|
||||
in vec3 _normal;
|
||||
in vec3 _tangent;
|
||||
in vec3 _color;
|
||||
in vec4 _worldPosition;
|
||||
|
||||
void main(void) {
|
||||
vec3 fadeEmissive;
|
||||
FadeObjectParams fadeParams;
|
||||
|
||||
<$fetchFadeObjectParams(fadeParams)$>
|
||||
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
|
||||
|
||||
Material mat = getMaterial();
|
||||
int matKey = getMaterialKey(mat);
|
||||
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, normalTexel, metallicTex)$>
|
||||
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$>
|
||||
|
||||
vec3 viewNormal;
|
||||
<$tangentToViewSpaceLOD(_position, normalTexel, _normal, _tangent, viewNormal)$>
|
||||
|
||||
packDeferredFragmentLightmap(
|
||||
normalize(viewNormal.xyz),
|
||||
evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
|
||||
getMaterialAlbedo(mat) * albedo.rgb * _color,
|
||||
getMaterialRoughness(mat) * roughness,
|
||||
getMaterialMetallic(mat) * metallicTex,
|
||||
/*specular, // no use of */ getMaterialFresnel(mat),
|
||||
lightmapVal+fadeEmissive);
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// model_lightmap_specular_map_fade.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Olivier Prat on 06/05/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 DeferredBufferWrite.slh@>
|
||||
|
||||
<@include model/Material.slh@>
|
||||
|
||||
<@include MaterialTextures.slh@>
|
||||
<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC)$>
|
||||
<$declareMaterialLightmap()$>
|
||||
|
||||
<@include Fade.slh@>
|
||||
<$declareFadeFragment()$>
|
||||
|
||||
in vec4 _position;
|
||||
in vec2 _texCoord0;
|
||||
in vec2 _texCoord1;
|
||||
in vec3 _normal;
|
||||
in vec3 _color;
|
||||
in vec4 _worldPosition;
|
||||
|
||||
void main(void) {
|
||||
vec3 fadeEmissive;
|
||||
FadeObjectParams fadeParams;
|
||||
|
||||
<$fetchFadeObjectParams(fadeParams)$>
|
||||
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
|
||||
|
||||
Material mat = getMaterial();
|
||||
int matKey = getMaterialKey(mat);
|
||||
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, _SCRIBE_NULL, metallicTex)$>
|
||||
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$>
|
||||
|
||||
packDeferredFragmentLightmap(
|
||||
normalize(_normal),
|
||||
evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
|
||||
getMaterialAlbedo(mat) * albedo.rgb * _color,
|
||||
getMaterialRoughness(mat) * roughness,
|
||||
getMaterialMetallic(mat) * metallicTex,
|
||||
/*metallicTex, // no use of */getMaterialFresnel(mat),
|
||||
lightmapVal+fadeEmissive);
|
||||
}
|
74
libraries/render-utils/src/model_normal_map_fade.slf
Normal file
|
@ -0,0 +1,74 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// model_normal_map_fade.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Olivier Prat on 04/19/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 DeferredBufferWrite.slh@>
|
||||
|
||||
<@include model/Material.slh@>
|
||||
|
||||
<@include MaterialTextures.slh@>
|
||||
<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, _SCRIBE_NULL, EMISSIVE, OCCLUSION, SCATTERING)$>
|
||||
|
||||
<@include Fade.slh@>
|
||||
<$declareFadeFragment()$>
|
||||
|
||||
in vec4 _position;
|
||||
in vec4 _worldPosition;
|
||||
in vec2 _texCoord0;
|
||||
in vec2 _texCoord1;
|
||||
in vec3 _normal;
|
||||
in vec3 _tangent;
|
||||
in vec3 _color;
|
||||
|
||||
void main(void) {
|
||||
vec3 fadeEmissive;
|
||||
FadeObjectParams fadeParams;
|
||||
|
||||
<$fetchFadeObjectParams(fadeParams)$>
|
||||
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
|
||||
|
||||
Material mat = getMaterial();
|
||||
int matKey = getMaterialKey(mat);
|
||||
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, _SCRIBE_NULL, emissiveTex, scatteringTex)$>
|
||||
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$>
|
||||
|
||||
float opacity = 1.0;
|
||||
<$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
|
||||
<$discardTransparent(opacity)$>;
|
||||
|
||||
vec3 albedo = getMaterialAlbedo(mat);
|
||||
<$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
|
||||
albedo *= _color;
|
||||
|
||||
float roughness = getMaterialRoughness(mat);
|
||||
<$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>;
|
||||
|
||||
vec3 emissive = getMaterialEmissive(mat);
|
||||
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
|
||||
|
||||
vec3 viewNormal;
|
||||
<$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, viewNormal)$>
|
||||
|
||||
float scattering = getMaterialScattering(mat);
|
||||
<$evalMaterialScattering(scatteringTex, scattering, matKey, scattering)$>;
|
||||
|
||||
packDeferredFragment(
|
||||
viewNormal,
|
||||
opacity,
|
||||
albedo,
|
||||
roughness,
|
||||
getMaterialMetallic(mat),
|
||||
emissive+fadeEmissive,
|
||||
occlusionTex,
|
||||
scattering);
|
||||
}
|
48
libraries/render-utils/src/model_normal_map_fade.slv
Normal file
|
@ -0,0 +1,48 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// model_normal_map_fade.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Olivier Prat on 04/24/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 gpu/Inputs.slh@>
|
||||
<@include gpu/Color.slh@>
|
||||
<@include gpu/Transform.slh@>
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
<@include MaterialTextures.slh@>
|
||||
<$declareMaterialTexMapArrayBuffer()$>
|
||||
|
||||
out vec4 _position;
|
||||
out vec4 _worldPosition;
|
||||
out vec2 _texCoord0;
|
||||
out vec2 _texCoord1;
|
||||
out vec3 _normal;
|
||||
out vec3 _tangent;
|
||||
out vec3 _color;
|
||||
out float _alpha;
|
||||
|
||||
void main(void) {
|
||||
// pass along the color
|
||||
_color = colorToLinearRGB(inColor.rgb);
|
||||
_alpha = inColor.a;
|
||||
|
||||
TexMapArray texMapArray = getTexMapArray();
|
||||
<$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord0)$>
|
||||
<$evalTexMapArrayTexcoord1(texMapArray, inTexCoord0, _texCoord1)$>
|
||||
|
||||
// standard transform
|
||||
TransformCamera cam = getTransformCamera();
|
||||
TransformObject obj = getTransformObject();
|
||||
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$>
|
||||
<$transformModelToWorldPos(obj, inPosition, _worldPosition)$>
|
||||
<$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$>
|
||||
<$transformModelToWorldDir(cam, obj, inTangent.xyz, _tangent)$>
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// model_normal_specular_map_fade.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Olivier Prat on 06/05/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 DeferredBufferWrite.slh@>
|
||||
|
||||
<@include model/Material.slh@>
|
||||
|
||||
<@include MaterialTextures.slh@>
|
||||
<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION)$>
|
||||
|
||||
<@include Fade.slh@>
|
||||
<$declareFadeFragment()$>
|
||||
|
||||
in vec4 _position;
|
||||
in vec2 _texCoord0;
|
||||
in vec2 _texCoord1;
|
||||
in vec3 _normal;
|
||||
in vec3 _tangent;
|
||||
in vec3 _color;
|
||||
in vec4 _worldPosition;
|
||||
|
||||
void main(void) {
|
||||
vec3 fadeEmissive;
|
||||
FadeObjectParams fadeParams;
|
||||
|
||||
<$fetchFadeObjectParams(fadeParams)$>
|
||||
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
|
||||
|
||||
Material mat = getMaterial();
|
||||
int matKey = getMaterialKey(mat);
|
||||
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex)$>
|
||||
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$>
|
||||
|
||||
float opacity = 1.0;
|
||||
<$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>;
|
||||
<$discardTransparent(opacity)$>;
|
||||
|
||||
vec3 albedo = getMaterialAlbedo(mat);
|
||||
<$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
|
||||
albedo *= _color;
|
||||
|
||||
float roughness = getMaterialRoughness(mat);
|
||||
<$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>;
|
||||
|
||||
vec3 emissive = getMaterialEmissive(mat);
|
||||
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
|
||||
|
||||
vec3 viewNormal;
|
||||
<$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, viewNormal)$>
|
||||
|
||||
float metallic = getMaterialMetallic(mat);
|
||||
<$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
|
||||
|
||||
float scattering = getMaterialScattering(mat);
|
||||
|
||||
packDeferredFragment(
|
||||
normalize(viewNormal.xyz),
|
||||
opacity,
|
||||
albedo,
|
||||
roughness,
|
||||
metallic,
|
||||
emissive+fadeEmissive,
|
||||
occlusionTex,
|
||||
scattering);
|
||||
}
|
30
libraries/render-utils/src/model_shadow_fade.slf
Normal file
|
@ -0,0 +1,30 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// model_shadow_fade.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Olivier Prat on 06/05/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 Fade.slh@>
|
||||
<$declareFadeFragment()$>
|
||||
|
||||
layout(location = 0) out vec4 _fragColor;
|
||||
|
||||
in vec4 _worldPosition;
|
||||
|
||||
void main(void) {
|
||||
FadeObjectParams fadeParams;
|
||||
|
||||
<$fetchFadeObjectParams(fadeParams)$>
|
||||
applyFadeClip(fadeParams, _worldPosition.xyz);
|
||||
|
||||
// pass-through to set z-buffer
|
||||
_fragColor = vec4(1.0, 1.0, 1.0, 0.0);
|
||||
}
|
29
libraries/render-utils/src/model_shadow_fade.slv
Normal file
|
@ -0,0 +1,29 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// model_shadow_fade.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Olivier Prat on 06/045/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 gpu/Inputs.slh@>
|
||||
|
||||
<@include gpu/Transform.slh@>
|
||||
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
out vec4 _worldPosition;
|
||||
|
||||
void main(void) {
|
||||
// standard transform
|
||||
TransformCamera cam = getTransformCamera();
|
||||
TransformObject obj = getTransformObject();
|
||||
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
|
||||
<$transformModelToWorldPos(obj, inPosition, _worldPosition)$>
|
||||
}
|
72
libraries/render-utils/src/model_specular_map_fade.slf
Normal file
|
@ -0,0 +1,72 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// model_specular_map_fade.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Olivier Prat on 06/05/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 DeferredBufferWrite.slh@>
|
||||
|
||||
<@include model/Material.slh@>
|
||||
|
||||
<@include MaterialTextures.slh@>
|
||||
<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION)$>
|
||||
|
||||
<@include Fade.slh@>
|
||||
<$declareFadeFragment()$>
|
||||
|
||||
in vec4 _position;
|
||||
in vec2 _texCoord0;
|
||||
in vec2 _texCoord1;
|
||||
in vec3 _normal;
|
||||
in vec3 _color;
|
||||
in vec4 _worldPosition;
|
||||
|
||||
void main(void) {
|
||||
vec3 fadeEmissive;
|
||||
FadeObjectParams fadeParams;
|
||||
|
||||
<$fetchFadeObjectParams(fadeParams)$>
|
||||
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
|
||||
|
||||
Material mat = getMaterial();
|
||||
int matKey = getMaterialKey(mat);
|
||||
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex)$>
|
||||
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$>
|
||||
|
||||
float opacity = 1.0;
|
||||
<$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
|
||||
<$discardTransparent(opacity)$>;
|
||||
|
||||
vec3 albedo = getMaterialAlbedo(mat);
|
||||
<$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
|
||||
albedo *= _color;
|
||||
|
||||
float roughness = getMaterialRoughness(mat);
|
||||
<$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>;
|
||||
|
||||
vec3 emissive = getMaterialEmissive(mat);
|
||||
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
|
||||
|
||||
float metallic = getMaterialMetallic(mat);
|
||||
<$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
|
||||
|
||||
float scattering = getMaterialScattering(mat);
|
||||
|
||||
packDeferredFragment(
|
||||
normalize(_normal),
|
||||
opacity,
|
||||
albedo,
|
||||
roughness,
|
||||
metallic,
|
||||
emissive+fadeEmissive,
|
||||
occlusionTex,
|
||||
scattering);
|
||||
}
|
91
libraries/render-utils/src/model_translucent_fade.slf
Normal file
|
@ -0,0 +1,91 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// model_translucent_fade.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Olivier Prat on 06/05/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 model/Material.slh@>
|
||||
|
||||
<@include DeferredGlobalLight.slh@>
|
||||
|
||||
<$declareEvalGlobalLightingAlphaBlended()$>
|
||||
|
||||
<@include gpu/Transform.slh@>
|
||||
<$declareStandardCameraTransform()$>
|
||||
|
||||
<@include MaterialTextures.slh@>
|
||||
<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$>
|
||||
|
||||
<@include Fade.slh@>
|
||||
<$declareFadeFragment()$>
|
||||
|
||||
in vec2 _texCoord0;
|
||||
in vec2 _texCoord1;
|
||||
in vec4 _position;
|
||||
in vec3 _normal;
|
||||
in vec3 _color;
|
||||
in float _alpha;
|
||||
in vec4 _worldPosition;
|
||||
|
||||
out vec4 _fragColor;
|
||||
|
||||
void main(void) {
|
||||
vec3 fadeEmissive;
|
||||
FadeObjectParams fadeParams;
|
||||
|
||||
<$fetchFadeObjectParams(fadeParams)$>
|
||||
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
|
||||
|
||||
Material mat = getMaterial();
|
||||
int matKey = getMaterialKey(mat);
|
||||
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$>
|
||||
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$>
|
||||
|
||||
float opacity = getMaterialOpacity(mat) * _alpha;
|
||||
<$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
|
||||
|
||||
vec3 albedo = getMaterialAlbedo(mat);
|
||||
<$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
|
||||
albedo *= _color;
|
||||
|
||||
float roughness = getMaterialRoughness(mat);
|
||||
<$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>;
|
||||
|
||||
float metallic = getMaterialMetallic(mat);
|
||||
vec3 fresnel = vec3(0.03); // Default Di-electric fresnel value
|
||||
if (metallic <= 0.5) {
|
||||
metallic = 0.0;
|
||||
} else {
|
||||
fresnel = albedo;
|
||||
metallic = 1.0;
|
||||
}
|
||||
|
||||
vec3 emissive = getMaterialEmissive(mat);
|
||||
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
|
||||
|
||||
vec3 fragPosition = _position.xyz;
|
||||
vec3 fragNormal = normalize(_normal);
|
||||
|
||||
TransformCamera cam = getTransformCamera();
|
||||
|
||||
_fragColor = vec4(evalGlobalLightingAlphaBlended(
|
||||
cam._viewInverse,
|
||||
1.0,
|
||||
occlusionTex,
|
||||
fragPosition,
|
||||
fragNormal,
|
||||
albedo,
|
||||
fresnel,
|
||||
metallic,
|
||||
emissive+fadeEmissive,
|
||||
roughness, opacity),
|
||||
opacity);
|
||||
}
|
50
libraries/render-utils/src/model_translucent_unlit_fade.slf
Normal file
|
@ -0,0 +1,50 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// model_translucent_unlit_fade.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Olivier Prat on 06/05/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 model/Material.slh@>
|
||||
|
||||
<@include MaterialTextures.slh@>
|
||||
<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$>
|
||||
<@include LightingModel.slh@>
|
||||
|
||||
<@include Fade.slh@>
|
||||
<$declareFadeFragment()$>
|
||||
|
||||
in vec2 _texCoord0;
|
||||
in vec3 _color;
|
||||
in float _alpha;
|
||||
in vec4 _worldPosition;
|
||||
|
||||
out vec4 _fragColor;
|
||||
|
||||
void main(void) {
|
||||
vec3 fadeEmissive;
|
||||
FadeObjectParams fadeParams;
|
||||
|
||||
<$fetchFadeObjectParams(fadeParams)$>
|
||||
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
|
||||
|
||||
Material mat = getMaterial();
|
||||
int matKey = getMaterialKey(mat);
|
||||
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$>
|
||||
|
||||
float opacity = getMaterialOpacity(mat) * _alpha;
|
||||
<$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
|
||||
|
||||
vec3 albedo = getMaterialAlbedo(mat);
|
||||
<$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
|
||||
albedo *= _color;
|
||||
albedo += fadeEmissive;
|
||||
_fragColor = vec4(albedo * isUnlitEnabled(), opacity);
|
||||
}
|
54
libraries/render-utils/src/model_unlit_fade.slf
Normal file
|
@ -0,0 +1,54 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// model_unlit_fade.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Olivier Prat on 06/05/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 DeferredBufferWrite.slh@>
|
||||
<@include LightingModel.slh@>
|
||||
<@include model/Material.slh@>
|
||||
|
||||
<@include Fade.slh@>
|
||||
<$declareFadeFragment()$>
|
||||
|
||||
<@include MaterialTextures.slh@>
|
||||
<$declareMaterialTextures(ALBEDO)$>
|
||||
|
||||
in vec2 _texCoord0;
|
||||
in vec3 _normal;
|
||||
in vec3 _color;
|
||||
in float _alpha;
|
||||
in vec4 _worldPosition;
|
||||
|
||||
void main(void) {
|
||||
vec3 fadeEmissive;
|
||||
FadeObjectParams fadeParams;
|
||||
|
||||
<$fetchFadeObjectParams(fadeParams)$>
|
||||
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
|
||||
|
||||
Material mat = getMaterial();
|
||||
int matKey = getMaterialKey(mat);
|
||||
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$>
|
||||
|
||||
float opacity = 1.0;
|
||||
<$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
|
||||
<$discardTransparent(opacity)$>;
|
||||
|
||||
vec3 albedo = getMaterialAlbedo(mat);
|
||||
<$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
|
||||
albedo *= _color;
|
||||
albedo += fadeEmissive;
|
||||
packDeferredFragmentUnlit(
|
||||
normalize(_normal),
|
||||
opacity,
|
||||
albedo * isUnlitEnabled());
|
||||
}
|
101
libraries/render-utils/src/simple_fade.slf
Normal file
|
@ -0,0 +1,101 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// simple_fade.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Olivier Prat on 06/05/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 DeferredBufferWrite.slh@>
|
||||
<@include model/Material.slh@>
|
||||
|
||||
<@include Fade.slh@>
|
||||
<$declareFadeFragmentInstanced()$>
|
||||
|
||||
// the interpolated normal
|
||||
in vec3 _normal;
|
||||
in vec3 _modelNormal;
|
||||
in vec4 _color;
|
||||
in vec2 _texCoord0;
|
||||
in vec4 _position;
|
||||
in vec4 _worldPosition;
|
||||
|
||||
//PROCEDURAL_COMMON_BLOCK
|
||||
|
||||
#line 1001
|
||||
//PROCEDURAL_BLOCK
|
||||
|
||||
#line 2030
|
||||
void main(void) {
|
||||
vec3 fadeEmissive;
|
||||
FadeObjectParams fadeParams;
|
||||
|
||||
<$fetchFadeObjectParamsInstanced(fadeParams)$>
|
||||
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
|
||||
|
||||
Material material = getMaterial();
|
||||
vec3 normal = normalize(_normal.xyz);
|
||||
vec3 diffuse = _color.rgb;
|
||||
vec3 specular = DEFAULT_SPECULAR;
|
||||
float shininess = DEFAULT_SHININESS;
|
||||
float emissiveAmount = 0.0;
|
||||
|
||||
#ifdef PROCEDURAL
|
||||
|
||||
#ifdef PROCEDURAL_V1
|
||||
specular = getProceduralColor().rgb;
|
||||
// Procedural Shaders are expected to be Gamma corrected so let's bring back the RGB in linear space for the rest of the pipeline
|
||||
//specular = pow(specular, vec3(2.2));
|
||||
emissiveAmount = 1.0;
|
||||
#else
|
||||
emissiveAmount = getProceduralColors(diffuse, specular, shininess);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
const float ALPHA_THRESHOLD = 0.999;
|
||||
if (_color.a < ALPHA_THRESHOLD) {
|
||||
if (emissiveAmount > 0.0) {
|
||||
packDeferredFragmentTranslucent(
|
||||
normal,
|
||||
_color.a,
|
||||
specular+fadeEmissive,
|
||||
DEFAULT_FRESNEL,
|
||||
DEFAULT_ROUGHNESS);
|
||||
} else {
|
||||
packDeferredFragmentTranslucent(
|
||||
normal,
|
||||
_color.a,
|
||||
diffuse+fadeEmissive,
|
||||
DEFAULT_FRESNEL,
|
||||
DEFAULT_ROUGHNESS);
|
||||
}
|
||||
} else {
|
||||
if (emissiveAmount > 0.0) {
|
||||
packDeferredFragmentLightmap(
|
||||
normal,
|
||||
1.0,
|
||||
diffuse+fadeEmissive,
|
||||
max(0, 1.0 - shininess / 128.0),
|
||||
DEFAULT_METALLIC,
|
||||
specular,
|
||||
specular);
|
||||
} else {
|
||||
packDeferredFragment(
|
||||
normal,
|
||||
1.0,
|
||||
diffuse,
|
||||
max(0, 1.0 - shininess / 128.0),
|
||||
length(specular),
|
||||
DEFAULT_EMISSIVE+fadeEmissive,
|
||||
DEFAULT_OCCLUSION,
|
||||
DEFAULT_SCATTERING);
|
||||
}
|
||||
}
|
||||
}
|
44
libraries/render-utils/src/simple_fade.slv
Normal file
|
@ -0,0 +1,44 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// simple_fade.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Olivier Prat on 06/04/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 gpu/Inputs.slh@>
|
||||
<@include gpu/Color.slh@>
|
||||
<@include gpu/Transform.slh@>
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
<@include Fade.slh@>
|
||||
<$declareFadeVertexInstanced()$>
|
||||
|
||||
// the interpolated normal
|
||||
out vec3 _normal;
|
||||
out vec3 _modelNormal;
|
||||
out vec4 _color;
|
||||
out vec2 _texCoord0;
|
||||
out vec4 _position;
|
||||
out vec4 _worldPosition;
|
||||
|
||||
void main(void) {
|
||||
_color = colorToLinearRGBA(inColor);
|
||||
_texCoord0 = inTexCoord0.st;
|
||||
_position = inPosition;
|
||||
_modelNormal = inNormal.xyz;
|
||||
|
||||
// standard transform
|
||||
TransformCamera cam = getTransformCamera();
|
||||
TransformObject obj = getTransformObject();
|
||||
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
|
||||
<$transformModelToWorldPos(obj, inPosition, _worldPosition)$>
|
||||
<$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$>
|
||||
<$passThroughFadeObjectParams()$>
|
||||
}
|
66
libraries/render-utils/src/simple_textured_fade.slf
Normal file
|
@ -0,0 +1,66 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// simple_textured_fade.slf
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Olivier Prat on 06/05/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 gpu/Color.slh@>
|
||||
<@include DeferredBufferWrite.slh@>
|
||||
<@include model/Material.slh@>
|
||||
|
||||
<@include Fade.slh@>
|
||||
|
||||
// the albedo texture
|
||||
uniform sampler2D originalTexture;
|
||||
|
||||
// the interpolated normal
|
||||
in vec3 _normal;
|
||||
in vec4 _color;
|
||||
in vec2 _texCoord0;
|
||||
in vec4 _worldPosition;
|
||||
|
||||
// Declare after all samplers to prevent sampler location mix up with originalTexture
|
||||
<$declareFadeFragmentInstanced()$>
|
||||
|
||||
void main(void) {
|
||||
vec3 fadeEmissive;
|
||||
FadeObjectParams fadeParams;
|
||||
|
||||
<$fetchFadeObjectParamsInstanced(fadeParams)$>
|
||||
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
|
||||
|
||||
vec4 texel = texture(originalTexture, _texCoord0);
|
||||
float colorAlpha = _color.a;
|
||||
if (_color.a <= 0.0) {
|
||||
texel = colorToLinearRGBA(texel);
|
||||
colorAlpha = -_color.a;
|
||||
}
|
||||
|
||||
const float ALPHA_THRESHOLD = 0.999;
|
||||
if (colorAlpha * texel.a < ALPHA_THRESHOLD) {
|
||||
packDeferredFragmentTranslucent(
|
||||
normalize(_normal),
|
||||
colorAlpha * texel.a,
|
||||
_color.rgb * texel.rgb + fadeEmissive,
|
||||
DEFAULT_FRESNEL,
|
||||
DEFAULT_ROUGHNESS);
|
||||
} else {
|
||||
packDeferredFragment(
|
||||
normalize(_normal),
|
||||
1.0,
|
||||
_color.rgb * texel.rgb,
|
||||
DEFAULT_ROUGHNESS,
|
||||
DEFAULT_METALLIC,
|
||||
DEFAULT_EMISSIVE + fadeEmissive,
|
||||
DEFAULT_OCCLUSION,
|
||||
DEFAULT_SCATTERING);
|
||||
}
|
||||
}
|
60
libraries/render-utils/src/simple_textured_unlit_fade.slf
Normal file
|
@ -0,0 +1,60 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// simple_textured_unlit_fade.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Olivier Prat on 06/05/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 gpu/Color.slh@>
|
||||
<@include DeferredBufferWrite.slh@>
|
||||
|
||||
<@include Fade.slh@>
|
||||
|
||||
// the albedo texture
|
||||
uniform sampler2D originalTexture;
|
||||
|
||||
// the interpolated normal
|
||||
in vec3 _normal;
|
||||
in vec4 _color;
|
||||
in vec2 _texCoord0;
|
||||
in vec4 _worldPosition;
|
||||
|
||||
// Declare after all samplers to prevent sampler location mix up with originalTexture
|
||||
<$declareFadeFragmentInstanced()$>
|
||||
|
||||
void main(void) {
|
||||
vec3 fadeEmissive;
|
||||
FadeObjectParams fadeParams;
|
||||
|
||||
<$fetchFadeObjectParamsInstanced(fadeParams)$>
|
||||
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
|
||||
|
||||
vec4 texel = texture(originalTexture, _texCoord0.st);
|
||||
float colorAlpha = _color.a;
|
||||
if (_color.a <= 0.0) {
|
||||
texel = colorToLinearRGBA(texel);
|
||||
colorAlpha = -_color.a;
|
||||
}
|
||||
|
||||
const float ALPHA_THRESHOLD = 0.999;
|
||||
if (colorAlpha * texel.a < ALPHA_THRESHOLD) {
|
||||
packDeferredFragmentTranslucent(
|
||||
normalize(_normal),
|
||||
colorAlpha * texel.a,
|
||||
_color.rgb * texel.rgb+fadeEmissive,
|
||||
DEFAULT_FRESNEL,
|
||||
DEFAULT_ROUGHNESS);
|
||||
} else {
|
||||
packDeferredFragmentUnlit(
|
||||
normalize(_normal),
|
||||
1.0,
|
||||
_color.rgb * texel.rgb+fadeEmissive);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// simple_transparent_textured_fade.slf
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Olivier Prat on 06/05/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 gpu/Color.slh@>
|
||||
|
||||
<@include DeferredBufferWrite.slh@>
|
||||
<@include DeferredGlobalLight.slh@>
|
||||
<$declareEvalGlobalLightingAlphaBlended()$>
|
||||
|
||||
<@include gpu/Transform.slh@>
|
||||
<$declareStandardCameraTransform()$>
|
||||
|
||||
<@include Fade.slh@>
|
||||
|
||||
// the albedo texture
|
||||
uniform sampler2D originalTexture;
|
||||
|
||||
// the interpolated normal
|
||||
in vec4 _position;
|
||||
in vec3 _normal;
|
||||
in vec4 _color;
|
||||
in vec2 _texCoord0;
|
||||
in vec4 _worldPosition;
|
||||
|
||||
// Declare after all samplers to prevent sampler location mix up with originalTexture
|
||||
<$declareFadeFragmentInstanced()$>
|
||||
|
||||
void main(void) {
|
||||
vec3 fadeEmissive;
|
||||
FadeObjectParams fadeParams;
|
||||
|
||||
<$fetchFadeObjectParamsInstanced(fadeParams)$>
|
||||
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
|
||||
|
||||
vec4 texel = texture(originalTexture, _texCoord0.st);
|
||||
float opacity = _color.a;
|
||||
if (_color.a <= 0.0) {
|
||||
texel = colorToLinearRGBA(texel);
|
||||
opacity = -_color.a;
|
||||
}
|
||||
opacity *= texel.a;
|
||||
vec3 albedo = _color.rgb * texel.rgb;
|
||||
|
||||
vec3 fragPosition = _position.xyz;
|
||||
vec3 fragNormal = normalize(_normal);
|
||||
|
||||
TransformCamera cam = getTransformCamera();
|
||||
|
||||
_fragColor0 = vec4(evalGlobalLightingAlphaBlended(
|
||||
cam._viewInverse,
|
||||
1.0,
|
||||
1.0,
|
||||
fragPosition,
|
||||
fragNormal,
|
||||
albedo,
|
||||
DEFAULT_FRESNEL,
|
||||
0.0f,
|
||||
fadeEmissive,
|
||||
DEFAULT_ROUGHNESS,
|
||||
opacity),
|
||||
opacity);
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// simple_transparent_textured_unlit_fade.slf
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Olivier Prat on 06/05/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 gpu/Color.slh@>
|
||||
|
||||
<@include Fade.slh@>
|
||||
|
||||
// the albedo texture
|
||||
uniform sampler2D originalTexture;
|
||||
|
||||
// the interpolated normal
|
||||
in vec3 _normal;
|
||||
in vec4 _color;
|
||||
in vec2 _texCoord0;
|
||||
in vec4 _worldPosition;
|
||||
|
||||
layout(location = 0) out vec4 _fragColor0;
|
||||
|
||||
// Declare after all samplers to prevent sampler location mix up with originalTexture
|
||||
<$declareFadeFragmentInstanced()$>
|
||||
|
||||
void main(void) {
|
||||
vec3 fadeEmissive;
|
||||
FadeObjectParams fadeParams;
|
||||
|
||||
<$fetchFadeObjectParamsInstanced(fadeParams)$>
|
||||
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
|
||||
|
||||
vec4 texel = texture(originalTexture, _texCoord0.st);
|
||||
float colorAlpha = _color.a;
|
||||
if (_color.a <= 0.0) {
|
||||
texel = colorToLinearRGBA(texel);
|
||||
colorAlpha = -_color.a;
|
||||
}
|
||||
_fragColor0 = vec4(_color.rgb * texel.rgb+fadeEmissive, colorAlpha * texel.a);
|
||||
}
|
53
libraries/render-utils/src/skin_model_fade.slv
Normal file
|
@ -0,0 +1,53 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// skin_model_fade.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Olivier Prat on 06/045/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 gpu/Inputs.slh@>
|
||||
<@include gpu/Color.slh@>
|
||||
<@include gpu/Transform.slh@>
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
<@include Skinning.slh@>
|
||||
|
||||
<@include MaterialTextures.slh@>
|
||||
<$declareMaterialTexMapArrayBuffer()$>
|
||||
|
||||
out vec4 _position;
|
||||
out vec2 _texCoord0;
|
||||
out vec2 _texCoord1;
|
||||
out vec3 _normal;
|
||||
out vec3 _color;
|
||||
out float _alpha;
|
||||
out vec4 _worldPosition;
|
||||
|
||||
void main(void) {
|
||||
vec4 position = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0);
|
||||
|
||||
skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal);
|
||||
|
||||
// pass along the color
|
||||
_color = colorToLinearRGB(inColor.rgb);
|
||||
_alpha = inColor.a;
|
||||
|
||||
TexMapArray texMapArray = getTexMapArray();
|
||||
<$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord0)$>
|
||||
<$evalTexMapArrayTexcoord1(texMapArray, inTexCoord0, _texCoord1)$>
|
||||
|
||||
// standard transform
|
||||
TransformCamera cam = getTransformCamera();
|
||||
TransformObject obj = getTransformObject();
|
||||
<$transformModelToEyeAndClipPos(cam, obj, position, _position, gl_Position)$>
|
||||
<$transformModelToWorldPos(obj, position, _worldPosition)$>
|
||||
<$transformModelToWorldDir(cam, obj, interpolatedNormal.xyz, _normal.xyz)$>
|
||||
}
|
62
libraries/render-utils/src/skin_model_normal_map_fade.slv
Normal file
|
@ -0,0 +1,62 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// skin_model_normal_map_fade.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Olivier Prat on 06/045/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 gpu/Inputs.slh@>
|
||||
<@include gpu/Color.slh@>
|
||||
<@include gpu/Transform.slh@>
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
<@include Skinning.slh@>
|
||||
|
||||
<@include MaterialTextures.slh@>
|
||||
<$declareMaterialTexMapArrayBuffer()$>
|
||||
|
||||
out vec4 _position;
|
||||
out vec2 _texCoord0;
|
||||
out vec2 _texCoord1;
|
||||
out vec3 _normal;
|
||||
out vec3 _tangent;
|
||||
out vec3 _color;
|
||||
out float _alpha;
|
||||
out vec4 _worldPosition;
|
||||
|
||||
void main(void) {
|
||||
vec4 position = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz);
|
||||
|
||||
// pass along the color
|
||||
_color = colorToLinearRGB(inColor.rgb);
|
||||
_alpha = inColor.a;
|
||||
|
||||
TexMapArray texMapArray = getTexMapArray();
|
||||
<$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord0)$>
|
||||
<$evalTexMapArrayTexcoord1(texMapArray, inTexCoord0, _texCoord1)$>
|
||||
|
||||
interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);
|
||||
interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);
|
||||
|
||||
// standard transform
|
||||
TransformCamera cam = getTransformCamera();
|
||||
TransformObject obj = getTransformObject();
|
||||
<$transformModelToEyeAndClipPos(cam, obj, position, _position, gl_Position)$>
|
||||
<$transformModelToWorldPos(obj, position, _worldPosition)$>
|
||||
<$transformModelToWorldDir(cam, obj, interpolatedNormal.xyz, interpolatedNormal.xyz)$>
|
||||
<$transformModelToWorldDir(cam, obj, interpolatedTangent.xyz, interpolatedTangent.xyz)$>
|
||||
|
||||
_normal = interpolatedNormal.xyz;
|
||||
_tangent = interpolatedTangent.xyz;
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// model_shadow.frag
|
||||
// skin_model_shadow.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 3/24/14.
|
||||
|
|
30
libraries/render-utils/src/skin_model_shadow_fade.slf
Normal file
|
@ -0,0 +1,30 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// skin_model_shadow_fade.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Olivier Prat on 06/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 Fade.slh@>
|
||||
<$declareFadeFragment()$>
|
||||
|
||||
in vec4 _worldPosition;
|
||||
|
||||
layout(location = 0) out vec4 _fragColor;
|
||||
|
||||
void main(void) {
|
||||
FadeObjectParams fadeParams;
|
||||
|
||||
<$fetchFadeObjectParams(fadeParams)$>
|
||||
applyFadeClip(fadeParams, _worldPosition.xyz);
|
||||
|
||||
// pass-through to set z-buffer
|
||||
_fragColor = vec4(1.0, 1.0, 1.0, 0.0);
|
||||
}
|
32
libraries/render-utils/src/skin_model_shadow_fade.slv
Normal file
|
@ -0,0 +1,32 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// skin_model_shadow_fade.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Olivier Prat on 06/045/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 gpu/Inputs.slh@>
|
||||
<@include gpu/Transform.slh@>
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
<@include Skinning.slh@>
|
||||
|
||||
out vec4 _worldPosition;
|
||||
|
||||
void main(void) {
|
||||
vec4 position = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position);
|
||||
|
||||
// standard transform
|
||||
TransformCamera cam = getTransformCamera();
|
||||
TransformObject obj = getTransformObject();
|
||||
<$transformModelToClipPos(cam, obj, position, gl_Position)$>
|
||||
<$transformModelToWorldPos(obj, position, _worldPosition)$>
|
||||
}
|
|
@ -119,9 +119,12 @@ namespace render {
|
|||
DebugFlags _debugFlags { RENDER_DEBUG_NONE };
|
||||
gpu::Batch* _batch = nullptr;
|
||||
|
||||
uint32_t _globalShapeKey { 0 };
|
||||
uint32_t _globalShapeKey{ 0 };
|
||||
uint32_t _itemShapeKey{ 0 };
|
||||
bool _enableTexturing { true };
|
||||
|
||||
bool _enableFade{ false };
|
||||
|
||||
RenderDetails _details;
|
||||
render::ScenePointer _scene;
|
||||
int8_t _cameraMode { -1 };
|
||||
|
|
|
@ -42,6 +42,7 @@ void render::renderItems(const RenderContextPointer& renderContext, const ItemBo
|
|||
void renderShape(RenderArgs* args, const ShapePlumberPointer& shapeContext, const Item& item, const ShapeKey& globalKey) {
|
||||
assert(item.getKey().isShape());
|
||||
auto key = item.getShapeKey() | globalKey;
|
||||
args->_itemShapeKey = key._flags.to_ulong();
|
||||
if (key.isValid() && !key.hasOwnPipeline()) {
|
||||
args->_shapePipeline = shapeContext->pickPipeline(args, key);
|
||||
if (args->_shapePipeline) {
|
||||
|
@ -54,6 +55,7 @@ void renderShape(RenderArgs* args, const ShapePlumberPointer& shapeContext, cons
|
|||
} else {
|
||||
qCDebug(renderlogging) << "Item could not be rendered with invalid key" << key;
|
||||
}
|
||||
args->_itemShapeKey = 0;
|
||||
}
|
||||
|
||||
void render::renderShapes(const RenderContextPointer& renderContext,
|
||||
|
@ -85,10 +87,10 @@ void render::renderStateSortShapes(const RenderContextPointer& renderContext,
|
|||
using SortedShapes = std::unordered_map<render::ShapeKey, std::vector<Item>, render::ShapeKey::Hash, render::ShapeKey::KeyEqual>;
|
||||
SortedPipelines sortedPipelines;
|
||||
SortedShapes sortedShapes;
|
||||
std::vector<Item> ownPipelineBucket;
|
||||
std::vector< std::tuple<Item,ShapeKey> > ownPipelineBucket;
|
||||
|
||||
for (auto i = 0; i < numItemsToDraw; ++i) {
|
||||
auto item = scene->getItem(inItems[i].id);
|
||||
auto& item = scene->getItem(inItems[i].id);
|
||||
|
||||
{
|
||||
assert(item.getKey().isShape());
|
||||
|
@ -100,7 +102,7 @@ void render::renderStateSortShapes(const RenderContextPointer& renderContext,
|
|||
}
|
||||
bucket.push_back(item);
|
||||
} else if (key.hasOwnPipeline()) {
|
||||
ownPipelineBucket.push_back(item);
|
||||
ownPipelineBucket.push_back( std::make_tuple(item, key) );
|
||||
} else {
|
||||
qCDebug(renderlogging) << "Item could not be rendered with invalid key" << key;
|
||||
}
|
||||
|
@ -114,15 +116,19 @@ void render::renderStateSortShapes(const RenderContextPointer& renderContext,
|
|||
if (!args->_shapePipeline) {
|
||||
continue;
|
||||
}
|
||||
args->_itemShapeKey = pipelineKey._flags.to_ulong();
|
||||
for (auto& item : bucket) {
|
||||
args->_shapePipeline->prepareShapeItem(args, pipelineKey, item);
|
||||
item.render(args);
|
||||
}
|
||||
}
|
||||
args->_shapePipeline = nullptr;
|
||||
for (auto& item : ownPipelineBucket) {
|
||||
for (auto& itemAndKey : ownPipelineBucket) {
|
||||
auto& item = std::get<0>(itemAndKey);
|
||||
args->_itemShapeKey = std::get<1>(itemAndKey)._flags.to_ulong();
|
||||
item.render(args);
|
||||
}
|
||||
args->_itemShapeKey = 0;
|
||||
}
|
||||
|
||||
void DrawLight::run(const RenderContextPointer& renderContext, const ItemBounds& inLights) {
|
||||
|
|